Форум: "Базы";
Поиск по всему сайту: delphimaster.net;
Текущий архив: 2002.04.11;
Скачать: [xml.tar.bz2];




Вниз

круговерть с DLL 


der   (2002-03-06 12:48) [0]

всем привет!
Ситуация такая: есть прога, использующая datamodule (свойство active у всех таблиц включается в самом начале и не выключается до выхода из программы). Часть функций надо бы реализовать внешней DLL. Одна из них использует те же таблицы из datamodule. Как это все можно реализовать? Т.е. чтобы и в основной программе таблицы были активны, и в этой самой DLL можно было использовать фильтры, индексы и пр.. Это возможно?



deleon   (2002-03-06 13:05) [1]

Все это возможно, но это чревато кучей багов, хотя как напишешь :-)



sniknik   (2002-03-06 13:53) [2]

Написать не проблема, просто передавай Table-s как параметры, можно даже класс DataModule передать. Все одно передаются только ссылки и в dll ты будеш работать с теми же таблицами что и в программе. Не понимаю только зачем? Но наверно нада. А касаемо багов не попробуеш не узнаеш, может именно у тебя их совсем не будет.



Arhelon   (2002-03-06 14:21) [3]

Пишешь что обоих проэктах (и exe и dll)
uses
Sharemem,
....

и потом свободно передаешь в dll что угодно
типа

function gShow(ds:TDataSet): TForm; stdcall;
var f: TfGrid;
begin
f:=TfGrid.Create(Application);
f.ds:=ds;
f.s.DataSet:=ds;
f.g.Update;
f.Show;
result:=f;
end;

exports gShow;
енто модуль dll
а в модуле exe
function gShow(ds:TDataSet): TForm; stdcall; external "pDll.dll";
и далее
procedure TForm1.bDllClick(Sender: TObject);
begin
f:=gShow(ds);
end;
вот собственно и всё что могет помоч отцу русской демократии



deleon   (2002-03-14 13:35) [4]

А никто, выше-приведенный пример не пробовал сделать не статическим вызовом Dll, а динамическим?



sniknik   (2002-03-14 13:48) [5]

Шутиш? Только динамическими пользуйся! гораздо удобнее (больше возможностей)

type
TCashProc = class(TComponent)
private
DllHandle: Thandle;
public
Proc: TCashProc;
DllName: String;
ConString: WideString;
DllInit: function (Own: TComponent; ConString: WideString): Boolean; stdcall;
DllClose: function: Boolean; stdcall;
GetInfo: function: PChar; stdcall; {}
GetConString: function (Handle: HWND; ConString: WideString): WideString; stdcall;
GetZNumber: function: PChar; stdcall; {}
ExistIn: function (Path: PChar): Boolean; stdcall;
CopyIn: function: PChar; stdcall;
DeleteIn: function (Path: PChar): Boolean; stdcall;
ExistOut: function (CashNo: Integer): Integer; stdcall;
CopyOut: function (CashNo: Integer; Path: PChar): PChar; stdcall;
DeleteOut: function: Boolean; stdcall;
constructor Create(Owner: TComponent; Dll: String; ConStr: WideString);
destructor Destroy; override;
end;

Const LoadOk: Boolean= True;

implementation

