Delphi: как реализовать QueryInterface из IUnknown?

В Делфи, IUnknown объявляется как:

function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;

Примечание: выходной параметр не типизирован

в своем TInterfacedObject потомок мне нужно обрабатывать QueryInterface, поэтому я могу вернуть объект, который поддерживает запрошенный интерфейс:

function TFoo.QueryInterface(const IID: TGUID; out Obj): HResult;
begin
   if IsEqualGUID(IID, IFooBar) then
   begin
      Obj := (TFooBar.Create(Self) as IFooBar);
      Result := S_OK;
   end
   else
      Result := inherited QueryInterface(IID, {out}Obj);
end;

проблема приходит на линию:

Obj := (TFooBar.Create(Self) as IFooBar);

Делфи жалуется:

оператор неприменим к этому типу операнда

очевидно, что я не знаю, как и что назначить нетипизированный

3 ответов


вам нужно ввести-cast левый сторона инструкции присваивания. Таким образом, нетипизированный параметр имеет тип, и компилятор знает, как присвоить ему значение:

IFooBar(Obj) := TFooBar.Create(Self) as IFooBar;

обратите внимание, что вы нарушаете один из требования COM. Если вы запрашиваете интерфейс, вы должны иметь возможность запросить результат для IUnknown и всегда получать одно и то же значение:

Foo.QueryInterface(IUnknown, I1);
I1.QueryInterface(IFooBar, B);
B.QueryInterface(IUnknown, I2);
Assert(I1 = I2);

Если вы просто хотите создать новые объекты типа TFooBar, затем дайте вашему интерфейсу метод, который генерирует те:

function TFoo.NewFooBar: IFooBar;
begin
  Result := TFooBar.Create(Self) as IFooBar;
end;

на основе реализации TObject.GetInterface в системе.pas я бы предложил следующее:

  Pointer(Obj) := TFooBar.Create(Self);

помимо замечаний Роба о нарушении правил здесь, вы можете даже преуспеть с этой конструкцией:

function TFoo.QueryInterface(const IID: TGUID; out Obj): HResult;
begin
   if IsEqualGUID(IID, IFooBar) then
      Result := TFooBar.Create(Self).QueryInterface(IID, obj)
   else
      Result := inherited QueryInterface(IID, {out}Obj);
end;

Я не расследовал это, но вы можете получить некоторые проблемы с подсчетом ссылок...