Wednesday, March 18, 2009

How to import an Object from a dll?

Some time ago, a boss of a company that i used to work gave a course of COM & DCOM technologies because he thought packages (bpl's) wasn't working as one might expect (actually the problem wasn't packages at all, but that's another story). He was trying to change packages to COM interfaces as a way to share application's objects with Dll's (dynamic link libraries). Thanks god we solved the problem without changing the more than 50 packages the application uses.

Well, there's a way to export objects (and classes) from dll's. The first thing you have to do is to code a Unit containing the classes you want to export:
{ MyClasses.pas }

unit MyClasses;

interface

uses
Classes;

type
TMyClass = class
public
constructor create;
(* Here you can create the methods you want *)
end;

implementation

constructor TMyClass.create;
begin
writeln('Create!!!');
end;

end.
The second thing to do is to create the the library project and include the recent unit:
{ interfaces.dpr }

library interfaces;

uses
Classes,
MyClasses;

function GetMyExportedClass: Pointer; cdecl;
begin
Result := GetClass('TMyClass');
end;

exports
GetMyExportedClass;

end.
After this you have to create a program that loads the dll and execute the exported function (GetMyExportedClass) to create TMyClass objects:

{ test.dpr }

program test;

{$APPTYPE CONSOLE}

uses
{$ifdef fpc}
dynlibs,
{$endif}
SysUtils,
Classes;

var
{$ifdef fpc}
mHandle: TLibHandle;
{$else}
mHandle: THandle;
{$endif}

var
myObj: TObject;
_EC: function : Pointer; cdecl;

begin
(* load shared library *)
if (pointer(mHandle) = nil) then
begin
(* Try to load shared library *)
mHandle := LoadLibrary('lib.dll');
if (pointer(mHandle) <> nil) then
begin
writeln('Loaded!');
(* instantiate a TMyExportedClass object *)
_EC := GetProcAddress(mHandle, 'GetMyExportedClass');
if (pointer(@_EC) <> nil) then
begin
(* Initialize exported class *)
myObj := TObject(_EC).create;
(* work with exported class
:
:
... and free exported class *)
myObj.free;
end;
(* unload shared library *)
{$ifdef fpc}
UnLoadLibrary(mHandle);
{$else}
FreeLibrary(mHandle);
{$endif}
end;
end;
end.
The code above exports an object from a dll, but as the object must be type casted to TObject, you can't view it's methods. In the next post, i'll show you how to create interfaces that allows to view the object's metods.

1 comment:

Unknown said...

hi dear
I just red your interesting document on importing object from dll.
May i have source code for "How to import an Object from a dll?"
thanks