将Delphi类传递给需要__thiscall方法的类的C ++函数/方法 [英] Pass a Delphi class to a C++ function/method that expects a class with __thiscall methods

查看:259
本文介绍了将Delphi类传递给需要__thiscall方法的类的C ++函数/方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have some MSVC++ compiled DLL's for which I have created COM-like (lite) interfaces (abstract Delphi classes). Some of those classes have methods that need pointers to objects. These C++ methods are declared with the __thiscall calling convention (which I cannot change), which is just like __stdcall, except a this pointer is passed on the ECX register.

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

I create the class instance in Delp then pass it on to the C++ method. I can set breakpoints in Delphi and see it hitting the exposed __stdcall methods in my Delphi class, but soon I get a STATUS_STACK_BUFFER_OVERRUN and the app has to exit. Is it possible to emulate/deal with __thiscall on the Delphi side of things? If I pass an object instantiated by the C++ system then all is good, and that object's methods are called (as would be expected), but this is useless - I need to pass Delphi objects.


编辑2010-04-19 18:12 这是更详细的情况:第一个
方法调用(setLabel)
错误(虽然它的stub方法)。
第二个方法叫做(init),输入
,然后在尝试读取
vol 参数时输出。

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

Delphi Side

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寄存器有关?非常感谢。

I would have half expected using stdcall alone to work, but something is messing up, not sure what, perhaps something to do with the ECX register being used? Help would be greatly appreciated.


编辑2010-04-19 17:42 可能是ECX寄存器需要
保存在入口和恢复一旦
功能退出?是C ++所需的
指针吗?我可能是
只是到达基于
一些强烈的Google搜索的时刻。 I
找到相关的,但它
似乎正在处理这个问题的反向

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.


推荐答案

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

Let us assume that you have created a MSVC++ class with VMT that maps perfectly into the VMT of a Delphi class (I have never done it, I just believe you that is possible). Now you can call the virtual methods of a Delphi class from MSVC++ code, the only problem is __thiscall calling convention. Since __thiscall is not supported in Delp the possible solution is to use proxy virtual methods on Delphi side:

UPDATED

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;

这篇关于将Delphi类传递给需要__thiscall方法的类的C ++函数/方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