Форум: "KOL";
Текущий архив: 2005.10.09;
Скачать: [xml.tar.bz2];
ВнизОбъект в DLL и использование его методов в главном модуле Найти похожие ветки
← →
dimaxx © (2005-01-22 15:11) [0]Сабж. Нужно написать библиотеку, в которой по вызову функции в главный модуль возвращается указатель на созданный объект. Как написать библиотеку - я знаю, но я не знаю как мне согласовать объявление объекта так, чтобы его методы можно было бы вызвать из главного модуля программы используя полученный указатель?
Например, есть библиотека Calc32.dll. В ней одна внешняя функция:function CreateCalcObject: PCalcObj; stdcall;
Объект в библиотеке записан примерно так:type
PCalcObj = ^TCalcObj;
TCalcObj = object(TObj)
private
FTemp: integer;
protected
destructor Destroy; virtual;
public
function Execute(const Show: boolean): integer;
procedure Prepare;
end;
Далее идет реализация. Количество процедур/функций в разделе public может различаться и они могут быть с параметрами и без (это взято для примера).
В главном модуле пишу:function CreateCalcObject: PCalcObj; external "Calc32.dll" name "CreateCalcObject";
var Calc: PCalcObj;
I: integer;
...
...
Calc:=CreateCalcObject;
Calc.Prepare;
I:=Calc.Execute(False);
Calc.Free;
...
Естественно, возникает ошибка, что неопределенPCalcObj
, неизвестные методыPrepare
,Execute
иFree
. Как мне его объявить в главном модуле, если обявление и реализация находятся в DLL?
Может, кто подскажет как реализовать это по-другому? Мне нужен вариант реализации, при котором я мог бы не городить десяток внешних функций библиотеки (которые записаны в объекте), а использовать всего одну для создания указателя и потом через этот указатель работать со всеми функциями и, возможно, свойствами.
← →
thaddy (2005-01-22 15:57) [1]Is it possible to declare them like the MakeMethod function does?,
So procedure CalcSomething(Dummy:pointer;WhateverYourParametersAre:Whatevertype);stdcall
This works for C++ classes anyway and should work for KOL objects too. Pass the value of ebx on call as dummy if it doesn't work
← →
SPeller © (2005-01-22 19:07) [2]Делаешь всё как ты и делал, только подключаешь к главной программе объект с точно таким же объявлением, но пустыми методами. Главное помни что порядок полей и методов и их количество важно. Главная программа будет думать что работает с объектом, который описан в ней, а на самом деле будет оперировать с объектом, указатель на который ты вернул из своей dll.
← →
Владимир Кладов (2005-01-22 19:35) [3]Ни в коем случа ТАК делать НЕ надо. Интерфейс с DLL должен быть не через объект, а через набор примитивных процедур. Или вы напоретесь. Не сразу, так через полгода. Или ваши пользователю напорются.
← →
thaddy (2005-01-22 19:45) [4]So assignment in interface section like?
Type
Tmyprocedure = procedure (Dummy:pointer;whaterver:whateve);
var
Myprocedure :TMyprocedure = TCalcClass.whatever(whatever:whatever);
??
I am going to try to get it working, but you probably have :)
← →
dimaxx © (2005-01-22 22:04) [5]2 Владимир Кладов: Не надо делать так как я написал, или так, как SPeller ответил? Можно на моем примере как надо делать? Я просто не сталкивался с этим, поэтому мне интересен способ решения этой задачи.
Интерфейс с DLL должен быть не через объект, а через набор примитивных процедур. Или вы напоретесь. Не сразу, так через полгода. Или ваши пользователю напорются.
То есть такая реализация невозможна? Нужно обязательно объявлять каждую внешнюю функцию явно, а не через объект? На что я (или пользователи) могу напороться?
2 thaddy: Thanks, but TCalcClass declared only in the dll-unit.
← →
SPeller © (2005-01-22 22:30) [6]Либо можно использовать структуры, в которых содержатся указатели на простые процедуры, и возвращать основной программе указатель на экземпляр такой записи. Правда, этот тот же object :) Плагины для винампа работают так. Поэтому что же мешает заменить запись на обхект, если это по сути то же самое? Главное ни от чего не наследовать этот объект, чтобы потом мороки небыло.
← →
Владимир Кладов (2005-01-23 08:44) [7]Если в KOL что-то изменится, или проект будет перекомпилирован с другой опцией, или будет использован другой Delphi для компиляции dll, чем программы, то вот тогда и напоретесь. Получается, что dll и exe должны идти вместе и не отрываться друг от друга. И программист должен постоянно перекомпилировать их вместе. А если они выкладываются на интернет отдельно, и компилируются отдельно, то так делать точно не надо. Неужто сложно использовать только простые процедуры и PChar для передачи параметров в dll.
← →
SPeller © (2005-01-23 11:15) [8]Если объект ни от чего не наследовать, то вероятность получения проблем минимальна. Объекты "устарели", поэтому я думаю что вряд ли с ними что-то будет делаться. Однако есть шанс получить ошибку если на разных компиляторах будет скомпилировано. Тогда лучше использовать записи.
← →
dimaxx © (2005-01-23 22:18) [9]C записями попробую. Тем более, что я уже подумывал так сделать. Только никак не мог найти в своей копилке портированный хидер для написания плагинов. Сегодня пороюсь тщательнее - может, найду... Был он точно...
PS: Ха, конечно был! Я же переводил на KOL использование in и out плагинов от винампа в своих целях...
← →
dimaxx © (2005-01-26 21:14) [10]Чет не могу понять, к в библиотеке присвоить значению записи ссылу на метод объекта. Подскажите как правильно. Сначала вроде присвоил (есть адреса и они действительно в библиотеке), вызываю - ошибка. Мона пример...
← →
SPeller © (2005-01-27 03:20) [11]Ты присвоил адрес метода, а ты не забыл о первом скрытом параметре Self?
← →
dimaxx © (2005-01-27 22:48) [12]Поскольку присваивание происходит в библиотеке, то непосредственное присваивание типа
MyRec.Prepare:=CalcObj.Prepare;
не работает. Пришлось извернуться так:type
PCalcObj = ^TCalcObj;
TCalcObj = object(TObj)
private
FTemp: integer;
public
function Execute(const Show: boolean): integer;
procedure Prepare(const Value: single);
end;
function CreateCalcObject: PDLLObject; stdcall;
procedure FreeCalcObject; stdcall;
implementation
var CalcObj: PCalcObj;
function NewCalcObject: PCalcObj;
begin
New(Result,Create);
end;
function DLLExecute(const Show: boolean): integer; stdcall;
begin
Result:=CalcObj.Execute(Show);
end;
procedure DLLPrepare(const Value: single); stdcall;
begin
CalcObj.Prepare(Value);
end;
function CreateCalcObject: PDLLObject; stdcall;
begin
CalcObj:=NewCalcObject;
Result.Execute:=DLLExecute;
Result.Prepare:=DLLPrepare;
end;
procedure FreeCalcObject; stdcall;
begin
CalcObj.Free;
end;
Объява PDLLObject выненсена в INC-файл:type
PDLLObject = ^TDLLObject;
TDLLObject = packed record
Execute: function(const Show: boolean): integer; stdcall;
Prepare: procedure(const Value: single); stdcall;
end;
Теперь присваивание выполняется, но как только я вызываю какой-нить из методов - получаю ошибки по числу вызываемых методов объекта:{$I Obj.inc}
var DLL: PDLLObject;
function CreateCalcObject: PDLLObject; external "calc32.dll" name "CreateCalcObject";
procedure FreeCalcObject; external "calc32.dll" name "FreeCalcObject";
procedure TForm1.Button1Click(Sender: PObj);
begin
DLL:=CreateCalcObject;
DLL.Prepare(PI);
DLL.Execute(True);
FreeCalcObject;
end;
Замена PDLLObject на TDLLObject ниченго не меняет - все равно ошибки. Как быть?
← →
dimaxx © (2005-01-27 22:51) [13]Да, забыл дописать: в external объявляются CreateCalcObject и FreeCalcObject.
← →
thaddy (2005-01-27 23:29) [14]or do that in initialization/finalization
You can also adapt constructor destructor to use addref, release to control
← →
dimaxx © (2005-02-03 22:57) [15]Так что - никто не посоветует как быть?
← →
SPeller © (2005-02-04 12:17) [16]function CreateCalcObject: PDLLObject; external "calc32.dll" name "CreateCalcObject"; stdcall;
← →
dimaxx © (2005-02-07 23:08) [17]Не-а, ни фига не помогает. Проверил адреса реальных экспортных процедур библиотеки и тех, что передаются через запись - не совпадают. Отсюда глюки...
← →
SPeller © (2005-02-08 09:18) [18]А если так:
CalcObj:=NewCalcObject;
@Result.Execute := @DLLExecute;
@Result.Prepare := @DLLPrepare;
Страницы: 1 вся ветка
Форум: "KOL";
Текущий архив: 2005.10.09;
Скачать: [xml.tar.bz2];
Память: 0.5 MB
Время: 0.015 c