![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Как передать коннект к базе Firebird из программы в dll? [D7, Firebird]
Akris © (2005-08-27 20:11:00)Подскажите, пожалуйста, как передать коннект к базе данных Firebird из основной программы в dll так, чтобы было только одно соединение с базой.
Пробовал передавать компонент TpFIBDataBase - вылетает Access Violation по адресу в библиотеке.
Я использую компоненты FibPlus 4.8.
Akris (2005-08-29 16:49:00) [1]1. DM.DataBase в вызывающем модуле - это компонент TpFIBDataBase в DataModule.
3. Form1 в DLL глобальная переменная - я понял и убрал.
4. Выгрузка библиотеки стоит на except - такова логика программы.
5. Закрываю форму я другой процедурой, которая вызывается из dll.
Спасибо всем, кто ответил. Рабочий код следующий:
type
//Объявление процедурного типа для вызова формы из DLL
TShowForm = procedure (AppHandle: THandle;BaseHandle: TISC_DB_HANDLE); stdcall;
{...}
//Вызов формы из DLL
procedure TfrMain.Button1Click(Sender: TObject);
var
LibHandle: THandle;
LibFunction: TShowForm;
begin
{Делаем попытку загрузить Dll}
LibHandle := LoadLibrary(PChar(ExtractFileDir(ParamStr(0))+'\PenniesDll\PenniesLib.dll'));
try
{Если загрузка Dll окажется неудачной, переменная LibHandle будет иметь
нулевое значение. В этом случае возникнет исключительная ситуация}
if (LibHandle = 0) then
begin
raise EDLLLoadError.Create('Не могу загрузить Dll');
end;
{Устанавливаем связь с экспортируемой функцией}
@LibFunction := GetProcAddress(LibHandle, 'ShowForm');
{Если функция экспортируется удачно, тогда возвращаем результат}
if not(@LibFunction = nil) then
LibFunction(Application.Handle, DM.DataBase.Handle)
else
RaiseLastWin32Error;
except
//Выгружаем библиотеку
FreeLibrary(LibHandle);
end;
end;
Код в DLL, который создает форму. На форме DBGrid, DataSource, FIBDataSet, FIBTransaction.
//------------------------------------------------------------------------------
procedure ShowForm(AppHandle: THandle;BaseHandle: TISC_DB_HANDLE); stdcall;
begin
Application.Handle := AppHandle;
DM := TDM.Create(Application);
Form1 := TForm1.Create(Application);
Form1.Show;
DM.DataBase.Handle := BaseHandle;
DM.dstTemp.Database := DM.DataBase;
DM.dstTemp.SelectSQL.Add('SELECT * FROM USERS');
DM.dstTemp.Open;
Form1.ds.DataSet := DM.dstTemp;
Form1.DBGrid1.Align := alClient;
end;
Причина вылета: не было создания DataModule.
Спасибо Peter за помощь.
Desdechado (2005-08-29 16:30:00) [2]1. DM.DataBase в вызывающем модуле - неизвестно что
2. я бы передал в DLL еще и Application.Handle, а в DLL присвоил бы его ейному Application.Handle (а перед завершением DLL-функции и восстановил бы)
3. Form1 в DLL похоже на глобальную переменную. Есть неплохой шанс использовать ее ненароком несколько раз, нахватавшись глюков
4. выгрузку библиотеки я поставил бы не на except, а на finally, а так у тебя она остается болтаться в случае неошибки, что приведет к ошибке при следующем ее вызове
5. я бы еще для ShowForm возвращал статус или Handle формы, чтоб ее потом закрыть корректно можно было
Akris (2005-08-29 15:37:00) [3]Код приложения, который вызывает форму из DLL:
type
//Объявление процедурного типа для вызова формы из DLL
TShowForm = procedure (DataBase: Pointer); stdcall;
{...}
//Вызов формы из DLL
procedure TfrMain.Button1Click(Sender: TObject);
var
LibHandle: THandle;
LibFunction: TShowForm;
begin
{Делаем попытку загрузить Dll}
LibHandle := LoadLibrary(PChar(ExtractFileDir(ParamStr(0))+'\PenniesDll\PenniesLib.dll'));
try
{Если загрузка Dll окажется неудачной, переменная LibHandle будет иметь
нулевое значение. В этом случае возникнет исключительная ситуация}
if (LibHandle = 0) then
begin
raise EDLLLoadError.Create('Не могу загрузить Dll');
end;
{Устанавливаем связь с экспортируемой функцией}
@LibFunction := GetProcAddress(LibHandle, 'ShowForm');
{Если функция экспортируется удачно, тогда возвращаем результат}
if not(@LibFunction = nil) then
LibFunction(Pointer(DM.DataBase))
else
RaiseLastWin32Error;
except
//Выгружаем библиотеку
FreeLibrary(LibHandle);
end;
end;
Код в DLL, который создает форму. На форме DBGrid, DataSource, FIBDataSet, FIBTransaction.
//------------------------------------------------------------------------------
procedure ShowForm(aDataBase: Pointer); stdcall;
begin
Form1 := TForm1.Create(Application);
Form1.Show;
//Здесь вылетает Access Violetion in module PenniesLib
DM.DataBase := TpFIBDatabase(aDataBase);
DM.dstTemp.Database := DM.DataBase;
DM.dstTemp.SelectSQL.Add('SELECT * FROM USERS');
DM.dstTemp.Open;
Form1.ds.DataSet := DM.dstTemp;
Form1.DBGrid1.Align := alClient;
end;
Akris (2005-08-29 15:36:00) [4]Код приложения, который вызывает форму из DLL:
type
//Объявление процедурного типа для вызова формы из DLL
TShowForm = procedure (DataBase: Pointer); stdcall;
{...}
//Вызов формы из DLL
procedure TfrMain.Button1Click(Sender: TObject);
var
LibHandle: THandle;
LibFunction: TShowForm;
begin
{Делаем попытку загрузить Dll}
LibHandle := LoadLibrary(PChar(ExtractFileDir(ParamStr(0))+'\PenniesDll\PenniesLib.dll'));
try
{Если загрузка Dll окажется неудачной, переменная LibHandle будет иметь
нулевое значение. В этом случае возникнет исключительная ситуация}
if (LibHandle = 0) then
begin
raise EDLLLoadError.Create('Не могу загрузить Dll');
end;
{Устанавливаем связь с экспортируемой функцией}
@LibFunction := GetProcAddress(LibHandle, 'ShowForm');
{Если функция экспортируется удачно, тогда возвращаем результат}
if not(@LibFunction = nil) then
LibFunction(Pointer(DM.DataBase))
else
RaiseLastWin32Error;
except
//Выгружаем библиотеку
FreeLibrary(LibHandle);
end;
end;
Код в DLL, который создает форму. На форме DBGrid, DataSource, FIBDataSet, FIBTransaction.
//------------------------------------------------------------------------------
procedure ShowForm(aDataBase: Pointer); stdcall;
begin
Form1 := TForm1.Create(Application);
Form1.Show;
//Здесь вылетает Access Violetion in module PenniesLib
DM.DataBase := TpFIBDatabase(aDataBase);
DM.dstTemp.Database := DM.DataBase;
DM.dstTemp.SelectSQL.Add('SELECT * FROM USERS');
DM.dstTemp.Open;
Form1.ds.DataSet := DM.dstTemp;
Form1.DBGrid1.Align := alClient;
end;
Domkrat (2005-08-29 12:24:00) [5]У нас реализован вариант: exe (1 конект) + BPL.
Экзешка реализует интерфейс, который возвращает конекшн, который можно вызвать из BPL.
Desdechado (2005-08-29 12:05:00) [6]а млжет, при вызове DLL ты в ней не указываешь вызвавшее приложение в качестве Application?
или с разными версиями компонентов компилируешься - тогда 100% глюки будут
DrPass (2005-08-28 13:13:00) [7]Скорее всего, проблема в отсутствии пресловутого ShareMem. Я в свое время делал такой финт с DLL (только не с FIBPlus, а с IBExpress). В принципе, жалоб и подводных камней не было (была, правда, проблема с обработкой событий - но это уже "особенности" архитектуры IBExpress)
sniknik (2005-08-28 13:01:00) [8]> Согласен что не проблема, но для SuperServer.
для любого сервера десяток соеденений не проблема. имхо. если только лицензия не на 5-ть ;о)).
проблема будет если использовать персонал(ембедед) версию... гдe возможно всего одно подключение.
но в общем не понятно в чем проблема, не скажу за TpFIBDataBase но ADOconnection и Database(BDE) в dll передавал (просто тесты. в реальных программах такой нужды не возникало) все отлично передается... не думаю что FIB-ы глючат, скорее твоя реализация их использования "с брачком".
1-е проверь соглашения о вызовах, чтобы совпадали в dll и exe.
2-e внимательно прочитай коментарий при создании dll создающийся, там явное указание насчет менеджера памяти, и что делать, чтобы передавались строки и обьекты.
впечатление что ты это сообщение проигнорировал.
3-е описывай проблему подробно, с примерами и кодом. пока по твоему описанию ничего не понять.
Akris (2005-08-28 12:39:00) [9]> На фига справочники в dll?
Потому что нужно сделать возможность вида и содержимого справочника. А поскольку справочник в dll тода можно менять только одну отдельную dll вместо замены всего приложения.
> Ну и что? Хоть 10 соединений - для FB это, имхо, не проблема.
Согласен что не проблема, но для SuperServer. Да и к тому же на каждое соединение с базой будет уходить время, а при использовании уже открытого соединения нет этих затрат.
}{ander (2005-08-27 22:01:00) [10]> будем иметь четыре соединения с базой данных
Ну и что? Хоть 10 соединений - для FB это, имхо, не проблема.
Sergey Masloff (2005-08-27 22:00:00) [11]Использовать пакеты (package) а не dll, но работоспособностья лично не проверял. На фига справочники в dll? Тоже непонятно
Akris (2005-08-27 21:09:00) [12]Тогда как решить следующую задачу:
есть основное приложение, которое реализует подключение к базе данных и есть три справочника - которые реализуются dll. Если не передавать коннект, тогда при открытии всех трех справочников будем иметь четыре соединения с базой данных: одно соединение из основного приложения и по одному из каждого справочника. А это не есть гуд!!!
Кстати, какие есть грабли?
Sergey Masloff (2005-08-27 20:54:00) [13]Не надо это делать. Просто на такие грабли наступишь...