constructor TCashProc.Create(Owner: TComponent; Dll: String; ConStr: WideString);
begin
inherited Create(Owner);
DllHandle:= LoadLibrary(PChar(Dll));
if DllHandle >= 32 then begin
DllInit:= GetProcAddress(DllHandle, "DllInit");
if @DllInit = nil then begin
MessageDlg("Ошибка: в модуле не найдена функция DllInit", mtError, [mbOk], 0);
LoadOk:= False;
end;
DllClose:= GetProcAddress(DllHandle, "DllClose");
if @DllClose = nil then begin
MessageDlg("Ошибка: в модуле не найдена функция DllClose", mtError, [mbOk], 0);
LoadOk:= False;
end;
GetInfo:= GetProcAddress(DllHandle, "GetInfo");
if @GetInfo = nil then begin
MessageDlg("Ошибка: в модуле не найдена функция GetInfo", mtError, [mbOk], 0);
LoadOk:= False;
end;
GetConString:= GetProcAddress(DllHandle, "GetConString");
if @GetConString = nil then begin
MessageDlg("Ошибка: в модуле не найдена функция GetConString", mtError, [mbOk], 0);
LoadOk:= False;
end;
GetZNumber:= GetProcAddress(DllHandle, "GetZNumber");
if @GetZNumber = nil then begin
MessageDlg("Ошибка: в модуле не найдена функция GetZNumber", mtError, [mbOk], 0);
LoadOk:= False;
end;
ExistIn:= GetProcAddress(DllHandle, "ExistIn");
if @ExistIn = nil then begin
MessageDlg("Ошибка: в модуле не найдена функция ExistIn", mtError, [mbOk], 0);
LoadOk:= False;
end;
CopyIn:= GetProcAddress(DllHandle, "CopyIn");
if @CopyIn = nil then begin
MessageDlg("Ошибка: в модуле не найдена функция CopyIn", mtError, [mbOk], 0);
LoadOk:= False;
end;
DeleteIn:= GetProcAddress(DllHandle, "DeleteIn");
if @DeleteIn = nil then begin
MessageDlg("Ошибка: в модуле не найдена функция DeleteIn", mtError, [mbOk], 0);
LoadOk:= False;
end;
ExistOut:= GetProcAddress(DllHandle, "ExistOut");
if @ExistOut = nil then begin
MessageDlg("Ошибка: в модуле не найдена функция ExistOut", mtError, [mbOk], 0);
LoadOk:= False;
end;
CopyOut:= GetProcAddress(DllHandle, "CopyOut");
if @CopyOut = nil then begin
MessageDlg("Ошибка: в модуле не найдена функция CopyOut", mtError, [mbOk], 0);
LoadOk:= False;
end;
DeleteOut:= GetProcAddress(DllHandle, "DeleteOut");
if @DeleteOut = nil then begin
MessageDlg("Ошибка: в модуле не найдена функция DeleteOut", mtError, [mbOk], 0);
LoadOk:= False;
end;
ConString:= ConStr;
if LoadOk then LoadOk:= DllInit(Owner, ConString);
end else begin
MessageDlg("Ошибка: не могу найти "+Dll, mtError, [mbOk], 0);
LoadOk:= False;
end;
end;



deleon   (2002-03-14 13:54) [6]

Это все понятно...но у меня DbGrid в exe, а коннект создается в dll и передает в exe TDataSet, сейчас я тебе на мыло скину этот небольшой пример!



deleon   (2002-03-14 13:58) [7]

[sniknik]Пример выслал - посмотри :)



sniknik   (2002-03-14 14:09) [8]

Письмо пришло а примера нет. Извини писмом ответить затруднительно у нас почта из сети не уходит (провайдер новый 1.5 месяца работает пока не отладили) повтори. и обрати внимание на ; stdcall; при описании процедур должно стоять и в dll и exe. (у меня были с этим смол проблемс)



deleon   (2002-03-14 14:18) [9]

stdcall - везде стоит!
Пример уже выслал, посмотри если что поймешь ответь в этой теме :))) Спасибо!



deleon   (2002-03-14 14:30) [10]

[sniknik] - а ICQ у тебя есть ?



sniknik   (2002-03-14 14:32) [11]

