Delphi interface from DLL
Using Delphi XE.
When trying to access a Delphi interface object from a DLL, it fails if I try to do it dynamically versus statically.
The interface unit in the dll implements a function to return an instance of the interface. When linked statically, the result is nil when entering the function and everything works. When loading dynamically, the result is non-nil, so when the assignment to result is being done, the IntFCopy code sees it as non-nil and so tries to free it before the assignment, which raises an exception.
Any insight would be appreciated.
The DLL includes testinterfaceload_u and exports testInt:
library testinterfaceload;
uses
SimpleShareMem,
SysUtils,
Classes,
testinterfaceload_u in 'testinterfaceload_u.pas';
{$R *.res}
exports testInt;
begin
end.
testinterfaceload_u is the unit that defines the interface and simple class implementation:
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.
Here's a console app that loads the dll and calls the testInt function to return the interface:
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
DLLHandl开发者_JAVA技巧e := 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.
TTestInt
needs to be declared as stdcall
in the code that imports the DLL.
Your interface definition should contain a GUID and each function needs the "stdcall" declaration. Without it you might run into problems..
type ITestInt = interface
['{AA286610-E3E1-4E6F-B631-F54BC6B31150}']
procedure Test; stdcall
end;
Taking a stab at things: Try adding a calling method (stdcall, pascal, etc.) to the declaration of the dll's testInt function and the TTestInt fnction type in the console app.
necroposting mode on
function testInt : ITestInt;
begin
//debugger shows result as non-nil ITestInt even before this assignment, when dynamic
result := TTestInt.Create;
end;
should be a procedure like this
procedure testInt(out intf: ITestInt); stdcall;
begin
intf := TTestInt.Create;
end;
精彩评论