c++ - 将 Delphi 类传递给需要具有 __thiscall 方法的类的 C++ 函数/方法

标签 c++ delphi dll calling-convention

我有一些 MSVC++ 编译的 DLL,我为其创建了类 COM(精简版)接口(interface)(抽象 Delphi 类)。其中一些类具有需要指向对象的指针的方法。这些 C++ 方法是使用 __thiscall 调用约定(我无法更改)声明的,这与 __stdcall 类似,只是传递了一个 this 指针在 ECX 寄存器上。

我在 Delphi 中创建类实例,然后将其传递给 C++ 方法。我可以在 Delphi 中设置断点,并看到它命中了我的 Delphi 类中公开的 __stdcall 方法,但很快我得到一个 STATUS_STACK_BUFFER_OVERRUN 并且应用程序必须退出。是否可以在 Delphi 方面模拟/处理 __thiscall?如果我传递一个由 C++ 系统实例化的对象,那么一切都很好,并且该对象的方法被调用(如预期的那样),但这没有用 - 我需要传递 Delphi 对象。

Edit 2010-04-19 18:12 This is what happens in more detail: The first method called (setLabel) exits with no error (though its a stub method). The second method called (init), enters then dies when it attempts to read the vol parameter.

C++ 端

#define SHAPES_EXPORT __declspec(dllexport) // just to show the value
class SHAPES_EXPORT CBox
{
  public:
    virtual ~CBox() {}
    virtual void init(double volume) = 0;
    virtual void grow(double amount) = 0;
    virtual void shrink(double amount) = 0;
    virtual void setID(int ID = 0) = 0;
    virtual void setLabel(const char* text) = 0;
};

德尔福方面

IBox = class
public
  procedure destroyBox; virtual; stdcall; abstract;
  procedure init(vol: Double); virtual; stdcall; abstract;
  procedure grow(amount: Double); virtual; stdcall; abstract;
  procedure shrink(amount: Double); virtual; stdcall; abstract;
  procedure setID(val: Integer); virtual; stdcall; abstract;
  procedure setLabel(text: PChar); virtual; stdcall; abstract; 
end;

TMyBox = class(IBox)
protected
  FVolume: Double;
  FID: Integer;
  FLabel: String; //
public
  constructor Create;
  destructor Destroy; override;
  // BEGIN Virtual Method implementation
  procedure destroyBox; override; stdcall;             // empty - Dont need/want C++ to manage my Delphi objects, just call their methods
  procedure init(vol: Double); override; stdcall;      // FVolume := vol;
  procedure grow(amount: Double); override; stdcall;   // Inc(FVolume, amount);
  procedure shrink(amount: Double); override; stdcall; // Dec(FVolume, amount);
  procedure setID(val: Integer); override; stdcall;    // FID := val;
  procedure setLabel(text: PChar); override; stdcall;  // Stub method; empty.
  // END Virtual Method implementation      
  property Volume: Double read FVolume;
  property ID: Integer read FID;
  property Label: String read FLabel;
end;

我本来有一半希望单独使用 stdcall 来工作,但是有些事情搞砸了,不确定是什么,也许与正在使用的 ECX 寄存器有关?将不胜感激。

Edit 2010-04-19 17:42 Could it be that the ECX register needs to be preserved on entry and restored once the function exits? Is the this pointer required by C++? I'm probably just reaching at the moment based on some intense Google searches. I found something related, but it seems to be dealing with the reverse of this issue.

最佳答案

让我们假设您已经使用 VMT 创建了一个 MSVC++ 类,它完美地映射到 Delphi 类的 VMT 中(我从来没有这样做过,我只是相信你这是可能的)。现在您可以从 MSVC++ 代码调用 Delphi 类的虚方法,唯一的问题是 __thiscall 调用约定。由于 __thiscall 在 Delphi 中不受支持,可能的解决方案是在 Delphi 端使用代理虚方法:

已更新

type
  TTest = class
    procedure ECXCaller(AValue: Integer);
    procedure ProcProxy(AValue: Integer); virtual; stdcall;
    procedure Proc(AValue: Integer); stdcall;
  end;

implementation

{ TTest }

procedure TTest.ECXCaller(AValue: Integer);
asm
  mov   ecx,eax
  push  AValue
  call  ProcProxy
end;

procedure TTest.Proc(AValue: Integer);
begin
  ShowMessage(IntToStr(AValue));
end;

procedure TTest.ProcProxy(AValue: Integer);
asm
   pop  ebp            // !!! because of hidden delphi prologue code
   mov  eax,[esp]      // return address
   push eax
   mov  [esp+4],ecx    // "this" argument
   jmp  Proc
end;

关于c++ - 将 Delphi 类传递给需要具有 __thiscall 方法的类的 C++ 函数/方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2667925/

相关文章:

c++ - 是否可以从构造函数自动推导出基类模板参数?

c++ - 如何在用户不可见的情况下每月下载并执行一个文件?

delphi - 如何从使用 TFileOpenDialog 中回收内存?

delphi - ocks5代理互联网

c# - 将 .exe 项目转换为类库

c# - 无法加载DLL : The specified module could not be found

c++ - 使用后丢弃 DLL 的资源

c++ - 为什么对一个 vector 进行多线程操作的速度很慢?

c++ - 尝试使用对另一个类的对象的引用

android - 如何在 android 上安装 Firebird 驱动程序以便我可以连接 FireDac