Delphi DLL, вызываемая из C ++, дает сбой при отображении формы - PullRequest
1 голос
/ 06 февраля 2011

РЕДАКТИРОВАТЬ: тупой вопрос, уже исправлен.Form1 было nil, потому что я не назначил ему новый TForm1, я забыл, что Delphi не делает этого для вас, как C ++.

У меня есть DLL-библиотека Delphi, которую я хочу использовать дляGUI моей программы на C ++, поэтому для начала я создал форму, и у меня есть функция, которая будет показывать форму, которая экспортируется, чтобы C ++ мог ее вызывать.Однако программа вызывает сбой при вызове функции.Вот мой код(Я использую Delphi 2010)

Часть delphi:

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;

Программа выводит "Found it @"а потом вылетает.Если я закомментирую Form1.Show() в DLL-библиотеке Delphi, она не будет аварийно завершена, и функция вернет 3 (протестировано printf).Я пропускаю некоторую инициализацию или что-то?Спасибо.

1 Ответ

2 голосов
/ 06 февраля 2011

Причина этого заключается в том, что 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 реализации функции, так как исключения и другие зависящие от языка функции времени выполнения не должны пересекать границы DLL .

Вероятно, вы должны сделать аналогичные вещи для освобождения других потенциально распределенных частейдинамической памяти тоже.

- jeroen

...