Форум: "Основная";
Текущий архив: 2005.08.28;
Скачать: [xml.tar.bz2];
ВнизТак, а если общение через интерфейс, но интерфейс в DLL? Найти похожие ветки
← →
Mx © (2005-08-05 12:20) [0]Нужен ли тогда ShareMem? Допустим загружаем DLL, а она экспортирует функцию для создания объекта, с которым потом общаемся через интерфейс (объект не COM, но интерфейс реализует, как IDesigner в Delphi). Будут ли проблемы со string"ами (не бельем, естественно)?
← →
Digitman © (2005-08-05 12:47) [1]смысл, необходимость и логика использования Sharemem в случае взаимодействия с dll через интерфейсы ничем не отличаются от случая "обычного" взаимодействия
← →
Mx © (2005-08-05 13:03) [2]
> Digitman © (05.08.05 12:47) [1]
Торможу, так нужен ShareMem или нет? Если можно, по-подробнее.
← →
wal © (2005-08-05 13:08) [3]Если через интерфейс будешь строки (string) или дин. массивы передавать, то нужен, если нет, то не нужен, А почему бы сразу на COM не замахнуться, а не только на интерфейсы?
С уважением.
← →
Alexander Panov © (2005-08-05 13:09) [4]Mx © (05.08.05 13:03) [2]
для интерфейсов правила, которые описаны в Wizard-dll - те же самые.
← →
Mx © (2005-08-05 13:11) [5]Ну вот, расстроили меня... :(
← →
DiamondShark © (2005-08-05 13:16) [6]А в чём расстройство-то?
Если интерфейсы используются только как фича языка, то действуют все те же правила, что и для любых других конструкций.
← →
Digitman © (2005-08-05 13:39) [7]
> Mx © (05.08.05 13:03) [2]
используешь ты интерфейсы или не используешь - без разницы, правила использования ShareMem едины и касаются динам.типов данных, передаваемых как параметры dll-вызовов и получаемых как результаты этих вызовов
разницы нет никакой - то ли ты вызвал из ДЛЛ непосредственно ф-цию SomeFunction(), то ли ты вызвал некий метод некоего интерфейса SomeInterface.SomeMethod()
ShareMem необходим всегда в случаях когда вызывающий и вызываемый код используют разные экз-ры менеджеров памяти, но при этом есть оправданная необходимость выделения памяти в одном коде, а перераспределения/освобождения - в другом
ShareMem, будучи подключенным, будет использован как единый менеджер памяти для обоих кодов
Sharemem необходим в случаях , когда взаимодействующие модули (передающие между собой, например, данные дин.типов) разрабатываются в среде Делфи/BCB и при сборке этих модулей использованы разные зн-я опции Build With Run-Time Packages
Sharemem не требует своего использования, если все взаимодействующие модули были собраны с опцией Build With Run-Time Packages = True, при этом они будут использовать единый менеджер памяти, который находится в ран-тайм-библиотеке, загружаемой в АП процесса единожды и используемой впоследствии всеми модулями.
← →
Mx © (2005-08-05 14:22) [8]
> Digitman © (05.08.05 13:39) [7]
> разные экз-ры менеджеров памяти
Вот оказывается в чем проблема? Гм... тогда сделаю пакеты, тем более потом еще и в Kilyx"е будут использовать.
← →
GLFox © (2005-08-05 15:16) [9]А лучше всего использовать PChar, чтобы не тащить ShareMem с собой.
← →
Mx © (2005-08-05 15:37) [10]Есть консольное приложение:
program CnConsole;
{$APPTYPE CONSOLE}
type
TConsoleClient = class(TInterfacedObject, IClientInterface)
end;
function CreateAppObject: IApplicationInterface; external "SomeLib.dll";
var
Client: IClientInterface;
App: IApplicationInterface;
begin
App := CreateAppObject;
try
Client := TConsoleClient.Create;
App.Connect(...);
except
on E: Exception do
WriteLn(...);
end;
WriteLn("Press ENTER to continue...");
ReadLn;
end.
В этой самой SomeLib.dll имеем класс:type
TConceptApplication = class(TInterfacedObject, IApplicationInterface)
private
...
end;
var
ConceptApplication: TConceptApplication;
implementation
...
end.
и экспортируемая фукнция:function CreateAppObject: IConceptApplication;
begin
Result := TConceptApplication.Create;
end;
Так вот, созданный объект App не разрушается, а вроде как счетчик ссылок при выходе должен был сам на нуль свалить. Почему так?
← →
Mx © (2005-08-05 15:39) [11]Ну почему нельзя редактировать своё сообщения? Порой такие несуразные ошибки!
С типами я в примере напутал. Результат у CreateAppObject естественно IApplicationInterface.
← →
GLFox © (2005-08-05 15:46) [12]А непосредственно сделать так:
App := nil
не пробовал?
← →
Alexander Panov © (2005-08-05 15:50) [13]Mx © (05.08.05 15:37) [10]
Так вот, созданный объект App не разрушается,
А в какой момент он должен быть у тебя разрушен?
← →
Mx © (2005-08-05 15:50) [14]
> GLFox © (05.08.05 15:46) [12]
Так пробовал - работает. Но почему автоматом этого не происходит? В GUI такого не было. Неужели в чем-то различие? Или я что-то упустил?
← →
Mx © (2005-08-05 15:54) [15]
> Alexander Panov © (05.08.05 15:50) [13]
> А в какой момент он должен быть у тебя разрушен?
Я так понимаю, когда приложение закрывается. Ну, например, как с дин. массивами. Еще раз пересмотрел свой старый GUI проект, там такой объект (правда не из DLL сконструированный) записывается в поле формы в ее конструкторе. Разрушается он самостоятельно, никаких nil ему не присваивается.
← →
GLFox © (2005-08-05 16:01) [16]>Mx © (05.08.05 15:54) [15]
>> Alexander Panov © (05.08.05 15:50) [13]
>> А в какой момент он должен быть у тебя разрушен?
>Я так понимаю, когда приложение закрывается.
Когда приложение закрывается винда и так уничтожит все связанные с ним ресурсы.
А вообще, рекомендую почитать книгу Эрика Хармона "Разработка COM-приложений в среде Delphi". Книга хоть и не новая, но про интерфесы там весьма доходчиво написано.
← →
Digitman © (2005-08-05 16:04) [17]
> Mx © (05.08.05 15:50) [14]
ты его нигде не разрушаешь, вот он и не разрушается у тебя.
время жизни переменной Арр равно времени жизни процесса, и все это время интерфейсная ссылка, которую ты получил, "живет" в этой переменной
← →
Mx © (2005-08-05 16:28) [18]
> Digitman © (05.08.05 16:04) [17]
> время жизни переменной Арр равно времени жизни процесса
Это так, безусловно! Но когда приложение закрывается процесс таки завершается (правда тут Windows рулит, а не RTL, понимаю). Я хоче понять почему в случае с формой такого не было? Может ввиду ее явного разрушения в деструкторе Application?
← →
Digitman © (2005-08-05 16:34) [19]
> когда приложение закрывается процесс таки завершается
так точно.
а раз завершается, то при этом немедленно и безусловно прекращают существование ВСЕ объекты, существовавшие когда-либо при "жизни" процесса в ЕГО контексте, в ЕГО адресном пространстве
и при этом неважно какой был процесс - консольный или GUI или сервис ..
← →
Digitman © (2005-08-05 16:36) [20]
> вроде как счетчик ссылок при выходе должен был сам на нуль
> свалить
он и "свалил" ... в ходе исполнения неявного кода, который скрывается за последним оператором программы END.
← →
Mx © (2005-08-05 16:36) [21]
> Digitman © (05.08.05 16:34) [19]
Но деструктор-то не выполняется, а в случае с GUI выполняется. Почему?
← →
Digitman © (2005-08-05 16:38) [22]а ты что, брейпойнт в тело деструктора ставил ? и вроде бы как не поймал этот брейкпойнт при закрытии приложения ?
или как ты это пытался определить ?
← →
Mx © (2005-08-05 16:40) [23]
> Digitman © (05.08.05 16:38) [22]
Вначале поставил breakpoint, но потом подумал раз приложение закрывается можно не поймать. Тады сделал ShellExecute на web-страницу. Не сработало. Если явно App := nil, то все естественно ok.
← →
Digitman © (2005-08-05 16:51) [24]
> Mx © (05.08.05 16:40) [23]
> можно не поймать
да, в ряде случаев можно и не поймать
просто заведи себе хорошую и полезную привычку оформлять код , работающий с интерф.объектами, след.образом
App := CreateAppObject;
try
.. поработали с App ..
finally
App := nil; //безусловно уничтожили
end;
и все недоразумения сразу исчезнут
← →
Mx © (2005-08-05 16:56) [25]
> Digitman © (05.08.05 16:51) [24]
Привычку такую я со всем динамическим завел. Но ведь не всегда у нас код ограничен одним методом, верно. Сделаю явное присваивание. Все-равно, это отладочная прога.
← →
Digitman © (2005-08-05 17:10) [26]
> ведь не всегда у нас код ограничен одним методом
да, не всегда.
но всегда можно найти решение ...
например, в дан.случае можно не заводить статическую переменную вообще, можно сделать так :
begin
with CreateAppObject do
try
...
except
on E: Exception do
WriteLn(...);
end;
//<- здесь объект уже неявно уничтожен
..
end.
← →
Mx © (2005-08-05 17:17) [27]
> Digitman © (05.08.05 17:10) [26]
Прикол в том, что и так не работает! Я именно такую конструкцию применил в самый первый раз. Никакого деструктора не вызывается.
← →
Digitman © (2005-08-05 17:49) [28]потому что RefCount > 0 на этот момент
← →
Digitman © (2005-08-05 17:50) [29]точнее RefCount > 1
← →
Digitman © (2005-08-05 18:22) [30]дело в том что в методе TInterfacedObject.AfterConstruction() сч-к ссылок увеличивается на единицу, после чего (в момент запроса у этого объекта интерфейса и возврата его в кач-ве результата работы ф-ции CreateAppObject) для использования в WITH сч-к увеличивается еще на единицу
т.е. в варианте
with CreateAppObject do begin
messagebox(0, pchar(inttostr(getrefcount)), "", mb_ok or mb_setforeground);
//<- RefCount = 1 ! нужен вызов _release;
end;
объект не будет разрушен
а в варианте
messagebox(0, pchar(inttostr(CreateAppObject. getrefcount)), "", mb_ok or mb_setforeground);
все будет в порядке - объект будет успешно уничтожен
← →
Mx © (2005-08-05 21:59) [31]Значит [26] все-таки не совсем корректен. Я так и не понял почему в случае с формой разрушение происходит корректно? Какие есть соображения?
← →
Бурундук © (2005-08-06 16:34) [32]Кстати, советую почитать
http://www.delphikingdom.com/asp/viewitem.asp?catalogid=759
(+ комментарии)
← →
Mx © (2005-08-06 20:17) [33]
> Бурундук © (06.08.05 16:34) [32]
Спасибо за ссылку! Действительно, если произвести инициализацию в операторе var, то объект все-таки разрушается по завершении. Впредь буду знать.
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2005.08.28;
Скачать: [xml.tar.bz2];
Память: 0.53 MB
Время: 0.059 c