我将ICallFrame接口转换为Delphi,但不确定如何处理ICallFrame::Invoke方法。
这是定义:
根据文档,varargs 指令仅适用于外部例程和 cdecl 调用约定。这有点奇怪,因为 Invoke 声明为
这是定义:
HRESULT Invoke(
void *pvReceiver,
...
);
根据文档,varargs 指令仅适用于外部例程和 cdecl 调用约定。这有点奇怪,因为 Invoke 声明为
STDMETHODCALLTYPE
,即 __stdcall
,这是一种被调用者清理的约定。但是可变参数函数不能是被调用者清理的,因为被调用者不知道传递了多少参数。如果使用 Visual Studio 进行此操作,是否存在某种编译器魔法?即使编译器魔法使用 cdecl,Delphi 编译器也不接受此操作(因为它不是外部函数)E2070 Unknown directive: 'varargs'
。ICallFrame = interface(IUnknown)
['{D573B4B0-894E-11d2-B8B6-00C04FB9618A}']
// other methods left out
function Invoke(pvReceiver: PVOID): HRESULT; cdecl; varargs;
end;
根据Rudy的回答,似乎这个方法可行:
type
TfnInvoke = function(this: Pointer; pvReceiver: Pointer): HRESULT; cdecl varargs;
implementation
function GetInterfaceMethod(const intf; methodIndex: dword) : pointer;
begin
Result := Pointer(pointer(dword_ptr(pointer(intf)^) + methodIndex * SizeOf(Pointer))^);
end;
...
var
Invoker: TfnInvoke;
...
// Don't forget IUnknown methods when counting!
Invoker := GetInterfaceMethod(myIntf, 21);
Invoker(myIntf, FObject, 11, 17.3);
我会用这个进行测试并回报结果... 编辑:已测试并且可行。
type TfnInvoke = function(this, pvReceiver: Pointer): HRESULT; cdecl varargs;
。它在Delphi Tokyo中可用。 - Rudy Velthuiscallobj.h
中ICallFrame::Invoke()
的实际 SDK 声明,它是使用STDMETHODCALLTYPE
声明的,这解析为__stdcall
。因此,我不明白varargs
如何能够与此接口配合使用。通常情况下,varargs
完全不兼容 COM,因此我不知道ICallFrame
的设计者在想什么。 - Remy Lebeaustdcall
简单地不支持可变参数,就这样。只有cdecl
支持。因此,如果编译器在参数列表末尾看到...
,它会强制使用cdecl
调用约定。忽略关于this
参数的部分,它与此无关。 - Remy Lebeaustdcall
和cdecl
以相同的方式传递参数值,但是它们以不同的方式清理参数。因此,使用正确的调用约定非常重要,否则将会破坏调用栈。 - Remy Lebeau