Ato*_*ian 6 c++ delphi dll calling-convention
我有一些MSVC++编译的DLL,我已经创建了COM-like(lite)接口(抽象的Delphi类).其中一些类具有需要指向对象的指针的方法.这些C++方法是使用__thiscall调用约定(我无法更改)声明的,就像__stdcall一样,除了这个指针在ECX寄存器上传递.
我在Delphi中创建类实例,然后将其传递给C++方法.我可以在Delphi中设置断点并看到它在我的Delphi类中遇到暴露的__stdcall方法,但很快我得到一个STATUS_STACK_BUFFER_OVERRUN并且应用程序必须退出.是否可以在Delphi方面模拟/处理__thiscall?如果我传递一个由C++系统实例化的对象,那么一切都很好,并调用该对象的方法(如预期的那样),但这没用 - 我需要传递Delphi对象.
编辑2010-04-19 18:12这就是更详细的情况:第一个调用的方法(setLabel)退出时没有错误(尽管它是一个存根方法).第二种方法叫做(init),然后在尝试读取vol参数时进入 .
C++ Side
#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;
};
Run Code Online (Sandbox Code Playgroud)
德尔福方面
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;
Run Code Online (Sandbox Code Playgroud)
我有一半期望单独使用stdcall工作,但是有些事情搞砸了,不确定是什么,或许与使用ECX寄存器有关?非常感谢帮助.
编辑2010-04-19 17:42可能是ECX寄存器需要在进入时保留并在函数退出后恢复吗?是这个 指针由C++要求?我可能只是根据一些激烈的Google搜索来实现这一目标.我找到了相关的东西,但似乎正在处理这个问题的反面.
让我们假设您已经创建了一个具有 VMT 的 MSVC++ 类,它完美地映射到 Delphi 类的 VMT(我从未这样做过,我只是相信您这是可能的)。现在您可以从 MSVC++ 代码中调用 Delphi 类的虚拟方法,唯一的问题是 __thiscall 调用约定。由于Delphi中不支持__thiscall,因此可能的解决方案是在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;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2706 次 |
| 最近记录: |