Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Как получить объект по интерфейсу? [D7, WinXP]


Страницы:   1 2

Mx ©   (2005-04-22 17:16:00) 

Привет, Мастера! Согласно "ребрендингу" поменял свой ник, который и мне порядочно надоел, но это к делу не относится...

Вопрос может совсем дикий, но он в названии (ламером прошу не обзывать). Имеем переменную типа IUnknown, можно ли получить ссылку на сам объект? Или эта ссылка и есть то, что мне надо?


Набережных С.   (2005-04-25 19:58:00) [1]


> vuk ©   (25.04.05 19:12) [24]

Насчет сохранения интерфейсных свойств - возможно. Я не в курсе этого момента, упустил, надо будет глянуть, спасибо. Однако я его встречал где-то в местах, не связанных с этим механизмом. Но если так - тем более заплата, для расширения функциональности без кардинальной переделки существующих механизмов. Не было такой возможности изначально заложено - вот и пришлось изворачиваться:)

> это скорее можно отнести к внутренним механизмам VCL.

Это я имел в виду : предназначив для чисто внутреннего спользования
В любом случае, такой подход считаю крайне нежелательным. Хотя я и сам, случалось, упомянал такой способ на этом форуме, но всегда при этом предупреждал, что лучше так не делать. Вот и сейчас не промолчал:))


vuk   (2005-04-25 19:12:00) [2]

to Mx ©   (23.04.05 16:29) [22]:
>Кажется я понял что имеется ввиду (про отсутствие объекта).
Я не знаю, что Вы там поняли, но намекну, что COM-объекты могут быть реализованы на языке, не поддерживающем ООП в принципе.

to Набережных С. ©   (23.04.05 16:48) [23]:
>IntfGetComponent ввели, я убежден, как заплатку, предназначив
>для чисто внутреннего использования.
IntfGetComponent введен именно для получения ссылки на компонент, реализующий интерфейс. Используется при сохранении в потоки published свойств интерфейсного типа. Я бы не сказал, что это заплатка, это скорее можно отнести к внутренним механизмам VCL.


Набережных С.   (2005-04-23 16:48:00) [3]


> MBo ©   (23.04.05 14:49)
> техника, использованная в TComponent.IntfGetComponent

Имхо, эта "техника" столь же очевидная, сколь и неправильная. И IntfGetComponent ввели, я убежден, как заплатку, предназначив для чисто внутреннего использования.

А код в [11] действительно красивый. Сам по себе, безотносительно к каким-либо теориям:)


Mx   (2005-04-23 16:29:00) [4]

Кажется я понял что имеется ввиду (про отсутствие объекта).


Набережных С.   (2005-04-23 16:10:00) [5]


> Mx ©   (23.04.05 13:08) [19]

Что-то ты где-то не там читал. Или не так понял. Даже когда есть ссылка "на какой-либо интерфейс какого либо объекта". Ибо спецификация COM не устанавливает ни малейших ограничений на РЕАЛИЗАЦИЮ интерфейса. И уж тем более не устанавливает НИКАКИХ правил формирования структуры объекта.


MBo   (2005-04-23 14:49:00) [6]

>vuk ©   (22.04.05 20:43) [16]
Конечно, при использовании любых хакерских недокументированных штучек автор должен себе отдавать отчет о риске и о границах применимости.

Про IBackDoor - что имелось в виду - техника, использованная в TComponent.IntfGetComponent - со введением специального интерфейса именно для обеспечения возможности Subj-евой цели?


Mx   (2005-04-23 13:08:00) [7]


> DiamondShark ©   (23.04.05 12:59) [18]
>
> За интерфейсом может не стоять вообще никакого "объекта"
> в классическом понимании.

Я имел ввиду случай, когда есть переменная, ссылающаяся на какой-либо интерфейс какого-либо объекта


DiamondShark   (2005-04-23 12:59:00) [8]


> Наверняка, объекты других языков тоже таковы, потому код
> (хотя я там мало что понял) скорее всего универсальный.

За интерфейсом может не стоять вообще никакого "объекта" в классическом понимании.


Mx   (2005-04-23 11:48:00) [9]


> vuk ©   (22.04.05 20:43) [16]
>
> ТОлько для нормальной работы
> интерфейс должен быть гарантированно реализован классом
> Delphi.
>


Помнится в справке Delphi я встречал, что объект в памяти формируется с соблюдением совместимости с COM. Наверняка, объекты других языков тоже таковы, потому код (хотя я там мало что понял) скорее всего универсальный.


vuk   (2005-04-22 20:43:00) [10]

