Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > Varios
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 26-11-2014
JavB JavB is offline
Registrado
NULL
 
Registrado: nov 2014
Posts: 2
Poder: 0
JavB Va por buen camino
Compartir datos en DLL llamada desde tres instancias

Hola buenas,

Se ha realizado una DLL que accede a un dispositivo físico. A esta DLL le pueden llamar varios programas, desde uno a cuatro.
Con cada uno de los programas funciona correctamente por separado, pero cuando se han de compartir datos, no funciona debido al heap de cada instancia.

Hemos emplado el ShareMem, y el FastShareMem, pero no parece funcionar puesto que NO tenemos acceso al código fuente de las aplicaciones y no es posible trabajar con 3 dll sino todas las aplicaciones comparten dicha librería.

El problema es gestionar que los datos que abre o modifica una aplicación sean las mismas para la segunda, tercera etc. La forma de realizarlo, con los condicionantes que tenemos, estiamos que sería con Archivos proyectados en memoria. ¿sería esta la forma correcta? ¿existen otras alternativas? ¿alguna indicación previa o ejemplo?

Hemos visto cosas, pero casi todas son referidas a aplicaciones y no a librerías.

Gracias por anticipado y un saludo.
Responder Con Cita
  #2  
Antiguo 26-11-2014
Avatar de Ñuño Martínez
Ñuño Martínez Ñuño Martínez is offline
Moderador
 
Registrado: jul 2006
Ubicación: Ciudad Catedral, Españistán
Posts: 6.000
Poder: 25
Ñuño Martínez Tiene un aura espectacularÑuño Martínez Tiene un aura espectacular
¿El DLL lo has hecho tú? Si es así, creo que es un mal enfoque. No puedes "compartir" la misma instancia DLL, de ahí que no te funcione. Quizá realizando un segundo programa "servidor" al que conecten los cuatro programas "cliente" y gestione las peticiones funcionaría mejor.

O eso, o un controlador de dispositivo (ya que dices que es para acceder a un dispositivo físico).
__________________
Proyectos actuales --> Allegro 5 Pascal ¡y Delphi!|MinGRo Game Engine
Responder Con Cita
  #3  
Antiguo 27-11-2014
JavB JavB is offline
Registrado
NULL
 
Registrado: nov 2014
Posts: 2
Poder: 0
JavB Va por buen camino
En primer lugar, gracias por respondernos tan rápido. Procedemos a contestar:

Sí, la DLL la hemos realizado nosotros.

Esa es la principal duda que teníamos: los ejemplos que hemos visto son referentes a aplicaciones. Igual si hubiera varias DLL también funcionaría, pero no tenemos esa opción: todos los programas funcionan "contra" la misma DLL.

Aunque nos queda la duda viendo el libro de M. Cantú: "la biblia de delphi". En su edición 7, viene lo siguiente en la pág. 547:

"Si se carga el codigo de la DLL solo una vez, podríamos preguntarnos que ocurre con los datos globales. Básicamente, cada copia de la DLL tiene su propia copia de los datos, en el espacio de direcciones de la aplicación que llama. Sin
embargo, posiblemente será necesario compartir datos globales entre las aplicaciones que usen una DLL. La técnica más común para compartir datos consiste en usar archivos proyectados en memoria. Usaremos esa técnica en el caso de una DLL, pero podemos también utilizarla para compartir directamente los datos entre las aplicaciones. Este ejemplo se llama DllMem e incluye el proyecto DllMem (la propia DLL) y el proyecto UseMem (la aplicación demo)."

Desgraciadamente la persona que nos ha dejado el libro no dispone del CD y no es posible verificar sí es posible realizar lo que pretendemos. Estamos en trámites para adquirir el CD, pero suponemos que tardará aún.

En cuanto a la alternativa, habíamos pensado realizar algo así, pero no somos expertos en delphi y nos llevaría a más cuestiones. La primera sería: ¿Cómo una aplicación puede "escuchar" peticiones desde una DLL? El mayor problema es la rapidez, por lo que el acceso a un fichero en el disco duro queda restringido. Y peticiones TCP/IP también.
¿Hay algún mecanismo de colas que pueda quedar abierto en un aplicación?
Responder Con Cita
  #4  
