Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > OOP
Registrarse FAQ Miembros Calendario Guía de estilo Buscar Temas de Hoy Marcar Foros Como Leídos

Grupo de Teaming del ClubDelphi

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 30-05-2018
bucanero bucanero is offline
Miembro
 
Registrado: nov 2013
Ubicación: Almería, España
Posts: 208
Poder: 11
bucanero Va camino a la fama
Clases encapsuladas en DLL y herencia

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
  // se define una interface con los procedimientos/funciontes
  IMyInterface = interface(IInterface)
    ['{ECEF5846-F1B3-4ECE-9113-16B2C7962F04}']
    function algoMas: integer;
    procedure mostrar;
  end;

  // se define una Objeto abstracto con los metodos de la interface
  TMyAbstractObject = class abstract (TInterfacedObject, IMyInterface)
    function algoMas: integer; virtual; abstract;
    procedure mostrar; virtual; abstract;
  end;

  // se define el puntero a la clase abstracta del objeto
  TClassMyObject = class of TMyAbstractObject;

  // se define la funcion para la importacion/exportacion de la clase
  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;

// función que devuelve el puntero a la clase del objeto
function GetMyExportedClass: TClassMyObject; cdecl;
begin
  Result := TMyObject;
end;


{ TMyClass }
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
  (* load shared library *)
  if (pointer(mHandle) = nil) then begin
    (* Try to load shared library *)
    mHandle := LoadLibrary('MiClassDLL.dll');
    if (pointer(mHandle) = nil) then
      raise Exception.Create('No se ha podido cargar la DLL')
    else begin
      (* instantiate a TMyExportedClass object *)
      _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
  (* unload shared library *)
  {$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
    /// Inicializar la clase exportada
    myObj := TMyObjectDLL.create;
    try
      MessageDlg(IntToStr(myObj.AlgoMas), mtInformation, [mbOK], 0);
      myObj.mostrar;
    finally
      (*... and free exported class *)
      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!!!
Responder Con Cita
  #2  
Antiguo 02-06-2018
engranaje engranaje is offline
Miembro
 
Registrado: may 2011
Posts: 163
Poder: 13
engranaje Va por buen camino
En el código anterior tienes esto
Código Delphi [-]
var   TMyObjectDLL: TClassMyObject = Nil;

Más adelante dices que te funciona esto:
Código Delphi [-]
myObj := TMyObjectDLL.create;

y finalmente el código que te falla:
Código Delphi [-]
TOtraMyClass= class(TMyObjectDll)

Si no me he perdido en todo esto TMyObjectDLL no es mas que una instancia de la clase TClassMyObject. Pero al final no deja de ser mas que una variable,
no puedes hacer que TOtraMyClass sea una clase hija de TMyObjectDll porque como te dice el mensaje TMyObjectDll no es un TYPE. Podrías hacer:
Código Delphi [-]
   TOtraMyClass= class(TClassMyObject )
Como digo espero no haberme perdido pero a priori parece que te has despistado, igual por haberle puesto de nombre TMyObjectDLL a una instancia del objeto TClassMyObject. Puede colaborar con el error que funcione el código:
Código Delphi [-]
myObj := TMyObjectDLL.create;
pero despues de todo TMyobjectdll aunque sea un instancia tiene un metodo create que devuelve un objeto del tipo TMyAbstractObject, aunque si he seguido bien todo tu código igual te serviría:
Código Delphi [-]
myObj := TClassMyObject.create;

Última edición por engranaje fecha: 02-06-2018 a las 17:49:27.
Responder Con Cita
  #3  
Antiguo 04-06-2018
bucanero bucanero is offline
Miembro
 
Registrado: nov 2013
Ubicación: Almería, España
Posts: 208
Poder: 11
bucanero Va camino a la fama
Gracias engranaje por responder


Cita:
Empezado por engranaje Ver Mensaje

Si no me he perdido en todo esto TMyObjectDLL no es mas que una instancia de la clase TClassMyObject. Pero al final no deja de ser mas que una variable,
no puedes hacer que TOtraMyClass sea una clase hija de TMyObjectDll porque como te dice el mensaje TMyObjectDll no es un TYPE. Podrías hacer:
Código Delphi [-]
   TOtraMyClass= class(TClassMyObject )
[/delphi]
Quizas no me explique bien en mi post anterior..., y si como bien dices TMyObjectDLL es una instancia de la clase TClassMyObject, el tema es que la clase TClassMyObject esta solamente definida en la DLL y no en la aplicacion. A priori la aplicación solo sabe que es una clase descendiente de TMyAbstractObject pero no sabe mas.

Aquí dejo un enlace a la estructura del programa

y aquí dejo el código fuente por si alguien quiere hacer pruebas:
https://www.megaupload.us/10ip/MiEjemplo.rar

La idea original que pretendo es cargar una clase desde una DLL, Al igual que cuando se utiliza una función definida en una DLL el programa solo sabe el nombre de la función y los parámetros que utiliza, sin conocer mas nada sobre dicha función y se carga de esta manera

Código Delphi [-]
  function MiFuncion : string; stdcall; external 'MiDll.dll';

Para utilizar una clase la idea sería algo similar, como poder hacer algo así:

Código Delphi [-]
  TMyObjectDLL = class stdcall; external 'MiDll.dll';

Aunque evidentemente esto no esta soportado, ni lo acepta el compilador, por eso ando buscando alternativas...

Como una clase es bastante mas compleja que una simple función, he pretendido utilizar clases predefinidas donde las funciones genéricas al menos estén definidas ya en interfaces y donde el programa que pretende utilizar dicha clase, tenga ya de antemano alguna información sobre la clase
Responder Con Cita
  #4  
Antiguo 05-06-2018
Avatar de Neftali [Germán.Estévez]
Neftali [Germán.Estévez] Neftali [Germán.Estévez] is offline
[becario]
 
Registrado: jul 2004
Ubicación: Barcelona - España
Posts: 18.233
Poder: 10
Neftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en bruto
Cita:
Empezado por bucanero Ver Mensaje
y aquí dejo el código fuente por si alguien quiere hacer pruebas:
https://www.megaupload.us/10ip/MiEjemplo.rar

¿Puedes subir el fichero al FTP del club o algún otro sitio "normal"?
Después de unas cuantas extensiones que me ha intentado instalar esta web, varias ventanas de publicidad, pedirme que quite el AdBloqcker y unas cuantas esperas, he decidido desistir...
__________________
Germán Estévez => Web/Blog
Guía de estilo, Guía alternativa
Utiliza TAG's en tus mensajes.
Contactar con el Clubdelphi

P.D: Más tiempo dedicado a la pregunta=Mejores respuestas.
Responder Con Cita
  #5  
Antiguo 05-06-2018
bucanero bucanero is offline
Miembro
 
Registrado: nov 2013
Ubicación: Almería, España
Posts: 208
Poder: 11
bucanero Va camino a la fama
Gracias Neftali por responder

Cita:
Empezado por Neftali [Germán.Estévez] Ver Mensaje
Después de unas cuantas extensiones que me ha intentado instalar esta web, varias ventanas de publicidad, pedirme que quite el AdBloqcker y unas cuantas esperas, he decidido desistir...
Ahora que lo intente, es cierto que es una pesadilla... No suelo usar habitualmente este tipo de paginas para subir ficheros... y por ser MEGAUPLOAD de las mas conocidas pensé que funcionaria mejor

Aquí esta el enlace al fichero en el FTP del ClubDelphi Leer_Clase_Desde_DLL.rar
Responder Con Cita
Respuesta


Herramientas Buscar en Tema
Buscar en Tema:

Búsqueda Avanzada
Desplegado

Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Aclaración sobre Herencia de Clases lugabame OOP 2 14-01-2015 17:07:06
Clases y Herencia en PHP salvica PHP 3 15-04-2011 22:06:12
¿Cómo puedo implementar clases,herencia,poliformismo en Delphi con ejemplos? Master23 Varios 2 21-08-2010 19:58:22
Los ayudantes de clases (o clases ayudantes), ¿ya se gestaban en Delphi 7? Al González OOP 5 12-12-2007 10:03:52
Clases y herencia dec HTML, Javascript y otros 1 16-01-2007 11:53:36


La franja horaria es GMT +2. Ahora son las 20:36:24.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi