开发者

Delphi DLL called from C++ crashes when showing a form

开发者 https://www.devze.com 2023-02-08 16:46 出处:网络
EDIT: Dumb question, already fixed. Form1 was nil because I didn\'t assign it a new TForm1, I forgot Delphi doesn\'t do that for you like C++.

EDIT: Dumb question, already fixed. Form1 was nil because I didn't assign it a new TForm1, I forgot Delphi doesn't do that for you like C++.

I have a Delphi DLL that I want to use for the GUI of my C++ program, so just for starters, I created a form, and have a function that will show the form which is exported so that C++ can call it. However, the program crashes when it calls the function. Here is my code. (I am using Delphi 2010)

The delphi part:

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.

And here is the C++ code:

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;

The program prints "Found it @ " and then crashes. If I comment out Form1.Show() in the Delphi DLL, it doesn't crash, and the function returns 3 (tested by printf). Am I missing some initialization or something? Thanks.


The reason it crases is that the var Form1: TForm1; is not initialized.

The reason that the var Form1: TForm1; is not initialized, is most likely because you put the unit Main into a DLL project, but it originally came from a Delphi VCL project where you had Form1 on the auto-creation list.

The auto-creation list means that the Delphi .dpr will initialize the form.

Now you need to manually create the form, so you need to export these 3 new routines from your DLL, and have the C++ DLL call them:

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;

In addition, you should put a try...except block around the implementation of your ShowForm function implementation, as exceptions and other language dependent run-time features should not cross DLL boundaries.

You probably should do similar things for releasing other potentially allocated pieces of dynamic memory too.

--jeroen

0

精彩评论

暂无评论...
验证码 换一张
取 消