Antiguo 27-11-2014
Avatar de Ñuño Martínez
Ñuño Martínez Ñuño Martínez is offline
Moderador
 
Registrado: jul 2006
Ubicación: Ciudad Catedral, Españistán
Posts: 6.000
Poder: 25
Ñuño Martínez Tiene un aura espectacularÑuño Martínez Tiene un aura espectacular
El uso de la red es el más apropiado. Si no recuerdo mal (hace mucho que no uso Delphi y me pasé a Lazarus) Delphi incluye todo lo necesario para hacerlo, incluso con ejemplos de sistemas cliente-servidor. En local (y me refiero a "localhost") es bastante rápido.

Aun así, sigo pensando que la mejor opción es crear un controlador de dispositivo, pero si no recuerdo mal, con Delphi es muy difícil (por temas de Windows, no del propio Delphi) y habría que hacerlo en C, y luego llamar a ese controlador (una vez instalado) desde los programas con llamadas al sistema.
__________________
Proyectos actuales --> Allegro 5 Pascal ¡y Delphi!|MinGRo Game Engine
Responder Con Cita
  #5  
Antiguo 04-12-2014
Avatar de nlsgarcia
[nlsgarcia] nlsgarcia is offline
Miembro Premium
 
Registrado: feb 2007
Ubicación: Caracas, Venezuela
Posts: 2.206
Poder: 21
nlsgarcia Tiene un aura espectacularnlsgarcia Tiene un aura espectacular
JavB,

Cita:
Empezado por JavB
...Se ha realizado una DLL que accede a un dispositivo físico...A esta DLL le pueden llamar varios programas...El problema es gestionar que los datos que abre o modifica una aplicación sean las mismas para la segunda, tercera etc...Compartir datos en DLL llamada...


Revisa esta información:
Cita:
Sharing DLL Data Across Different Processes

Back in the world of 16-bit Windows, DLL memory was handled differently than it is in the
32-bit world of Win32. One often-used trait of 16-bit DLLs is that they share global memory among different applications. In other words, if you declare a global variable in a 16-bit DLL, any application that uses that DLL will have access to that variable, and changes made to that variable by an application will be seen by other applications.

In Win32, this sharing of DLL global data no longer exists
. Because each application process
maps the DLL to its own address space, the DLL’s data also gets mapped to that same address space. This results in each application getting its own instance of DLL data. Changes made to the DLL global data by one application won’t be seen from another application.

you can still provide a means for applications to share data in a DLL with other
applications. The process isn’t automatic, and it requires the use of Memory-Mapped Files to store the shared data.

Memory-mapped files can be used to provide the ability to share data among different
processes running on the same machine
.

