Tuesday, June 13, 2006

 

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.
Comments:
I haven't tried this way yet Leonardo, I must try some time. The way I did it was this way:
http://z505.com/pascal/ExportClasses/ExportClassFPC.zip

It is in the freepascal contributed units section.

I haven't experimented with it in too many real world applications yet and would like criticism if there is anything wrong with that way that I have done it?

As you can see in that example I used a shared memory manager so that AnsiStrings can be shared across DSO/DLL/EXE/ELF.

L505
 
Sorry, above posting chopped off some of the URL.

Here is the URL:
Export Class
 
I've delphi 7 and when compiling your test.dpr it give me the error file not found: 'dynlibs.dcu'. Is it because I've an older version of Delphi?
I've also seen the .zip solution of the previous comment and I want to know if possible what I have to cut if I only need the .exe .
Thanks in advice!
 
Justo lo que andaba buscando y es tan facil como crear la unidad y luego coger las clases desde la dll de la unidad creada, supongo que se peuden importar varias clases, estoy realizando un programa de facturacion y tengo varias clases que crear en una dll para simplificar el codigo, ya que actualmente el ejecutable es muy pesado.
 
Post a Comment



<< Home

This page is powered by Blogger. Isn't yours?