Передача записи, содержащей метод, между хост-приложением и DLL - PullRequest
5 голосов
/ 08 декабря 2011

Можно ли (без использования пакетов времени выполнения или DLL общей памяти) передавать тип записи между хост-приложением и модулем DLL, где тип записи содержит функции / процедуры (Delphi 2006 и выше)?

Давайте для простоты предположим, что наш тип Record не содержит никаких полей String (поскольку для этого, конечно, требуется DLL-библиотека Sharemem), и вот пример:

TMyRecord = record
  Field1: Integer;
  Field2: Double;
  function DoSomething(AValue1: Integer; AValue2: Double): Boolean;
end;

Итак, чтобы указатьэто просто: могу ли я передать «экземпляр» TMyRecord между хост-приложением и DLL (в любом направлении), без использования пакетов времени выполнения или DLL общей памяти, и выполнить функцию DoSomething как из Host EXE, так и из DLL?

Ответы [ 2 ]

7 голосов
/ 08 декабря 2011

Я бы не советовал, работает ли он или нет.Если вам нужно, чтобы DLL работала с TMyRecord экземплярами, самый безопасный вариант - использовать простые функции экспорта DLL, например:

DLL:

type
  TMyRecord = record 
    Field1: Integer; 
    Field2: Double; 
  end; 

function DoSomething(var ARec: TMyRecord; AValue1: Integer; AValue2: Double): Boolean; stdcall;
begin
  ...
end;

exports
  DoSomething;

end.

Приложение:

type 
  TMyRecord = record  
    Field1: Integer;  
    Field2: Double;  
  end;  

function DoSomething(var ARec: TMyRecord; AValue1: Integer; AValue2: Double): Boolean; stdcall; external 'My.dll';

procedure DoSomethingInDll;
var
  Rec: TMyRecord;
  //...
begin 
  //...
  if DoSomething(Rec, 123, 123.45) then
  begin
    //...
  end else
  begin
    //...
  end;
  //...
end; 
4 голосов
/ 08 декабря 2011

Если я правильно понял ваш вопрос, то вы можете сделать это, вот один из способов сделать это:

testdll.dll

library TestDll;

uses
  SysUtils,
  Classes,
  uCommon in 'uCommon.pas';

{$R *.res}

procedure TakeMyFancyRecord(AMyFancyRecord: PMyFancyRecord); stdcall;
begin
  AMyFancyRecord^.DoSomething;
end;

exports
  TakeMyFancyRecord name 'TakeMyFancyRecord';

begin
end.

uCommon.pas <- используется как приложением, так и dll, единицей, где определена ваша необычная запись </p>

unit uCommon;

interface

type
  PMyFancyRecord = ^TMyFancyRecord;
  TMyFancyRecord = record
    Field1: Integer;
    Field2: Double;
    procedure DoSomething;
  end;

implementation

uses
  Dialogs;

{ TMyFancyRecord }

procedure TMyFancyRecord.DoSomething;
begin
  ShowMessageFmt( 'Field1: %d'#$D#$A'Field2: %f', [ Field1, Field2 ] );
end;

end.

и, наконец, тестовое приложение, файл -> новое -> приложение vcl формы, нажмите кнопку на форме, включите uCommon.pas в предложение использования, добавьте ссылку на внешний метод

procedure TakeMyFancyRecord(AMyFancyRecord: PMyFancyRecord); stdcall;
  external 'testdll.dll' name 'TakeMyFancyRecord';

и в событие нажатия кнопки добавьте

procedure TForm1.Button1Click(Sender: TObject);
var
  LMyFancyRecord: TMyFancyRecord;
begin
  LMyFancyRecord.Field1 := 2012;
  LMyFancyRecord.Field2 := Pi;
  TakeMyFancyRecord( @LMyFancyRecord );
end;

ОТКАЗ:

  • работает в D2010;
  • компилируется на моей машине!

наслаждайтесь!


Дэвид Хеффернан 'edit

Чтобы быть на 100% ясным, выполняемый метод DoSomething - это метод, определенный в DLL. Метод DoSomething, определенный в EXE, никогда не выполняется в этом коде.


...