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;
Я не расследовал это, но вы можете получить некоторые проблемы с подсчетом ссылок...