Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2005.10.09;
Скачать: CL | DM;

Вниз

Как передать коннект к базе Firebird из программы в dll?   Найти похожие ветки 

 
Akris ©   (2005-08-27 20:11) [0]

Подскажите, пожалуйста, как передать коннект к базе данных Firebird из основной программы в dll так, чтобы было только одно соединение с базой.
Пробовал передавать компонент TpFIBDataBase -  вылетает Access Violation по адресу в библиотеке.

Я использую компоненты FibPlus 4.8.


 
Sergey Masloff   (2005-08-27 20:54) [1]

Не надо это делать. Просто на такие грабли наступишь...


 
Akris ©   (2005-08-27 21:09) [2]

Тогда как решить следующую задачу:
есть основное приложение, которое реализует подключение к базе данных и есть три справочника - которые реализуются dll. Если не передавать коннект, тогда при открытии всех трех справочников будем иметь четыре соединения с базой данных: одно соединение из основного приложения и по одному из каждого справочника. А это не есть гуд!!!

Кстати, какие есть грабли?


 
Sergey Masloff   (2005-08-27 22:00) [3]

Использовать пакеты (package) а не dll, но работоспособностья лично не проверял. На фига справочники в dll? Тоже непонятно


 
}{ander ©   (2005-08-27 22:01) [4]

> будем иметь четыре соединения с базой данных

Ну и что? Хоть 10 соединений - для FB это, имхо, не проблема.


 
Akris ©   (2005-08-28 12:39) [5]

> На фига справочники в dll?

Потому что нужно сделать возможность вида и содержимого справочника. А поскольку справочник в dll тода можно менять только одну отдельную dll вместо замены всего приложения.

> Ну и что? Хоть 10 соединений - для FB это, имхо, не проблема.

Согласен что не проблема, но для SuperServer. Да и к тому же на каждое соединение с базой будет уходить время, а при использовании уже открытого соединения нет этих затрат.


 
sniknik ©   (2005-08-28 13:01) [6]

> Согласен что не проблема, но для SuperServer.
для любого сервера десяток соеденений не проблема. имхо. если только лицензия не на 5-ть ;о)).

проблема будет если использовать персонал(ембедед) версию... гдe возможно всего одно подключение.

но в общем не понятно в чем проблема, не скажу за TpFIBDataBase но ADOconnection и Database(BDE) в dll передавал (просто тесты. в реальных программах такой нужды не возникало) все отлично передается... не думаю что FIB-ы глючат, скорее твоя реализация их использования "с брачком".
1-е проверь соглашения о вызовах, чтобы совпадали в dll и exe.
2-e внимательно прочитай коментарий при создании dll создающийся, там явное указание насчет менеджера памяти, и что делать, чтобы передавались строки и обьекты.
впечатление что ты это сообщение проигнорировал.
3-е описывай проблему подробно, с примерами и кодом. пока по твоему описанию ничего не понять.


 
DrPass ©   (2005-08-28 13:13) [7]

Скорее всего, проблема в отсутствии пресловутого ShareMem. Я в свое время делал такой финт с DLL (только не с FIBPlus, а с IBExpress). В принципе, жалоб и подводных камней не было (была, правда, проблема с обработкой событий - но это уже "особенности" архитектуры IBExpress)


 
Desdechado ©   (2005-08-29 12:05) [8]

а млжет, при вызове DLL ты в ней не указываешь вызвавшее приложение в качестве Application?
или с разными версиями компонентов компилируешься - тогда 100% глюки будут


 
Domkrat ©   (2005-08-29 12:24) [9]

У нас реализован вариант: exe (1 конект) + BPL.
Экзешка реализует интерфейс, который возвращает конекшн, который можно вызвать из BPL.


 
Akris ©   (2005-08-29 15:36) [10]

Код приложения, который вызывает форму из 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:37) [11]

Код приложения, который вызывает форму из 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;


 
Desdechado ©   (2005-08-29 16:30) [12]

1. DM.DataBase в вызывающем модуле - неизвестно что
2. я бы передал в DLL еще и Application.Handle, а в DLL присвоил бы его ейному Application.Handle (а перед завершением DLL-функции и восстановил бы)
3. Form1 в DLL похоже на глобальную переменную. Есть неплохой шанс использовать ее ненароком несколько раз, нахватавшись глюков
4. выгрузку библиотеки я поставил бы не на except, а на finally, а так у тебя она остается болтаться в случае неошибки, что приведет к ошибке при следующем ее вызове
5. я бы еще для ShowForm возвращал статус или Handle формы, чтоб ее потом закрыть корректно можно было


 
Akris ©   (2005-08-29 16:49) [13]

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 за помощь.



Страницы: 1 вся ветка

Текущий архив: 2005.10.09;
Скачать: CL | DM;

Наверх




Память: 0.52 MB
Время: 0.041 c
2-1125592985
pathfinder
2005-09-01 20:43
2005.10.09
работа с текстовым файлом


2-1125324189
Term
2005-08-29 18:03
2005.10.09
Для хранения денег


4-1123694266
NightLord
2005-08-10 21:17
2005.10.09
Окна в Windows e


14-1127193741
Ega23
2005-09-20 09:22
2005.10.09
С днём рождения! 20 сентября


14-1126773985
SergProger
2005-09-15 12:46
2005.10.09
Файловая система