Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "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.064 c
3-1106449961
SarDoX
2005-01-23 06:12
2005.02.20
Поиск в БД


14-1106904607
VFV
2005-01-28 12:30
2005.02.20
Загрузка


3-1106650872
Urvin
2005-01-25 14:01
2005.02.20
Как реализовать бд на основе FireBird


4-1105008771
Брат
2005-01-06 13:52
2005.02.20
Поместить окно поверх остальных


3-1106116686
MakNik
2005-01-19 09:38
2005.02.20
найти всех детей узла дерева





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский