Delphi интерфейс из DLL - PullRequest
       35

Delphi интерфейс из DLL

2 голосов
/ 09 июля 2011

Использование Delphi XE.

При попытке получить доступ к объекту интерфейса Delphi из библиотеки DLL происходит сбой, если я пытаюсь сделать это динамически, а не статически.

Модуль интерфейса в dll реализуетфункция для возврата экземпляра интерфейса.При статическом связывании результат равен нулю при входе в функцию, и все работает.При динамической загрузке результат не равен нулю, поэтому, когда выполняется присвоение результата, код IntFCopy видит его как ненулевой и пытается освободить его перед назначением, что вызывает исключение.

Любое понимание будет приветствоваться.

DLL включает testinterfaceload_u и экспортирует testInt:

library testinterfaceload;

uses
  SimpleShareMem,
  SysUtils,
  Classes,
  testinterfaceload_u in 'testinterfaceload_u.pas';

{$R *.res}
exports testInt;

begin
end.

testinterfaceload_u - это модуль, который определяет интерфейс и реализацию простого класса:

unit testinterfaceload_u;

interface

type ITestInt = interface
 procedure Test;
end;

{this function returns an instance of the interface}
function testInt : ITestInt; stdcall; export;

type

TTestInt = class(TInterfacedObject,ITestInt)
 procedure Test;
end;



implementation

function testInt : ITestInt;
begin
//debugger shows result as non-nil ITestInt even before this assignment, when dynamic
  result := TTestInt.Create;  
end;

procedure TTestInt.Test;
var
  i : integer;
begin
  i := 0;
end;



end.

Вот консольное приложение, которое загружает dll и вызывает функцию testInt для возврата интерфейса:

program testload_console;

{$APPTYPE CONSOLE}

uses

SysUtils,
  Windows,
  testinterfaceload_u in 'testinterfaceload_u.pas';

type
  TTestInt = function() : ITestInt;

var
   TestInt: TTestInt;
   NewTestInt : ITestInt;
   DLLHandle: THandle;
begin
  DLLHandle := LoadLibrary('testinterfaceload.dll');
  if (DLLHandle < HINSTANCE_ERROR) then
       raise Exception.Create('testinterfaceload.dll can not be loaded or not found. ' +     SysErrorMessage(GetLastError));
  @TestInt := GetProcAddress(DLLHandle, 'testInt');
  try
    if Assigned(TestInt) then
      NewTestInt := TestInt;
  except on e:Exception do
    WriteLn(Output,e.Message);
  end;
end.

Ответы [ 3 ]

5 голосов
/ 09 июля 2011

TTestInt должен быть объявлен как stdcall в коде, который импортирует DLL.

5 голосов
/ 04 декабря 2012

Ваше определение интерфейса должно содержать GUID, и каждая функция нуждается в объявлении "stdcall".Без этого вы можете столкнуться с проблемами ..

type ITestInt = interface
  ['{AA286610-E3E1-4E6F-B631-F54BC6B31150}']
  procedure Test; stdcall
end;
3 голосов
/ 09 июля 2011

Делаем попытку: попробуйте добавить вызывающий метод (stdcall, pascal и т. Д.) К объявлению функции testInt dll и типа функции TTestInt в консольном приложении.

...