на первой функции не стоит в dll.
function dbw_finddatabase(pDesc: pdbw_dbdesc): TComponent; stdcall; <- (сдесь его не было!)
и с передачей параметров путаница например
в dll пишеш
function dbw_opendatabase(pDesc: pdbw_dbdesc; var iDb: TComponent): word; stdcall;
а в exe
OpenDb : dbw_opendatabase;
а надо так
OpenDb : function (pDesc: pdbw_dbdesc; var iDb: TComponent): word; stdcall;
и еще не обязательно имена прописывать так будет достаточно
exports
dbw_opendatabase,dbw_closedatabase,dbw_opentable,dbw_closetable;

это при первом рассмотрении может чтото еще щас отловлю све и вышлю как нибудь.

ICQ нет



deleon   (2002-03-14 14:37) [12]

1) dbw_opendatabase - это тип (описан в DbwApi.pas)
2) function dbw_finddatabase - локальная в dll и не вызывается из вне.
3) Жаль что нет ICQ



deleon   (2002-03-14 15:01) [13]

[sniknik] - ну как? есть какие-нибудь идеи ?



sniknik   (2002-03-14 15:10) [14]

Теоретически уже работает, только почемуто при вызове из dll после открытия сразу таблицу закрывает :(. А вот логика странная я бы так не делал.



deleon   (2002-03-14 15:19) [15]

Логика может и странная, но это плагин Database Workshop для доступа к Paradox-таблицам, поэтому другого пути нет! И у меня после открытия можно посмотреть все свойства таблицы, но грид упорно не показывает записи и при закрытии формы вываливается известная ошибка :(



sniknik   (2002-03-14 15:40) [16]

Там путаница с Hendl-ами поэтому и закрывается и ошибка вываливается. Подождеш до завтра? я дома разберусь а то работать тоже надо :) иногда.
у меня таблица откравается а гриде записи мелькают и тут же отключается. а ошибка при закрытии потому что пытается закрыть обьект которого уже нет.



deleon   (2002-03-14 15:41) [17]

Чувствую ничего из этой затеи не выйдет! Но почему при статической загрузке все работает, а при динамической нет ?!!!



deleon   (2002-03-14 15:42) [18]

Ок! Подожду и буду очень признателен!



deleon   (2002-03-14 15:56) [19]

Я заметил, что если LoadLibrary сделать в начале загрузки программы, а в конце сделать выгрузку, то все почти работает. Похоже что память под компонент распределяется локально в dll и после вызова процедуры - очищается или что-то в этом роде!



sniknik   (2002-03-14 16:02) [20]

Может быть надо попробовать а то как еще обьяснить компонент создеется и даже отрабатывает и тут же уничтожается сам по себе.



deleon   (2002-03-15 08:50) [21]

Все заработало при загрузке и выгрузке библиоьеки одновременно с приложением и замене директивы stdcall на cdecl.



deleon   (2002-03-21 14:05) [22]

1) Директива все-таки должна быть stdcall.
2) Все объекты, в том числе и компоненты, созданные в dll должны в ней-же и уничтожаться.
3) Компоненты в dll нельзя создавать через локальные переменные, только через глобальные, так как при завершении процедуры, очищается стек вместе с памятью распределенной через локальные переменные.
4) Все сделать реально, т.к. у меня заработало без всяких ошибок(таблицы и базы данных в dll, а формы отображения данных в приложении)
5) Удачи всем, кто пошел по этому пути!




Форум: "Базы";
Поиск по всему сайту: delphimaster.net;
Текущий архив: 2002.04.11;
Скачать: [xml.tar.bz2];




Наверх





Память: 0.77 MB
Время: 0.028 c
1-32898           Cupor                 2002-03-29 19:08  2002.04.11  
Панаели инструментов как в Photoshope


1-32834           ghost_by              2002-03-22 21:08  2002.04.11  
Тормоза в ListView


4-33031           dimonn                2002-02-09 14:48  2002.04.11  
Как изменить чужие Hint ы???


1-32855           sammy                 2002-03-29 07:11  2002.04.11  
обработать OnClick


14-32981          ATLANTIDO             2002-02-20 00:44  2002.04.11  
Что такое расшарить диск?