Delphi thiscall调用约定
Delphi thiscall calling convention
我需要调用非静态c++成员函数
因此我需要使用thiscall
调用约定。
Delphi不支持这个调用约定。
因此,在调用任何成员函数之前,我必须手动将参数压入堆栈。
asm
mov ecx, myClassPointer
end;
这个工作很好,但我正在寻找一个更好的方法来做到这一点。
在调用函数之前,我每次都用类指针调用asm代码,这不是很好。
由于我不是Delphi专家,我想知道您是否可以声明自己的调用约定或自动调用这些thiscall类方法。
您有以下选项:
- 在asm中编写适配器以调用该函数。这是您当前的解决方案,正如您所知,这种方法既脆弱又笨拙。写一个c++适配器,提供一个互操作友好的界面。
在我看来,后一个选项是正确的解决方案。c++代码不适合互操作。通过互操作公开c++类是完全错误的。它对消费者提出了不合理的要求。合理的方法包括在Win32中发现的COM和纯C风格的互操作。
编写一个自适应的c++ DLL,消耗不合理的c++类,并提供适当的互操作友好界面。适配器是用c++编写的,因此能够使用c++代码。但随后它导出了一个对互操作友好的接口变体,可以从任何工具链中轻松调用。
Delphi的register
调用约定为前三个参数使用寄存器。前两个是EAX
和EDX
,它们在thiscall
调用约定中不使用,可以设置为您喜欢的任何值。第三个寄存器是ECX
。
thiscall
在堆栈上传递所有参数,register
在堆栈上传递剩余参数。register
和thiscall
都有在堆栈上传递的被调用者cleanup参数。
所以你可以做的是声明一个register
函数,为EAX
和EDX
使用虚拟参数。您仍然可以将其包装在一个不同的函数中,以使其更容易调用,但至少现在可以将包装器函数声明为inline
。
请注意,在thiscall
和register
之间,参数在堆栈上被压入的顺序是不同的,所以你需要反转参数来匹配。
正如David已经说过的,您可以继续使用汇编器,但是还有更好的方法。我写了一篇名为"在Delphi中使用c++对象"的文章,用代码详细描述了如何使用这两种可行的替代方法:
- 编写一个C层,导出C风格的函数,这些函数只使用c++类,并将每个方法作为简单函数公开。这是相当简单的,但是从Delphi端使用有点尴尬。写一个COM层,这并不像听起来那么容易。我需要一位c++大师的帮助才能把它做好。本文描述了这些步骤,您可以将它们一对一地应用到您的类中。
我个人更喜欢com层。从Delphi端使用它要容易得多。
本文还描述了在编写此类代码或使用此类对象时可能遇到的一些问题。通读
- 为什么在 x64 中忽略__stdcall调用约定?
- 窗口调用约定
- 我应该提到纯虚函数中的调用约定吗?
- 如何使用gcc指定stdcall调用约定
- Clang:x86 FPU调用约定
- 该标准是否说明了例外和不同调用约定的共存
- Clang++的InterlockedExchange的32位调用约定错误,但MSVC可以
- std::sort & comp - 调用约定?
- 如何为类 /块 /范围选择C 调用约定
- DLL 的"good"调用约定是什么?
- 结构中重载运算符的调用约定
- 'ShowSUM':__declspec(dllexport)不能应用于具有__clrcall调用约定的函数
- x86-64 调用约定中的返回值
- 内联功能和调用约定
- 正在直接显示筛选器中调用约定
- 何时使用`__fastcall`调用约定
- 为C++结构定义显式析构函数如何影响调用约定
- 对类方法的正确约定调用
- 如何使用 Visual C++ 中的 Delphi 寄存器调用约定调用函数?
- 使用C调用约定调用函数模板专门化