Tomado del libro : Delphi 5 Developer’s Guide (Chapter 9 Dynamic Link Libraries y Chapter 12 Working with Files) de Xavier Pacheco y Steve Teixeira.
Revisa este código:
Código Delphi [-]
 // DLL que comparte data entre diferentes procesos
 library GlobalDataLib;
 
 uses
   Windows, SysUtils;
 
 const
   FileMapping : PChar = 'GlobalMappingData';
 
 type
   // Definición de data global contenida en el DLL
   PGlobalDllData = ^TGlobalDllData;
   TGlobalDllData = record
     S1 : String[100];
     S2 : String[50];
     S3 : Char;
     N1 : Integer;
     N2 : Double;
     N3 : LongWord;
     D1 : TDateTime;
     A1 : Array[0..9] of Integer;
   end;
 
 var
   AGlobalData, GlobalData : PGlobalDllData;
   MapHandle : THandle;
 
 // Función que obtiene la data global contenida en el DLL
 function GetDLLData : PGlobalDllData; StdCall;
 begin
   Result := GlobalData;
 end;
 
 // Apertura la data global por medio de File-Mapping Object
 procedure OpenGlobalData;
 var
   Size, i : Integer;
 
 begin
 
   Size := SizeOf(TGlobalDllData);
 
   MapHandle := CreateFileMapping(DWord(-1), nil, PAGE_READWRITE, 0, Size, FileMapping);
 
   if MapHandle = 0 then
     RaiseLastWin32Error;
 
   GlobalData := MapViewOfFile(MapHandle, FILE_MAP_ALL_ACCESS, 0, 0, Size);
 
   if GlobalData = nil then
   begin
     CloseHandle(MapHandle);
     RaiseLastWin32Error;
   end
   else
     AGlobalData := GetDLLData;
 
   if AGlobalData^.S1 <> EmptyStr then
      GlobalData^.S1 := AGlobalData^.S1
   else
      GlobalData^.S1 := EmptyStr;
 
   if AGlobalData^.S2 <> EmptyStr then
      GlobalData^.S2 := AGlobalData^.S2
   else
      GlobalData^.S2 := EmptyStr;
 
   if AGlobalData^.S3 <> '' then
      GlobalData^.S3 := AGlobalData^.S3
   else
      GlobalData^.S3 := #0;
 
   if AGlobalData^.N1 <> 0 then
      GlobalData^.N1 := AGlobalData^.N1
   else
      GlobalData^.N1 := 0;
 
   if AGlobalData^.N2 <> 0 then
      GlobalData^.N2 := AGlobalData^.N2
   else
      GlobalData^.N2 := 0;
 
   if AGlobalData^.N3 <> 0 then
      GlobalData^.N3 := AGlobalData^.N3
   else
      GlobalData^.N3 := 0;
 
   if AGlobalData^.D1 <> 0 then
      GlobalData^.D1 := AGlobalData^.D1
   else
      GlobalData^.D1 := 0;
 
   for i := Low(AGlobalData^.A1) to High(AGlobalData^.A1) do
   begin
      if AGlobalData^.A1[i] <> 0 then
         GlobalData^.A1[i] := AGlobalData^.A1[i]
      else
         GlobalData^.A1[i] := 0;
   end;
 
 end;
 
 // Cierra la data global por medio de File-Mapping Object
 procedure CloseGlobalData;
 begin
   UnmapViewOfFile(GlobalData);
   CloseHandle(MapHandle);
 end;
 
 // Controla la entrada y salida del DLL
 procedure DLLEntryPoint(dwReason: DWord);
 begin
   case dwReason of
     DLL_PROCESS_ATTACH: OpenGlobalData;
     DLL_PROCESS_DETACH: CloseGlobalData;
   end;
 end;
 
 exports
   GetDLLData;
 
 begin
   // Inicializa el punto de entrada al DLL
   DllProc := @DLLEntryPoint;
   DLLEntryPoint(DLL_PROCESS_ATTACH);
 end.
