Форум: "Основная";
Текущий архив: 2003.11.13;
Скачать: [xml.tar.bz2];
Внизэкспорт объектов из DLL Найти похожие ветки
← →
alex_*** (2003-10-30 12:12) [0]DLL:
function GetProgress(....):TObject;
Begin
result:=TMyProgress.Create(nil);
with result as TMyProgress do
Begin
......
end;
End;
EXE:
progress_obj:=GetProgress();
try
//
//идут вычисления, обновляется индикатор
//
finally
progress_obj.Free();
end;
Вопрос: корректно ли так убивать объект индикатора?
Ведь деструктор у TObject всегда виртуальный и по идее память должна разрушаться менеджером памяти в DLL?
← →
Игорь Шевченко (2003-10-30 13:07) [1]Некорректно.
> память должна разрушаться менеджером памяти в DLL?
Память должна освобождаться тем менеждером, который ее выделял
← →
handra (2003-10-30 13:32) [2]некорректно вдвойне - переда экземпляра объекта из DLL? Так нельзя...
← →
Игорь Шевченко (2003-10-30 13:34) [3]handra © (30.10.03 13:32)
Можно
← →
alex_*** (2003-10-30 13:40) [4]Я скажу даже больше. Такой принцип работает в наших программах уже 2 года без глюков. Но может здесь утечка памяти происходит?
Деструтор вызывается, отрабатывает, все ОК (по кр. мере внешне).
← →
Юрий Федоров (2003-10-30 13:43) [5]Если BwRTP - все корректно.
Если без - опасно
← →
Digitman (2003-10-30 13:44) [6]
> alex_***
> Деструтор вызывается, отрабатывает, все ОК
... до тех пор пока не начнешь неосмысленно играться с опцией Build With Run-Time Packages обоих проектов
← →
handra (2003-10-30 13:44) [7][3] Игорь Шевченко © (30.10.03 13:34)
handra © (30.10.03 13:32)
Можно
В теории, без использования пакетов, нельзя - вызывающие приложение не знает о классе объекта, при разных параметрах компиляции будут разные таблицы методов, хотя TObject он и в Афвике TObject.
← →
alex_*** (2003-10-30 13:49) [8]>> неосмысленно играться с опцией Build With Run-Time Packages
)) ну вы блин...
собирается всегда DLL и EXE с "Build With Run-Time Packages".
Судя по откликам в таком режиме все ОК.
Но все равно переделаю на интерфейсы, будет время.
← →
alex_*** (2003-10-30 13:52) [9]>В теории, без использования пакетов, нельзя - вызывающие >приложение не знает о классе объекта, при разных параметрах >компиляции будут разные таблицы методов, хотя TObject он и в >Афвике TObject.
Вот именно и в Африке. Поэтому можно. ПО кр. мере когда DLL и EXE собраны в одной версии Delphi.
← →
Игорь Шевченко (2003-10-30 13:58) [10]handra © (30.10.03 13:44)
Учите матчасть, уважаемый. О вызовах виртуальных методов, о вызовах невиртуальных методов, об операторах is и as
← →
han_malign (2003-10-30 13:59) [11]Конкретно для Free - корректно, он просто проверяет ссылку на nil и вызывает виртуальный Destroy.
З.Ы. На всякий случай: для того, чтобы не было дублирования кода, в основном приложении и в DLL, необходимо, чтобы интерфейс(базовый класс) был полность абстрактным, и в основном приложении не было ни одной реализации методов(от TObject-овских уже никуда не деться - но, на все воля Borland-а).
Вообще, прокатывают любые вызовы статических методов - просто код основного приложения работает с "маской полей" экземпляра(как при приведении указателя к record-у) - проблемы возникнут, если в методах используются глобальные переменные(или изменяемые локальные типизированные константы), или в DLL другая реализация этого статического метода(в последнем случае, проблемы с отладкой - долго думать, "где же, в двух строках, можно сделать логическую ошибку - должно отниматься, а оно прибавляется") - а так, просто, (повторюсь) дублирование кода(неоптимальное использование памяти)...
← →
han_malign (2003-10-30 14:04) [12]>han_malign © (30.10.03 13:59) [11]
>проблемы возникнут
Хотя, это не все, будут еще проблемы со строками и динамическими массивами(при изменении полей, вышеуказанного типа, в статическом методе основного приложения)
← →
handra (2003-10-30 14:04) [13][10] Игорь Шевченко © (30.10.03 13:58)
handra © (30.10.03 13:44)
Учите матчасть, уважаемый. О вызовах виртуальных методов, о вызовах невиртуальных методов, об операторах is и as
Какие as и is, если вызывающее приложение НЕ ЗНАЕТ о классе объекта и DLL?
Почему бы господам из Borland"а не сделать импорт классов из DLL?
← →
Игорь Шевченко (2003-10-30 14:05) [14]handra © (30.10.03 14:04)
> если вызывающее приложение НЕ ЗНАЕТ о классе объекта и DLL?
???????????????? это как, пардон ?
> Почему бы господам из Borland"а не сделать импорт классов
> из DLL?
Уже сделали, такие DLL называются run-time packages
← →
handra (2003-10-30 14:07) [15]?? ?????????????? это как, пардон ?
Уже сделали, такие DLL называются run-time packages
Я имею ввиду вариант без использования опции "Build with run-time packages".
← →
alex_*** (2003-10-30 14:10) [16]Спасибо всем за инфу.
Под интерфейсом я понимаю конкретно интерфейс:
IProgress = interface
["{13CAF858-D41F-46CB-AFA6-D16920063008}"]
function Update(...):Boolean;stdcall;
function SetName(...):Boolean;stdcall;
procedure SetCaption(...);stdcall;
function Reset(...):Boolean;stdcall;overload;
function Reset(...):Boolean;stdcall;overload;
function Advance(...):Boolean;stdcall;
end;
function GetProgress(var IObj: IProgress):Boolean;stdcall;
Begin
with TMyProgress.Create(nil) do
Begin
result:=QueryInterface(IProgress, IObj) ;
......
end;
End;
Тогда мы вообще отвязываемся от реализации объекта. И нет проблем с его разрушением, т.к. 100 пудово деструктор будет вызван в DLL при обнулении счетчика ссылок. А сделано было в первом варианте потому как на тот момент не успел прочитать про интерфейсы )))
← →
handra (2003-10-30 14:14) [17][16] alex_*** (30.10.03 14:10)
Хороший вариант, сам так делаю. Только при создании объекта, реализующего интерфейс в консрукторе добавь вызов _AddRef - решит кое-какие проблемы.
← →
alex_*** (2003-10-30 14:15) [18]->НЕ ЗНАЕТ о классе объекта и DLL?
Как это ?? А то что я возвращаю ссылку на всем известный TObject ничего не говорит вызывающему приложению чтоль ? Отприложения и не надо ничего знать про индикатор, ему нужно потом только вызвать Free (ну и еще изменять его, но это сделано в DLL, куда передается только ссылка типа TObject ). На мой взгляд даже в случае RTP будет работать, но не знаю будет ли все ОК на Free.
← →
alex_*** (2003-10-30 14:17) [19]>>добавь вызов _AddRef
Не решит а добавит. т.к интерфейс реализует не AuomationObject, a TForm. Подсчет ссылок приходится вести вручную.
← →
alex_*** (2003-10-30 14:20) [20]Кстати про ShareMem. У меня такое чувство, что в случ. "Build With Run-Time Packages" этот юнит нафиг не нужен. без него строки передаются, изменяются и все ОК.
← →
handra (2003-10-30 14:22) [21][18] alex_*** (30.10.03 14:15)
->НЕ ЗНАЕТ о классе объекта и DLL?
Как это ?? А то что я возвращаю ссылку на всем известный TObject ничего не говорит вызывающему приложению чтоль ? Отприложения и не надо ничего знать про индикатор, ему нужно потом только вызвать Free (ну и еще изменять его, но это сделано в DLL, куда передается только ссылка типа TObject ). На мой взгляд даже в случае RTP будет работать, но не знаю будет ли все ОК на Free.</I
Если не использовать "Build with run-time packages", класс TObject в DLL и TObject в EXE - разные классы.
← →
alex_*** (2003-10-30 14:24) [22]Что ты понимаешь под разными классами?
Адресное пространство одно, тип один, что еще надо?
← →
handar (2003-10-30 14:26) [23]что-то съехало, вот ответ:
Если не использовать "Build with run-time packages", класс TObject в DLL и TObject в EXE - разные классы.
по-поводу _AddRef - все из-за кривой реализации Borland TInterfacedObject
← →
alex_*** (2003-10-30 14:29) [24]What difference? Что такое разные классы? Ссылка-то одна
???
← →
Radionov Alexey (2003-10-30 14:29) [25]>alex_*** (30.10.03 14:24)
>Что ты понимаешь под разными классами?
>Адресное пространство одно, тип один, что еще надо?
Еще VMT надо одинаковую. И диспетчер памяти. А так - все нормально :)))
← →
Mystic (2003-10-30 14:30) [26]> alex_*** (30.10.03 14:20) [20]
Алекс, ты же нормально разбираешься в предмете сам. Почему ты не хочешь использовать пакеты? Может быть ты и прав, может объект разрушиться менеджером памяти DLL. Может это зависит и от версии Delphi. Зачем искать себе проблемы? Тот факт, что библиотека DLL имеет экспортируемые функции, которые возвращают строки или объекты, уже достаточен для того, чтобы оформить ее пакетом. По крайней мере, даже если ты ее оставишь как DLL, то использовать ее в проектах на VB и VC++ будет затруднительно. А если это чисто теоретический интерес, то ответ находитья в отладчике...
← →
Vuk (2003-10-30 14:32) [27]>все из-за кривой реализации Borland TInterfacedObject
Отсюда поподробнее про кривую реализацию.
← →
alex_*** (2003-10-30 14:35) [28]>[25]
Поскольку адресное пространствово одно, то VMT корректна. Диспетчер памяти не трогаем пока не пользуем AnsiString (по кр. это опускаем). Ну и в чем проблемы?
Хм... может проблемы в понимании VMT? За адреса в VMT несет ответственность экземпляр объекта. Вызывающему приложению важно чтоб не изменялся порядок и тип функций в VMT.
← →
handra (2003-10-30 14:41) [29][27] Vuk © (30.10.03 14:32)
>все из-за кривой реализации Borland TInterfacedObject
Отсюда поподробнее про кривую реализацию.
Ссылки плохо считает.
← →
Vuk (2003-10-30 14:43) [30]to alex_***:
>Ну и в чем проблемы?
Проблемы в том, что в dll и исполняемом модуле при компиляции без использования RTP формируются свои иерархии классов. То есть имеется, например два класса TObject (один в dll и один - в .exe) с разными адресами и т.п. То же самое происходит и со всеми остальными классами. И поэтому все, что связано с RTTI работать не будет.
← →
handra (2003-10-30 14:44) [31]Да, кстати, кривость его счета ссылок можно использовать для создания самоуничтожающегося объекта.
← →
Vuk (2003-10-30 14:44) [32]to handra:
>Ссылки плохо считает.
Я ж говорю - поподробнее. В чем выражается-то?
← →
alex_*** (2003-10-30 14:48) [33]Что-то я не въезжаю про разные классы в DLL и в EXE. Какие такие свои иерархии классов? КТо их там формирует? Объект представляет собой объект, а не иерархию классов. И если объект создан в DLL и ссылка передана в ЕХЕ, то почему возникает 2 разных экземпляра?
← →
handra (2003-10-30 14:49) [34]32] Vuk © (30.10.03 14:44)
to handra:
>Ссылки плохо считает.
Я ж говорю - поподробнее. В чем выражается-то?
У меня выражалось в пропадании объекта, когда он был нужен.
Т.е. я возвращал как свойство интерфейс на существующий объект, но счетчик ссылок интерфейса не увеличивался.
← →
alex_*** (2003-10-30 14:50) [35]Это происходит когда реализующий класс имеет в предках TComponent, там приходится вручную подсчитывать ссылки. А с AutomationObject у меня было все ОК.
← →
Vuk (2003-10-30 14:59) [36]to alex_***:
>Какие такие свои иерархии классов?
Самые натуральные. Класс в Delphi, как известно, не нечто расплывчатое, а вполне конкретная штука, структура у которой есть адрес и т.д. и т.п. В результате в dll и exe эти структуры имеют разный адрес несмотря на то, что классы полностью идентичны. Поэтому RTTI не будет работато корректно.
>КТо их там формирует?
Компилятор, понятное дело.
>Объект представляет собой объект, а не иерархию классов.
А наследование как же?
to handra:
>Т.е. я возвращал как свойство интерфейс на существующий объект,
>но счетчик ссылок интерфейса не увеличивался.
Это все смотреть надо, выделять в минимальный код, показывающий проблему и смотреть. В старых версиях кажется Delphi был похожий глюк...
← →
handra (2003-10-30 15:02) [37]не, выглядело примерно так:
I = interface
function Some(N: Integer): Integer; stdcall;
end;
T = class(TIterfacedObject,I)
public
function Some(N: Integer): Integer; stdcall;
end;
никаких TComponent.
в другом классе
T2=class(TObject)
private
FT: T;
public
property PropT: T read FT;
end;
при вызове:
begin
with FT.Create do
try
PropT.SomeFunc <---!!!
finally
Free; <-- boom!
end;
end;
Вместе означенном (!!!) счетчик при передаче интерфейса не увеличивался, но зато уменьшался.
И деструкторе T2 при попытке удалить объект FT возникало исключение
← →
alex_*** (2003-10-30 15:07) [38]to Vuk © (30.10.03 14:59) [36]
>В результате в dll и exe эти структуры имеют разный адрес несмотря на то, что классы полностью идентичны.
Так я же ПЕРЕДАЮ ссылку на объект. Я что, не могу с ней работать?
>А наследование как же?
Наследование влияет на формирование объекта: расширение его функциональности (дополнение VMT унаследованными методами, дополнение списка методов, всякие поля класса). А когда объект скомпилён, то это просто объект, безо всякой цепочки иерархии.
← →
handra (2003-10-30 15:07) [39]последний кусочек - опечатка:
при вызове:
begin
with T2.Create do
try
PropT.SomeFunc <---!!!
finally
Free; <-- boom!
end;
end;
зато следующая конструкция рабочая:
var A: T;
begin
with T2.Create do
try
A := PropT;
A.SomeFunc <---!!!
finally
Free; <-- boom!
end;
end;
← →
alex_*** (2003-10-30 15:13) [40]Нарушилась очередность вызовов деструкторов. Какие-то общие данные они имеют.
Страницы: 1 2 вся ветка
Форум: "Основная";
Текущий архив: 2003.11.13;
Скачать: [xml.tar.bz2];
Память: 0.55 MB
Время: 0.666 c