[fpc-devel] bug ID #4855

Marc Weustink marc.weustink at cuperus.nl
Mon Apr 10 12:09:32 CEST 2006


Michael Van Canneyt wrote:
> 
> 
> On Mon, 10 Apr 2006, Peter Vreman wrote:
> 
>>> Buys Regarding this bug #4855 I need to get it fixed..
>>>
>>>
>>>
>>> The issue like this...  I have 2 parts to my system...
>>>
>>>
>>>
>>> The EXE ... and a DLL
>>>
>>>
>>>
>>> In the DLL I have an exported function that returns an Interface...
>>>
>>>
>>>
>>> Function dosomething( const aObjectInt : ISomeInt ) : ISomeOtherInt
>>>
>>>
>>>
>>> This fails and causes the application to die..
>>>
>>> However if I put the same function inside the EXE it works fine.
>>
>>
>> The DLL has it's own memory manager. The EXE can't access the memory
>> allocated in the DLL.

Maybe I can clearify some. Before this bug got submitted, I had a 
converstaion with the submittor on IRC.

> Of course it can, when it gets a pointer ?
> It can't free it, of course, but that can be solved.

The dll is returning a COM interface, so it doesn't have to be freed in 
the exe.

> 
> Is the function called from a FPC application or a Delphi application ?
> If from delphi, try setting the 'stdcall' calling convention.
> 
> I think some more explanation is in order so we can reproduce and solve
> the problem.

The main problem is that a COM interface returned as a funtion result by 
fpc is different than a result returned by delphi

All interface funtions are declared with stdcall.

I cannot recall if the calling exe was a delphi or fpc produced one, but 
for this problem it doesn't really matter. What matters is mixing a 
delphi/fpc exe with and fpc/delphi dll

the dll exports a function like

function SomeFunc: IUnknown; stdcall;

The exe imports this function. Assigning the function result results in 
an AV  (I tested this with a delphi dll and a fpc exe)


When the interface is passed as a var in a procedure call, it works OK.

Marc


=======================================================================

library DllProject;
{$IFDEF FPC}{$mode objfpc}{$H+}{$ENDIF}
uses
   SysUtils,
   Classes;

type
   iTest = interface
     ['{B1473B32-DDB5-452C-86BE-9C4D85E68495}']
     function dotest( const aIn : Integer ): Integer; stdcall;
   end;

   TTest = class(TInterfacedObject, iTest )
     function dotest( const aIn : Integer ): Integer; stdcall;
   end;

function TTest.dotest( const aIn : Integer ): Integer; stdcall;
begin
   result := aIn + 1;
end;

Function test(): ITest; stdcall;
begin
   result := TTest.create();
end;

procedure testproc(out T: ITest); stdcall;
begin
   T := TTest.create();
end;

exports
    test, testproc;

begin
end.

=======================================================================

program project1;

{$mode objfpc}{$H+}

uses
   classes, windows;

type
   ITest = interface
     ['{B1473B32-DDB5-452C-86BE-9C4D85E68495}']
     function dotest( const aIn : Integer ): Integer; stdcall;
   end;

   TTest = Function(): ITest; stdcall;

   TTestproc = procedure(out T: ITest); stdcall;

var
   lLib: cardinal;
   doTest: TTest;
   doTestProc: TTestproc;
   fTest: ITest;
begin
   lLib   := loadlibrary( 'dllProject.dll' );
   pointer(doTest) := getprocaddress( lLib, 'test' );
   pointer(doTestProc) := getprocaddress( lLib, 'testproc' );

   if assigned( doTest ) then
   begin
     fTest := doTest();
     WriteLN(FTest.dotest(1));
   end;

   if assigned(doTestProc) then
   begin
     doTestProc(fTest);
     WriteLN(FTest.dotest(2));
   end;
end.



More information about the fpc-devel mailing list