将C stdcall接口方法中的变量参数转换为Delphi
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了将C stdcall接口方法中的变量参数转换为Delphi相关的知识,希望对你有一定的参考价值。
我正在将ICallFrame接口转换为Delphi,我不知道如何处理ICallFrame::Invoke方法。
这是定义:
HRESULT Invoke(
void *pvReceiver,
...
);
根据文档,varargs指令仅适用于外部例程,并且仅适用于cdecl调用约定。
这有点奇怪,因为用STDMETHODCALLTYPE
声明了Invoke,因此__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);
我将用此测试并报告回来...编辑:测试和工作。
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.Ctrl.pad中。
Update
这似乎是一种界面的方法。
不确定这是否有效,但我会尝试:
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。
以上是关于将C stdcall接口方法中的变量参数转换为Delphi的主要内容,如果未能解决你的问题,请参考以下文章