Форум: "Corba";
Текущий архив: 2005.02.20;
Скачать: [xml.tar.bz2];
ВнизCOM Найти похожие ветки
← →
vk220 © (2004-05-07 17:01) [0]Проблема такая: есть интерфейс Data.
Есть подчинённые ему интерфейсы Field.
При создании Field функция _AddRef вызывается конструктором Field.
А при уничтожении Field:
Field := nil;
проверяется счётчик ссылок (в модуле System функ. _Release) и т.к. их не 0,
Field просто не удаляется... соответсвенно проц. BeforeDestruction не вызывается.
Я не очень хорошо знаю технологию COM, если кто-нибудь понял изложенное выше, помогите,
пожалуйста.
Также буду благодарен за ссылки, где можно почитать о COM. (в Delphi)
← →
clickmaker © (2004-05-07 18:47) [1]http://rsdn.ru/summary/266.xml
← →
Бином Ньютоныч (2004-05-07 20:25) [2]Не нужно вызывать AddRef в конструкторе. Как я понял, Field возвращается клиенту методами Data, и Data должен жить, пока жив хотя-бы один Field. Тогда следует в том или ином виде использовать аггрегацию. Пожалуй, наиболее наглядно это можно сделать так:
IField = interface;
IData = interface
procedure GetField(out Field: IField);
end;
TData = class(..., IData)
procedure GetField(out Field: IField);
end;
TField = class(..., IField)
FController: IUnknown;
constructor Create(Controller: IUnknown);
end;
procedure TData.GetField(out Field: IField);
begin
Field:=TField.Create(Self);
end;
constructor TField.Create(Controller: IUnknown);
begin
FController:=Controller;
end;
Это очень простой случай, зато все наглядно. Также внимательно присмотрись к реализации в TComObject методов IUnknown для самого IUnknown и для других интерфейсов, держа в уме, что аггрегироваться объект может не только по IUnknown, но и по любому другому интерфейсу. Главное четко представлять, когда объект должен оперировать собственным счетчиком ссылок, а когда переправлять вызов контроллеру.
← →
vk220 © (2004-05-08 19:47) [3]>Не нужно вызывать AddRef в конструкторе
Я убрал из конструктора эту команду. Счётчик ссылок тем не менее увеличивается. Как у Data, так и у Field.
Я вот чего не могу понять: Счётчик ссылок увеличивается/уменьшается автоматически, или мне надо самому вызывать _AddRef и _Release?
Увеличивается он ещё как, а вот убавляться совсем не хочет.
← →
Бином Ньютоныч (2004-05-09 09:01) [4]>vk220 © (08.05.04 19:47) [3]
Как видишь, в моем примере нет ни одного явного вызова методов IUmknown, тем не менее объекты уничтожаются в нужный момент. Интерфейс в Delphi относится к типам с автоматическим управлением временем жизни. Компилятор сам вставляет вызовы AddRef и Release при присвоении/освобождении интерфейсных переменных. Самому делать эти вызовы нужно только в редких, особых случаях, четко представляя себе происходящее.
var
A: IData;
B: IField;
A:=TData.Create;
Здесь будет создан объект TData, получен указатель на его интерфейс IData и, в процессе присвоения его переменной А, будет вызван метод AddRef.
A.GetField(B);
Здесь тоже самое для объекта TField. Кроме того, указатель на IUnknown TData будет сохранен в поле FController объекта TField, при этом будет автоматически вызван IUnknown.AddRef объекта TData. Теперь счетчик будет содержать 2.
A:=nil
Будет вызван метод Release объекта TData, но объект не будет уничтожен, т.к. сохраняется ссылка на него в TField.FController.
B:=nil;
Здесь будет вызван Release объекта TField, при этом его счетчик ссылок обнулится, в результате чего будет автоматически вызван его деструктор. В процессе уничтожения объекта будет автоматически освобождена ссылка, хранящаяся в поле FController с вызовом Release объекта TData. Его счетчик ссылок обнулится и он тоже будет уничтожен.
Если же у тебя при освобождении интерфейсной переменной объект не уничтожается, то это значит, что где-то осталась неосвобожденная ссылка, либо был лишний несбалансированный вызов AddRef. Возможно, ты используешь перекрестные ссылки:
TData хранит IField, а TField хранит IData.
В таких случаях следует одно из полей сделать типа Pointer и при обращении к нему использовать прямое привидение. При этом автоматический подсчет ссылок производиться не будет.
Страницы: 1 вся ветка
Форум: "Corba";
Текущий архив: 2005.02.20;
Скачать: [xml.tar.bz2];
Память: 0.47 MB
Время: 0.042 c