Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Базы";
Текущий архив: 2005.10.09;
Скачать: [xml.tar.bz2];

Вниз

Как передать коннект к базе 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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.5 MB
Время: 0.012 c
4-1123172300
readme
2005-08-04 20:18
2005.10.09
добавить пункт в контекстное мннею


2-1125285887
-=snoop=-
2005-08-29 07:24
2005.10.09
ф-ия COPYFILE, не могу найти...


8-1116731635
Antonn
2005-05-22 07:13
2005.10.09
Использование GDI+


6-1118819383
DVYdm
2005-06-15 11:09
2005.10.09
Доступ к БД Firebird в Apache Server


14-1126841752
MBo
2005-09-16 07:35
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
Английский Французский Немецкий Итальянский Португальский Русский Испанский