我有一些MSVC++编译的DLL,为其创建了COM-类似(精简版)接口(抽象Delphi类)。其中一些类具有需要对象指针的方法。这些C++方法使用__thiscall调用约定声明(我无法更改),它与__stdcall非常相似,只是将this指针传递到ECX寄存器上。
我在Delphi中创建类实例,然后将其传递给C++方法。我可以在Delphi中设置断点,并看到它命中我的Delphi类中公开的__stdcall方法,但很快我就会遇到STATUS_STACK_BUFFER_OVERRUN,并且应用程序必须退出。在Delphi方面是否可能模拟/处理__thiscall?如果我传递由C++系统实例化的对象,则一切正常,并且调用该对象的方法(如预期所示),但这是无用的 - 我需要传递Delphi对象。
我本来以为只使用stdcall就足够了,但有些东西出问题了,不确定是什么,也许与使用ECX寄存器有关?非常感谢您的帮助。
编辑2010-04-19 17:42:是不是必须在进入函数时保留ECX寄存器并在函数退出时恢复它?C++需要“this”指针吗?目前我可能只是基于一些强烈的谷歌搜索。我找到了something related,但它似乎处理的是这个问题的反向情况。
我在Delphi中创建类实例,然后将其传递给C++方法。我可以在Delphi中设置断点,并看到它命中我的Delphi类中公开的__stdcall方法,但很快我就会遇到STATUS_STACK_BUFFER_OVERRUN,并且应用程序必须退出。在Delphi方面是否可能模拟/处理__thiscall?如果我传递由C++系统实例化的对象,则一切正常,并且调用该对象的方法(如预期所示),但这是无用的 - 我需要传递Delphi对象。
编辑于2010年04月19日18:12 更详细地说,发生了以下情况:第一个被调用的方法(setLabel)退出时没有错误(虽然它是一个存根方法)。第二个被调用的方法(init)进入后,在尝试读取vol参数时失败。
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寄存器有关?非常感谢您的帮助。
编辑2010-04-19 17:42:是不是必须在进入函数时保留ECX寄存器并在函数退出时恢复它?C++需要“this”指针吗?目前我可能只是基于一些强烈的谷歌搜索。我找到了something related,但它似乎处理的是这个问题的反向情况。
this
参数放在ECX中,但你的Delphi代码希望它在第一个堆栈参数中。所有其他堆栈参数也都错了一个。我有一种技术可以解决这个问题。我唯一担心使用它来处理这段代码的是类的析构函数。我会尝试在今天晚些时候写一篇描述。我的方法将基于我在无窗口富文本API上的工作:http://pages.cs.wisc.edu/~rkennedy/windowless-rtf - Rob Kennedy