Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

DLL И Interface


Grigsv ©   (2004-09-23 17:06:00) 

Добрый день, всем.
Проблемма :
1. Создал DLL
2. динамически загрузил ее в программе
3. Получил адрес функции и из нее получил адрес объекта.
4. Запросил у объекта интерфейс
5. Выполнил какие-то действия, Без видимых ошибок. ( Вызвал ShowMessage ;) )
6. освободил интерфейст.
7. Освободил библиотеку
Проблемма : на 6 или 7 шаге программа рушится.  Если работать без интерфейсов, то все нормально. Глюк. Помогите, объясните в чем дело, пожалуйста. Кусок кода ниже :

procedure TForm2.Button1Click(Sender: TObject);

var
 HI : HInst;
 Exec : function : TInterfacedObject; stdcall;
 O : TInterfacedObject;
 sh : IShow;
begin
 HI := LoadLibrary('LIB.Dll');
 if HI > 0 then begin
   Exec := GetProcAddress( HI, 'GetObj' );
   if Assigned( @Exec ) then begin

     O := Exec;

     if Assigned( O ) then begin
       sh := O as IShow;
       if Assigned(sh) then begin
         sh := o as IShow;
         sh.Mess;
       end;
     end;
   end;
   FreeLibrary( HI );
 end;
end;


Cobalt   (2004-09-27 17:10:00) [1]

А самому вызывать  _Release, конечно же, не стоит. Это сделает за тебя компилятор.


Cobalt   (2004-09-27 17:09:00) [2]

2 Grigsv   (27.09.04 15:22) [13]
Я же говорю, это не тебе :)
Пояснения - ниже (чтобы ты въехал, о чём я был не согласен с Digitman ©)

>Digitman ©   (24.09.04 10:06) [8]
менеджеры памяти скорей всего разные

память под интерфейсный объект в ходе его конструирования выделяется экземпляром менеджера в ДЛЛ, а попытка освобождения этой памяти в ходе его разрушения осуществляется экземпляром менеджера в ЕХЕ


Т.к. освобождение памяти, выделенной под интерфейс, осуществляется объектом, исполняющим интерфейс, (он-то создан в ДЛЛ) то обращается он к своему менеджеру памяти, не так ли?
И ShareMem тут не при чём - особенно, если ДЛЛ-ка написана на С++ или VB.


Grigsv   (2004-09-27 15:22:00) [3]

Cobalt, не надо хамить. Хамство не украшает человека.


Cobalt   (2004-09-27 14:43:00) [4]

2 Grigsv   (27.09.04 13:38) [11]
> Cobalt ©, _Realise : Эту функцию на прямую вызывать нежелательно. Да и глюки все равно при таком подходе остались.
Эта фраза предназначалась не тебе. Потому ты её не понял :)


Grigsv   (2004-09-27 13:38:00) [5]

Для чего я все это устроил: Есть единая запускалочка для разных форм, которые пишутся разными людьми. Формы работают с базами данных через BDE. Каждый человек собирает свои формы в одну или несколько библиотек. Связь EXE с DLL через объект связи, который для каждой DLL свой. Он и рассказывает, что нужно для работы своей DLL ( пользователь и права доступа, TDatabase, протоколирование и др.), т.е. какие интерфейсы он поддерживает.

Спасибо Digitman ©  за идею по поводу ShareMem. Работает.

По поводу остальных идей :

Polevi, ActiveX  : Для меня проще так. Может со временем и прийду к идее ActiveX.

Cobalt ©, _Realise : Эту функцию на прямую вызывать нежелательно. Да и глюки все равно при таком подходе остались.


Cobalt   (2004-09-24 14:33:00) [6]

>Digitman ©   (24.09.04 10:06) [8]
А разве для интерфейсов не вызывается просто _Release? И освобождает память тот класс, который исполняет интерфейс


Polevi   (2004-09-24 10:16:00) [7]

зачем жти извращения с LoadLibrary и GetProcAddress в данном случае
кто мешает использовать ActiveX library + CreateCom(Ole)Object


Digitman   (2004-09-24 10:06:00) [8]

нет, не вру

менеджеры памяти скорей всего разные

память под интерфейсный объект в ходе его конструирования выделяется экземпляром менеджера в ДЛЛ, а попытка освобождения этой памяти в ходе его разрушения осуществляется экземпляром менеджера в ЕХЕ

либо задействуй ShareMem либо собирай все с ран-тайм пакетами


Grigsv   (2004-09-24 09:37:00) [9]

Рано обрадовался, явного окна с ошибкой не появилось, но программа ушла в себя и не возвращается.


Grigsv   (2004-09-24 09:18:00) [10]

Проверил идею Cobalt © с функцией возвращающей интерфейс. Сработало, как не странно. :/

procedure TForm2.Button1Click(Sender: TObject);
var
 HI : HInst;
 Exec : function : IShow; stdcall;
 sh : IShow;
begin
 HI := LOadLibrary('LIB.Dll');
 if HI > 0 then begin
   Exec := GetProcAddress( HI, 'GetIShow' );
   if Assigned( @Exec ) then begin
     sh := Exec;
     if Assigned(sh) then begin
         sh.Mess;
         sh := nil;
     end;
   end;
   FreeLibrary( HI );
 end;
end;


Grigsv   (2004-09-24 09:06:00) [11]

Эксперементировал много, вот и стер строку с освобождением интерфейса. Но проблемма все равно осталась. С этой строкой, или без нее.

....
     if Assigned( O ) then begin
       sh := O as IShow;
       if Assigned(sh) then begin
         sh := o as IShow;
         sh.Mess;
         sh := nil; -- <<<<<<<<<<<<<<
       end;
     end;
....


Cobalt   (2004-09-23 17:47:00) [12]

Хм, а не лучше ли в функции декларировать, что она возвращает именно интерфейс?


Cobalt   (2004-09-23 17:47:00) [13]

Хм, а не лучше ли в функции декларировать, что она возвращает именно интерфейс?


Digitman   (2004-09-23 17:25:00) [14]

вру

рантайм-пакеты, конечно. не помешают, но ... где у тебя явный шаг 6 ?
он выполняется у тебя неявно ПОСЛЕ шага 7, оттого и проблема


Digitman   (2004-09-23 17:20:00) [15]

собери оба проекта с ран-тайм пакетами


Наверх

Титульная страница Поиск, карта сайта Написать письмо