Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "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.013 c
14-1127310647
Суслик
2005-09-21 17:50
2005.10.09
Кто в Москве продаст следующие книги?


4-1123600876
CTPAX.RU
2005-08-09 19:21
2005.10.09
Ошибка при чтении и записи в порт


1-1126827810
kblc
2005-09-16 03:43
2005.10.09
TPageControl and TListView


3-1125386830
Malign
2005-08-30 11:27
2005.10.09
Скорость работы хранимых процедур значительно ниже запросов


4-1124107383
alex-drob
2005-08-15 16:03
2005.10.09
Отловить событие в другом приложении.





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский