Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Varios (https://www.clubdelphi.com/foros/forumdisplay.php?f=11)
-   -   pasar un tipo de datos (array of record) entre aplicaciones (https://www.clubdelphi.com/foros/showthread.php?t=49624)

mauqu 25-10-2007 17:24:20

pasar un tipo de datos (array of record) entre aplicaciones
 
Estimados:

Desarrollo 2 aplicaciones donde la aplicación 1 debe enviarle sierta información a la aplicación 2 a travez de la memoria. Esta información es un array de una estructura de datos (array of record).

Para ello utilizé el siguiente código:

Aplicación 1 (aplicación que envia datos)

Código Delphi [-]
 
unit Unit1;
interface
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ShellApi;
type
  TTest = packed record
    Fecha,
    Hora:TDateTime;
    Monto,
    CantCuotas:real;
    MarcaOS:string[1];
    NroTicket:int64;
    CodBarras:int64;
    CodTroquel:integer;
    Alfabeta:integer;
    CantSolicitada:integer;
    TipoBonificacion:string[2];
    ValorBonificacion:real;
  end;
  
  TForm1 = class(TForm)
  Button1: TButton;
  procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
var
  Form1: TForm1;
implementation
{$R *.dfm}
 
procedure TForm1.Button1Click(Sender: TObject);
var
  Test:array of TTest;
  //Estructura de datos para la info de la transacción
  CopyDataStruct:TCopyDataStruct;
  PAplicacion2:Thandle; //El manejador del soft 2
  Resultado:integer; 
  regs:integer;
begin
  regs:=2;
  SetLength(Test,regs);
  //Cargar los datos de la transacción
  with test[0] do
  begin
    Fecha:=now;
    Hora:=now;
    Monto:=110.20;
    CantCuotas:=1.0;
    MarcaOS:='1';
    NroTicket:=999888999;
    CodBarras:=7796930007303;
    CodTroquel:=4108371;
    Alfabeta:=0;
    CantSolicitada:=2;
    TipoBonificacion:='';
    ValorBonificacion:=0;
  end;  

  with test[1] do
  begin
    Fecha:=now;
    Hora:=now;
    Monto:=110.20;
    CantCuotas:=1.0;
    MarcaOS:='1';
    NroTicket:=999888999;
    CodBarras:=7792069002868;
    CodTroquel:=3104331;
    Alfabeta:=0;
    CantSolicitada:=1;
    TipoBonificacion:='';
    ValorBonificacion:=0;
  end;  
  //Copiar los datos de la transacción
  CopyDataStruct.dwData := 2; //Estructura
  CopyDataStruct.cbData := SizeOf(Test)*regs;
  CopyDataStruct.lpData := @Test;
 
  //Buscar el soft 2
  PAplicacion2:=findwindow('TAplication2',nil);
  if PAplicacion2 = 0 then begin //Si no lo encuentra
    //Ejecutar el soft 2
    ShellExecute(handle,
                 'open',
                 'C:\Aplicacion2.exe',
                 nil,
                 'C:\',
                 SW_SHOWNORMAL);
    sleep(1000);    
    //Buscar el soft 2
    PAplicacion2:=findwindow('TAplication2',nil);
    if PAplicacion2=0 then begin //Si no lo cuentra
      showmessage('La aplicación 2 no se puede levantada.');
      exit;
    end;
  end;
  //Enviar el mensaje WM_COPYDATA al soft 2 pasandole los datos de la transacción
  //  el mensaje de vuelta.
  Resultado:=SendMessage(PVirtualPOS,WM_COPYDATA,Integer(Handle),integer(@CopyDataStruct));
  //Mostramos el resultado.
  caption:=inttostr(resultado);
end;

Aplicación 2 (receptora)

Código Delphi [-]
 
unit fMain;
interface
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ShellApi;
 
type
  TTDatos = packed record
    Fecha,
    Hora:TDateTime;
    Monto,
    CantCuotas:real;
    MarcaOS:string[1];
    NroTicket:int64;
    CodBarras:int64;
    CodTroquel:integer;
    Alfabeta:integer;
    CantSolicitada:integer;
    TipoBonificacion:string[2];
    ValorBonificacion:real;
  end;
  
  TDatos = array of TTDatos;

  TfrmMain = class(TForm)
  
  private
    { Private declarations }
  public
    { Public declarations }
    procedure CopiarData(var Msg: TWMCopyData); message WM_COPYDATA;
  
  end;
var
  frmMain: TfrmMain;
implementation
{$R *.dfm}
 
procedure TfrmMain.CopiarData(var Msg: TWMCopyData);
var
  PDatos:^TDatos;
  MisDatos:TDatos;
begin
  PDatos:=Msg.CopyDataStruct.lpData;
  MisDatos:=PDatos^; // ERROR
  Msg.Result:=9999;
end;
 
end.

Cuando la aplicación 2 recibe el mensaje y trata de acceder al array me da un error de access violations.

Que es lo que no estoy contemplando ???, o, como se debe hacer esto :)

Saludos cordiales.

Mau

Mick 25-10-2007 18:00:58

Una aplicacion no puede acceder a la memoria de otra aplicacion, es una medida de seguridad basica en cualquier sistema operativo decente.
Tienes que crear una zona de memoria compartida a la que se le permita acceder a otros programas, algunos ejemplos en:

http://www.delphifaq.com/faq/delphi_...API/f348.shtml
http://www.codeproject.com/threads/sharedmemipc.asp

Saludos

ArdiIIa 25-10-2007 23:05:48

A ver si con este tema se soluciona algo....

mauqu 26-10-2007 15:04:46

Ardilla gracias por la ayuda, me sivrio mucho, pero ahora tengo un tema más :S

Probe ya usando el FileMapping y el tema es que necesito compartir un array de estructuras, y programé algo así:


Código Delphi [-]

unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ShellApi;
type
TTest = packed record
Nombre,
Apellido:string[30];
end;
ATEST=array of TTest;

TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
PTest:^ATEST;
FicheroM: THandle;
begin

//Para el caso de un array, debo pasar como longitud la suma de todos sus miembros ??
FicheroM:=CreateFileMapping($FFFFFFFF,nil,PAGE_READWRITE,0,SizeOf(TTest),'Datos');
PTest:=MapViewOfFile(FicheroM,FILE_MAP_WRITE,0,0,0);

with Ptest^[0] do //Esto genera un error
begin
Nombre:='Pepe';
Apellido:='Alonso';
end;

with Ptest^[1] do
begin
Nombre:='Ludovico';
Apellido:='Pio';
end;

UnmapViewOfFile(PTest);

CloseHandle(FicheroM);

end;
end.






Entonces mi pregunta acá es, como se debe pasar un array de estructuras por medio de FileMapping ???.

Espero se entienda, gracias por la ayuda.

Mau

ArdiIIa 26-10-2007 20:04:31

Código Delphi [-]
unit Unit1;
interface
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ShellApi;
type
  TTest = packed record
    Nombre,
    Apellido:string[30];
  end;
  ATEST=array of TTest;
 
  TForm1 = class(TForm)
  Button1: TButton;
  procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
var
  Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
  PTest:^ATEST;
  FicheroM: THandle;
begin
 
   //Para el caso de un array, debo pasar como longitud la suma de todos sus miembros ??
   FicheroM:=CreateFileMapping($FFFFFFFF,nil,PAGE_READWRITE,0,SizeOf(TTest),'Datos');
  PTest:=MapViewOfFile(FicheroM,FILE_MAP_WRITE,0,0,0);
 
  with Ptest^[0] do //Esto genera un error
  begin
    Nombre:='Pepe';
    Apellido:='Alonso';
  end;
 
  with Ptest^[1] do
  begin
    Nombre:='Ludovico';
    Apellido:='Pio';
  end;
 
  UnmapViewOfFile(PTest);  
 
  CloseHandle(FicheroM);
 
end;
end.

Bueno, creo que la clave está es que estás intentando pasar un array de registros, pero no has reservado memoria para cada dicho array.
si verificas esto:
Código Delphi [-]
SizeOf(TTest)
antes de mapear, verás el problema.

Si leíste aquel hilo tal como te dije, también citaba esa posibilidad, reservando memoria mediante VirtualAllocEx

Recuerda que no puedes asignar elementos a un array vacio....

Luego examinando tu código, primeramente diría que la declaración del registro es incorrecta, dado que debes crear un puntero al registro.... en este caso PDatitos..

Código Delphi [-]
PDatitos = ^TDatitos;
TDatidos = packed record
    Dato_1    : Cardinal;   
    Dato_2    : Cardinal;   
    Dato_Main    : Cardinal; 
    Virtual_Mem_Adr  : Pointer;  // Dirección de memoria donde se aloja algo 
    Virtual_Men_Size : LongWord; // Longitud de memoria donde se aloja ese algo
    Etc_1 : Boolean;
end;


y luego crear o defirnir el array de una longitud fija....

Código Delphi [-]
Test_Array : Array [0..10] of TDatitos;


o dinámica

Código Delphi [-]
Test_Array: Array  of TDatitos;

En este caso debería ir asignando memória para cada elemento.

Luego podría hacer hago tal que esto para asignar valores al array


Código Delphi [-]
Test_Array[0].Dato_1 := 15;

Suerte.


La franja horaria es GMT +2. Ahora son las 05:40:49.

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