Hola a todos
Hasta ahora en las DLL almacenaba funciones o procedimientos sueltos que posteriormente se utilizaban en el programa. Ahora estoy experimentando con la idea de encapsular clases completas para utilizarla después y ya he conseguido la parte del encapsulado que realizo de la siguiente forma:
Uso una unidad que comparten tanto la DLL como el proyecto y es donde solo se definen las declaraciones abstractas e interfaces publicas de la clase a encapsular (aquí no hay nada en la implementación):
Código Delphi
[-]
unit UMyObjectInterface;
interface
type
IMyInterface = interface(IInterface)
['{ECEF5846-F1B3-4ECE-9113-16B2C7962F04}']
function algoMas: integer;
procedure mostrar;
end;
TMyAbstractObject = class abstract (TInterfacedObject, IMyInterface)
function algoMas: integer; virtual; abstract;
procedure mostrar; virtual; abstract;
end;
TClassMyObject = class of TMyAbstractObject;
TGetMyExportedObject = function: TClassMyObject; cdecl;
implementation
end.
Y para la DLL declaro una clase que hereda de la clase abstracta y es en donde se implementan los procedimientos y funciones necesarios
Código Delphi
[-]
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes,
DateUtils, UMyObjectInterface;
type
TMyObject = class(TMyAbstractObject)
function algoMas: integer; override;
procedure mostrar; override;
end;
function GetMyExportedClass: TClassMyObject; cdecl;
exports
GetMyExportedClass;
implementation
uses
Vcl.Dialogs;
function GetMyExportedClass: TClassMyObject; cdecl;
begin
Result := TMyObject;
end;
function TMyObject.algoMas: integer;
begin
Result := 123456;
end;
procedure TMyObject.mostrar;
begin
inherited;
MessageDlg('Hola mundo!!!', mtInformation, [mbOK], 0);
end;
end.
Compilo, generando la DLL y listo, ya tengo mi clase de prueba encapsulada dentro de la DLL
Ahora en la aplicación, cargo la DLL de forma dinámica y declaro una variable que apunta a la clase del objeto exportado
Código Delphi
[-]
unit UMyObjectInDLL;
interface
uses UMyObjectInterface;
var
TMyObjectDLL: TClassMyObject = Nil;
implementation
uses
{$ifdef fpc}
dynlibs,
{$endif}
Winapi.Windows, System.SysUtils;
var
{$ifdef fpc}
mHandle: TLibHandle = NIL;
{$else}
mHandle: THandle = 0;
{$endif}
_EC: TGetMyExportedObject = Nil;
initialization
if (pointer(mHandle) = nil) then begin
mHandle := LoadLibrary('MiClassDLL.dll');
if (pointer(mHandle) = nil) then
raise Exception.Create('No se ha podido cargar la DLL')
else begin
_EC := GetProcAddress(mHandle, 'GetMyExportedClass');
if (pointer(@_EC) = nil) then
raise Exception.Create('No se ha podido cargar la funcion GetMyExportedClass')
else
TMyObjectDLL := _EC;
end;
end;
finalization
{$ifdef fpc}
UnLoadLibrary(mHandle);
{$else}
FreeLibrary(mHandle);
{$endif}
end.
y para utilizar dicha clase lo hago así:
Código Delphi
[-]
...
uses
UMyObjectInterface,
UMyObjectInDLL;
procedure TMainForm.Button1Click(Sender: TObject);
var
myObj: TMyAbstractObject;
begin
myObj := TMyObjectDLL.create;
try
MessageDlg(IntToStr(myObj.AlgoMas), mtInformation, [mbOK], 0);
myObj.mostrar;
finally
myObj.free;
end;
end;
Hasta aquí todo perfecto y funciona correctamente.
Ahora lo que pretendo es desde la aplicación generar una clase que herede de la clase almacenada en la DLL, con un código similar a esto pero obtengo el error
E2005 'TMyObjectDLL' is not a type identifier
Código Delphi
[-]
uses UMyObjectInDLL, UMyObjectInterface;
type
TOtraMyClass= class(TMyObjectDll)
procedure Procedimiento2;
end;
Realmente no se si esto que estoy intentando realizar se puede hacer de alguna otra manera o no es posible...
saludos!!!