2015-08-15 32 views
9

我需要调用非静态C++成员函数的Delphi thiscall调用约定

因此我需要使用thiscall调用约定。

德尔福不支持这种调用约定。

因此,在我可以调用任何成员函数之前,我必须手动推送堆栈中的参数。

asm 
    mov ecx, myClassPointer 
    end; 

这工作正常,但我正在寻找更好的方式来做到这一点。

此刻,我在调用函数之前每次都用classpointer调用asm代码,这并不好。

因为我不是德尔福专家,我想知道你是否可以声明自己的调用约定或自动调用那些thiscall类的方法。

+2

我为微软的丰富编辑界面写了一些[这个适配器](http://www.cs.wisc.edu/~rkennedy/windowless-rtf),它错误地忽略了调用约定。我的适配器在两个方向上都包装接口,所以Delphi代码可以调用微软的代码,微软的代码可以调用回Delphi接口,并且每一方都认为另一方提供了预期的调用约定。也许你会觉得它很有用。 –

回答

4

德尔福的register调用约定使用前三个参数的寄存器。前两个是EAXEDX,它们在thiscall调用约定中未使用,可以设置为任何您喜欢的。这些寄存器中的第三个是ECX

thiscall传递堆栈中的所有参数,register传递堆栈上的剩余参数。 registerthiscall都有被调用者清除在堆栈上传递的参数。

所以你可以做的是声明一个register函数,虚拟参数为EAXEDX。您仍然可以将其包装在不同的函数中,以便于调用,但至少现在可以声明包装函数inline

请注意,参数在堆栈上的推送顺序在thiscallregister之间不同,因此需要反向参数以匹配。

5

您有以下选择:

  • 写适配器的ASM调用的函数。这是你目前的解决方案,正如你所知道的那样,这种方法很脆弱和尴尬。
  • 编写一个提供互操作友好界面的C++适配器。

后面的选项在我看来是正确的解决方案。 C++代码不适合互操作。通过interop暴露C++类是完全错误的。它给消费者提出了不合理的要求。合理的方法包括在Win32中发现的COM和简单的C风格互操作。

编写一个适配的C++ DLL,它使用不合理的C++类并公开一个适当的互操作性友好界面。适配器是用C++编写的,因此可以使用C++代码。但随后它会导出一个互操作性友好的界面变体,可以从任何工具链轻松调用。

+0

请您详细说明适配器部分。我从来没有听说过delphi函数调用的终止。基本上它应该在调用函数/过程本身之前调用具有所需类指针的asm代码。 – ChrisB

+0

否适配器是原始的thiscall C++和您的Delphi代码之间的一个层。它可以调用thiscall C++,并将其重新导出为适当的互操作安全接口。 –

+1

请参阅我在[我的答案](http://stackoverflow.com/a/32035356/95954)中提到的文章。它广泛地描述了适配器代码。 –

3

正如David所说,你可以继续使用汇编器,但有更好的方法。我编写了一个名为"Using C++ Objects in Delphi"的文章,广泛decribes,用代码,你可以如何使用这两种可行的替代办法:

  • 编写出口,简单地使用C++类和揭露每个方法为C风格的函数是C层简单的功能。这很简单,但从德尔福方面使用有点尴尬。
  • 写一个COM层,这听起来不那么容易。我需要C++大师的一些帮助才能做到这一点。本文将介绍这些步骤,您可以将它们应用到班级(1到1)。

我个人更喜欢COM层。德尔福方面使用起来要容易得多。

本文还介绍了编写此类代码或使用此类对象时可能遇到的一些问题。阅读全部内容。