2011-02-06 11 views
1

EDIT:ダムの質問が既に修正されています。 Form1nilだったので、私はそれに新しいTForm1を割り当てなかったので、C++のようにDelphiがそれをしないのを忘れてしまった。フォームを表示しているときにC++から呼び出されたDelphi DLLがクラッシュする

私は自分のC++プログラムのGUIに使いたいDelphi DLLを持っているので、まずフォームを作成し、エクスポートされたフォームを表示してC++で呼び出せるようにする関数を持っています。ただし、関数を呼び出すと、プログラムがクラッシュします。ここに私のコードです。 "@それを見つけた"

HMODULE h = LoadLibrary("delphidll.dll"); 

if (!h) { 
    printf("Failed LoadLibrary (GetLastError: %i)\n", GetLastError()); 

    return 0; 
} 

FARPROC p = GetProcAddress(h, "ShowForm"); 

if (p) 
    printf("Found it @ %p\n", p); 
else 
    printf("Didn't find it\n"); 

((int(__cdecl *)(int))p)(34); 

system("PAUSE"); 

return 0; 

プログラムを印刷し、その後クラッシュ:

unit Main; 

interface 

uses 
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
    Dialogs, Tabs, ComCtrls; 

type 
    TForm1 = class(TForm) 
    TabControl1: TTabControl; 
    TabSet1: TTabSet; 
    private 
    { Private declarations } 
    public 
    { Public declarations } 
    end; 

var 
    Form1: TForm1; 

function ShowForm(i: Integer) : Integer; export; cdecl; 

exports 
    ShowForm name 'ShowForm'; 

implementation 

{$R *.dfm} 

function ShowForm(i: Integer) : Integer; export; cdecl; 
begin 
    Form1.Show(); 

    Result := 3; // random value, doesn't mean anything 
end; 

end. 

そしてここでC++のコードがある:デルファイの部分は

を(私は、Delphi 2010を使用しています)。 Delphi DLLでForm1.Show()をコメントアウトすると、クラッシュせず、関数は3を返します(printfによってテストされます)。私はいくつかの初期化や何かを欠いていますか?ありがとう。

+0

@David私にはわからない。 – Okey

答えて

2

ひびが入っている理由は、var Form1: TForm1;が初期化されていないことです。あなたはDLLプロジェクトにunit Mainを置くため

var Form1: TForm1;が初期化されていないことを理由は、最も可能性が高いですが、それはもともとあなたが自動作成リストにForm1を持っていたのDelphi VCLプロジェクトから来ました。

自動作成リストは、Delphi .dprがフォームを初期化することを意味します。

今、あなたがあなたのDLLからこれらの3つの新しいルーチンをエクスポートする必要があるので、手動でフォームを作成する必要があり、およびC++ DLLは、それらを呼び出すいます

function CreateForm() : Integer; export; cdecl; 
begin 
    try 
    Application.CreateForm(TForm1, Form1); 
    Result := 0; 
    except 
    Result := -1; 
    end; 
end; 

function DestroyForm() : Integer; export; cdecl; 
begin 
    try 
    if Assigned(Form1) then 
    begin 
     FreeAndNil(Form1); 
     Application.ProcessMessages(); 
    end; 
    Result := 0; 
    except 
    Result := -1; 
    end; 
end; 

function DestroyApplication() : Integer; export; cdecl; 
begin 
    try 
    FreeAndNil(Application); 
    Result := 0; 
    except 
    Result := -1; 
    end; 
end; 

また、あなたがtry...exceptブロックを置く必要がありますShowForm関数実装の実装については、exceptions and other language dependent run-time features should not cross DLL boundariesとなります。

他の潜在的に割り当てられたダイナミックメモリをリリースするには、おそらく同様の作業を行う必要があります。

--jeroen

+0

Jeroen、いい答えですが、OPはすでにその結論に達し、Qを編集しました! –

+0

彼の編集ではない私の答えの2つの重要なことがあります:try/exceptブロックとアプリケーションの解放です。 –

+0

@Jeroenなぜあなたは 'ProcessMessages'を呼び出すのかわかりませんし、アプリケーションを解放する理由もありません。 –

関連する問題