gpt4 book ai didi

delphi - 将 C stdcall 接口(interface)方法中的变量参数转换为 Delphi

转载 作者:行者123 更新时间:2023-12-03 15:51:25 43 4
gpt4 key购买 nike

我正在转换 ICallFrame Delphi 的接口(interface),我不知道如何处理 ICallFrame::Invoke方法。

这是定义:

HRESULT Invoke(
void *pvReceiver,
...
);

根据文档 varargs指令仅适用于外部例程并且仅适用于 cdecl 调用约定。

这有点奇怪,因为 Invoke 是用 STDMETHODCALLTYPE 声明的,因此是 __stdcall,这是一个被调用者干净的约定。但是可变参数函数不能是被调用者干净的,因为被调用者不知道传递了多少参数。如果使用 Visual Studio 执行此操作,是否存在某种编译器魔法?

即使编译器魔法使用 cdecl,Delphi 编译器也不接受它(因为它不是外部的)E2070 未知指令:'varargs'

ICallFrame = interface(IUnknown)
['{D573B4B0-894E-11d2-B8B6-00C04FB9618A}']
// other methods left out
function Invoke(pvReceiver: PVOID): HRESULT; cdecl; varargs;
end;

根据鲁迪的回答,这似乎可行:

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);

我将对此进行测试并报告......编辑:经过测试并且有效。

最佳答案

Stdcall 不能使用变量参数。任何采用可变参数的 C 或 C++ 函数都必须是 __cdecl,因为只有在该调用约定中,知道传递了多少个参数的调用方(代码)才会清理堆栈。即使默认调用约定是 stdcall,var args 函数也将是 cdecl

Delphi 无法生成这样的函数,但它可以使用varargs使用现有的外部 C 函数(在 DLL 或 .obj 文件中)指令。

所以 C(或 C++)函数就像

HRESULT Invoke(void *pvReceiver, ...);

应转换为:

function Invoke(pvReceiver: Pointer); cdecl; varargs;

请注意,您在 Delphi 声明中省略了 ... 部分。当您使用 varargs 指令时会进行假设。

这允许您在 Delphi 中使用它,就像在 C 或 C++ 中一样:

Invoke(someReceiver, 17, 1.456);
<小时/>

另一个例子:例如众所周知的 C 函数 printf():

int printf(const char *format, ...);

声明为

function printf(format: PAnsiChar {args}): Integer; cdecl; varargs;

System.Win.Crtl.pas中。

更新

这似乎是一个接口(interface)的方法。

不确定这是否有效,但我会尝试:

type
TInvoke = function(Intf: IInterface; pvReceiver: Pointer): HRESULT; cdecl varargs;
// No semicolon between cdecl and varargs.

并将其用作:

MyResult := TInvoke(@myIntf.Invoke)(myIntf, someReceiver, 11, 17.3);

此方法可能已声明为 __stdcall (通过 STDMETHODCALLTYPE 宏),但即使如此,如果它是可变参数,(VC++) 编译器也会生成 __cdecl,雷米·勒博 (Remy Lebeau) 发现 in Raymond Chen's blog

关于delphi - 将 C stdcall 接口(interface)方法中的变量参数转换为 Delphi,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52372337/

43 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com