Código Delphi [-]
 // Programa que implementa la DLL que comparte data entre diferentes procesos
 unit Unit1;
 
 interface
 
 uses
   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
   Dialogs, StdCtrls, ExtCtrls, Math;
 
 type
   TForm1 = class(TForm)
     ListBox1: TListBox;
     Button1: TButton;
     Timer1: TTimer;
     procedure Timer1Timer(Sender: TObject);
     procedure Button1Click(Sender: TObject);
     procedure FormCreate(Sender: TObject);
   private
     { Private declarations }
   public
     { Public declarations }
   end;
 
   // Definición de data global contenida en el DLL
   PGlobalDllData = ^TGlobalDllData;
   TGlobalDllData = record
     S1 : String[100];
     S2 : String[50];
     S3 : Char;
     N1 : Integer;
     N2 : Double;
     N3 : LongWord;
     D1 : TDateTime;
     A1 : Array[0..9] of Integer;
   end;
 
 // Función que obtiene la data global contenida en el DLL
 function GetDLLData : PGlobalDLLData; stdcall; external 'GlobalDataLib.dll';
 
 var
   Form1: TForm1;
   AGlobalData : PGlobalDLLData;
 
 implementation
 
 {$R *.dfm}
 
 // Inicializa la aplicación
 procedure TForm1.FormCreate(Sender: TObject);
 begin
    Timer1.Interval := 100;
    Randomize;
    AGlobalData := GetDLLData;
 end;
 
 // Actualiza la data global contenida en el DLL
 procedure TForm1.Timer1Timer(Sender: TObject);
 var
    AuxStr : String;
    i : Integer;
 
 begin
 
    ListBox1.Clear;
 
    ListBox1.Items.Add(Format('S1 = %s',[AGlobalData^.S1]));
    ListBox1.Items.Add(Format('S2 = %s',[AGlobalData^.S2]));
    ListBox1.Items.Add(Format('S3 = %s',[AGlobalData^.S3]));
    ListBox1.Items.Add(Format('N1 = %d',[AGlobalData^.N1]));
    ListBox1.Items.Add(Format('N2 = %n',[AGlobalData^.N2]));
    ListBox1.Items.Add(Format('N3 = %d',[AGlobalData^.N3]));
    ListBox1.Items.Add(Format('D1 = %s',[DateTimeToStr(AGlobalData^.D1)]));
 
    for i := Low(AGlobalData^.A1) to High(AGlobalData^.A1) do
       AuxStr := AuxStr + IntToStr(AGlobalData^.A1[i]) + ' ';
 
    Delete(AuxStr,Length(AuxStr),1);
 
    ListBox1.Items.Add(Format('A1 = [%s]',[AuxStr]));
 
 end;
 
 // Genera nueva data global en el DLL
 procedure TForm1.Button1Click(Sender: TObject);
 var
    i : Integer;
 
 begin
 
    AGlobalData^.S1 := 'String-' + IntToStr(Random(100));
    AGlobalData^.S2 := 'String-' + IntToStr(Random(100));
    AGlobalData^.S3 := Chr(RandomRange(33,126));
    AGlobalData^.N1 := Random(100);
    AGlobalData^.N2 := Random(1000);
    AGlobalData^.N3 := Random(1000000);
    AGlobalData^.D1 := Now + Random(1095);
 
    for i := Low(AGlobalData^.A1) to High(AGlobalData^.A1) do
       AGlobalData^.A1[i] := Random(100);
 
 end;
 
 end.
El código anterior en Delphi 7 sobre Windows 7 Professional x32, implementa una DLL que comparte data entre diferentes procesos por medio de Memory-Mapped Files y un programa que usa la DLL para monitorear y cambiar aleatoriamente la data compartida, como se puede ver en la siguiente imagen:



En la imagen se puede ver cuatro programas que usan la DLL
GlobalDataLib y comparten la data mapeada en memoria, cualquiera de ellos puede actualizar la data y esta sera vista inmediatamente por los otros programas.

El código del ejemplo esta disponible en : GlobalDataLib.rar

Nota: Con esta técnica se evita el uso de programas Cliente-Servidor, solo en los casos específicos donde pueda aplicarse, pero debe usarse con cuidado dado que todos los programas comparten la misma data que es mapeada en memoria, la clave para los Memory-Mapped Files son las funciones
: CreateFileMapping y MapViewOfFile.

Revisa esta información:

Espero sea útil

Nelson.

Última edición por nlsgarcia fecha: 14-12-2014 a las 02:29:22.
Responder Con Cita
  #6  
Antiguo 04-12-2014
Avatar de Ñuño Martínez
Ñuño Martínez Ñuño Martínez is offline
Moderador
 
Registrado: jul 2006
Ubicación: Ciudad Catedral, Españistán
Posts: 6.000
Poder: 25
Ñuño Martínez Tiene un aura espectacularÑuño Martínez Tiene un aura espectacular
Realmente impresionante, Nelson.

Y como bien dices, cuidado porque se comparte memoria. Me pregunto si podría implementarse algún sistema de semáforos, al estilo de los programas multi-hilo, para evitar colisiones y conflictos.
__________________
Proyectos actuales --> Allegro 5 Pascal ¡y Delphi!|MinGRo Game Engine
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
Llamada desde PC carmelina Varios 0 29-03-2010 14:46:56
Compartir "objetos" entre varias instancias mafebresv Varios 4 17-01-2006 00:38:23
LLamada a un cgi desde php apicito PHP 5 26-10-2005 15:15:31
registros correlativos desde tres pc fixarg Conexión con bases de datos 3 17-10-2004 17:45:56
DataModule llamado desde varias instancias floren OOP 4 06-04-2004 20:27:50


La franja horaria es GMT +2. Ahora son las 14:09:43.


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