2011-02-06 72 views
1

編輯:啞問題,已經修復。 Form1nil,因爲我沒有爲它指定一個新的TForm1,我忘記了Delphi不會爲你像C++那樣做。從C++調用的Delphi DLL在顯示錶單時崩潰

我有一個Delphi DLL,我想用於我的C++程序的GUI,因此只是爲了初學者,我創建了一個窗體,並且有一個函數將顯示導出的窗體,以便C++可以調用它。但是,程序在調用該函數時會崩潰。這是我的代碼。 (我使用德爾福2010)

德爾福部分:

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++代碼:

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; 

該程序打印 「找到它@」,然後崩潰。如果我在Delphi DLL中註釋掉Form1.Show(),它不會崩潰,並且函數返回3(由printf測試)。我是否缺少一些初始化或某些東西?謝謝。

+0

@David我不知道該怎麼做。 – Okey 2011-02-06 18:49:02

回答

2

它激怒的原因是var Form1: TForm1;未被初始化。

的原因,var Form1: TForm1;沒有初始化,很可能是因爲你把unit Main成DLL項目,但它最初是從一個Delphi VCL項目,您自動創建名單上有Form1來了。

自動創建列表意味着Delphi .dpr將初始化表單。

現在你需要手動創建表單,所以你需要這3個新的程序從DLL導出,並有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! – 2011-02-06 17:00:03