COM に似た (lite) インターフェイス (抽象 Delphi クラス) を作成した MSVC++ コンパイル済み DLL がいくつかあります。これらのクラスの一部には、オブジェクトへのポインターを必要とするメソッドがあります。これらの C++ メソッドは、__thiscall呼び出し規約 (私は変更できません) で宣言されます。これは、 thisポインターが ECX レジスターで渡されることを除いて、__stdcall と同じです。
Delphi でクラス インスタンスを作成し、それを C++ メソッドに渡します。Delphi でブレークポイントを設定し、Delphi クラスで公開されている __stdcall メソッドにヒットするのを確認できますが、すぐに STATUS_STACK_BUFFER_OVERRUN が発生し、アプリを終了する必要があります。Delphi 側で __thiscall をエミュレート/処理することは可能ですか? C++ システムによってインスタンス化されたオブジェクトを渡すと、すべて問題なく、そのオブジェクトのメソッドが (予想どおり) 呼び出されますが、これは役に立ちません。Delphi オブジェクトを渡す必要があります。
Edit 2010-04-19 18:12これは、より詳細に何が起こるかです: (setLabel) と呼ばれる最初のメソッドは、エラーなしで終了します (ただし、スタブ メソッド)。(init) と呼ばれる 2 番目のメソッドは、 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;
};
デルファイ側
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 ECX レジスタをエントリ時に保存し、関数が終了したら復元する必要があるのでしょうか? thisポインターは C++ で必要ですか? 私はおそらく、いくつかの激しいGoogle検索に基づいて、現時点でたどり着いています. 関連するものを見つけましたが、この問題の逆を扱っているようです。