to MBo:
Оно конечно да, достать можно. ТОлько для нормальной работы интерфейс должен быть гарантированно реализован классом Delphi. А иначе можно такого надоставать, что мало не покажется. Уж лучше IBackdoor. Во всяком случае спасает от упадания лицом в салат. Кстати, в VCL как раз такой способ используется - TComponent реализует IInterfaceComponentReference.


MBo   (2005-04-22 20:08:00) [11]

>Это откуда ?
из borland-овских ньюсгрупп, 2002 год, автор указан.
Интересно, что функция была в виде задачи - Что оно делает?- (идентификаторы приводились несамообъясняющие)


Набережных С.   (2005-04-22 18:40:00) [12]


> MBo ©   (22.04.05 18:13) [11]

Ай-я-яй! Чистое хакерство, как не стыдно!?
:))))))
Присоединяюсь к Skier ©   (22.04.05 18:20) [13]. Действительно классно!


Skier   (2005-04-22 18:20:00) [13]

>MBo ©   (22.04.05 18:13) [11]
Классно ! Это откуда ?


Mx   (2005-04-22 18:13:00) [14]

Спасибо, мужики, все узнал что хотел. Добавлю свойство в интерфейс, а то в натуре какой-то огород получается ненужный.

P.S. А с IBackdoor'ом прикольно! Взял на заметку.


MBo   (2005-04-22 18:13:00) [15]

оно?


function GetImplementingObject(const I: IInterface): TObject;
const
 AddByte = $04244483; // opcode for ADD DWORD PTR [ESP+4], Shortint
 AddLong = $04244481; // opcode for ADD DWORD PTR [ESP+4], Longint
type
 PAdjustSelfThunk = ^TAdjustSelfThunk;
 TAdjustSelfThunk = packed record
   case AddInstruction: longint of
     AddByte : (AdjustmentByte: shortint);
     AddLong : (AdjustmentLong: longint);
 end;
 PInterfaceMT = ^TInterfaceMT;
 TInterfaceMT = packed record
   QueryInterfaceThunk: PAdjustSelfThunk;
 end;
 TInterfaceRef = ^PInterfaceMT;
var
 QueryInterfaceThunk: PAdjustSelfThunk;
begin
 Result := Pointer(I);
 if Assigned(Result) then
   try
     QueryInterfaceThunk := TInterfaceRef(I)^.QueryInterfa­ceThunk;
     case QueryInterfaceThunk.AddInstruc­tion of
       AddByte: Inc(PChar(Result), QueryInterfaceThunk.Adjustment­Byte);
       AddLong: Inc(PChar(Result), QueryInterfaceThunk.Adjustment­Long);
       else     Result := nil;
     end;
   except
     Result := nil;
   end;
end;

Hallvard Vassbotn


Skier   (2005-04-22 18:10:00) [16]

Примерно так :

IYourInterface = interface(...)
['{C9FC9806-2C28-4C3E-B265-C441398AC574}']
function GetInstance : TObject;
property Instance : TObject read GetInstance; //"слабая" ссылка
end;


DiamondShark   (2005-04-22 18:10:00) [17]


> Нет, оба пишу сам.

Тогда можно использовать приватный интерфейс как backdoor:

IBackdoor = interface
['{B094B0E6-ADE3-4818-8165-3F9F99123EC8}']
function GetObject: TObject;
end;

TMyImpl = class(TObject, IInterface, IBacdoor)
...
end;


Набережных С.   (2005-04-22 18:08:00) [18]


> Mx   (22.04.05 17:36) [4]

Даже если объект твой, все равно не надо так делать, ибо противоречит самой концепции интерфейса, а такие нарушения рано или поздно выходят боком. Тем более, что предоставив через интерфейс доступ к объекту ты тем самым как раз и уничтожишь его абстрагированность. Напротив, добавив в интерфейс метод проверки интересующего свойства ты ничего не теряешь. Просто те объекты, которые такого свойства не имеют, будут возвращать результатом этого метода E_NOTIMPL. Вполне обычная практика.

> Mx   (22.04.05 18:04) [7]

Да, так нормально. И они отличаются:)


Mx   (2005-04-22 18:04:00) [19]

А все-таки? И как из переменной A получить указатель на B или они все-таки не отличаются?

var
 A: IInterface;
 B: TInterfacedObject;
begin
 B := TInterfacedObject.Create;
 ...
 A := B as IInterface;
 ...
end;


Mx   (2005-04-22 18:01:00) [20]

Нет, оба пишу сам. Один - хранит списки экземпляров другого, а вернее список одного из интерфейсов этих экземпляров. Во многом это ради удобства и абстракции, но в принципе можно хранить и сами объекты...

P.S. Я прикинул, наверное, такое свойство и интерфейсу нужно, потому как будет еще сторонняя прога, которая с этим делом будет работать и там иногда эта инфа тоже понадобится, так что вынесу свойство в интерфейс.


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо