![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
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]собери оба проекта с ран-тайм пакетами