¡Hola a todos!
En los últimos días dediqué algunos ratos libres a escribir esta unidad de código. Es algo que programé hace varios años como parte de una biblioteca que contiene muchas otras cosas, pero decidí aislar y afinar este material para compartirlo con todos los colegas Delphi de manera más directa.
La idea básica es poder crearnos clases derivadas de una como TSuperGlobalObject en lugar de TObject, cuando queramos tener una
instancia de objeto que pueda ser compartida entre procesos de manera natural y transparente.
Con esto, un programa Delphi en ejecución puede instanciar un objeto de clase definida por el programador, de la manera usual:
Y luego otro programa Delphi en ejecución puede hacer lo mismo:
En ese momento los dos procesos estarán compartiendo el mismo objeto, y podrán acceder a sus campos y métodos como lo harían con cualquier objeto normal. Los cambios que un programa hace sobre el objeto son automáticamente visibles para el otro programa. Esto resulta en una manera muy práctica de compartir información entre dos aplicaciones que se ejecutan en la misma máquina.
Pueden hacérsele muchas mejoras a esta unidad, como adaptarle semáforos de acceso para controlar escrituras simultáneas o modificar algunas secciones de su código para hacerla
segura para hilos (
thread safe), pero la base ya está.
Al final de este mensaje aparece un enlace para descargarla. He aquí su código (se aceptan críticas constructivas

):
Código Delphi
[-]
Unit AGSuperglobals;
Interface
Type
TSuperGlobalObject = Class
Public
Class Function NewInstance :TObject; Override;
Procedure FreeInstance; Override;
End;
TSuperGlobalObjectClass = Class Of TSuperGlobalObject;
Function CreateSuperGlobalObject (Const Cls :TSuperGlobalObjectClass;
Const Name :String) :Pointer;
Implementation
Uses
Classes, Windows, SysUtils;
Var
HandleList :TList;
ObjectList :TList;
ObjectName :String;
Class Function TSuperGlobalObject.NewInstance :TObject;
Var
AlreadyExists :Boolean;
Handle :THandle;
Name :String;
Begin
If ObjectName <> '' Then
Name := ObjectName
Else
Name := ClassName;
Handle := CreateFileMapping (Invalid_Handle_Value, Nil, Page_ReadWrite,
0, InstanceSize, Pointer (Name + '.mem'));
AlreadyExists := GetLastError () = error_Already_Exists;
If Handle <> 0 Then
Begin
Result := MapViewOfFile (Handle, file_map_All_Access, 0, 0, 0);
If Result <> Nil Then
Begin
If Not AlreadyExists Then
InitInstance (Result);
If HandleList = Nil Then
Begin
HandleList := TList.Create;
ObjectList := TList.Create;
End;
HandleList.Add (Pointer (Handle));
ObjectList.Add (Result);
Exit;
End;
End;
Raise Exception.CreateFmt (
'Falló intento de crear objeto superglobal "%s".', [Name]);
End;
Procedure TSuperGlobalObject.FreeInstance;
Var
I :Integer;
Begin
UnmapViewOfFile (Self);
I := ObjectList.IndexOf (Self);
CloseHandle (THandle (HandleList.Extract (HandleList [i])));
ObjectList.Delete (I);
If HandleList.Count = 0 Then
Begin
FreeAndNil (HandleList);
FreeAndNil (ObjectList);
End;
End;
Function CreateSuperGlobalObject (Const Cls :TSuperGlobalObjectClass;
Const Name :String) :Pointer;
Begin
ObjectName := Name;
Try
Result := Cls.Create;
Finally
ObjectName := '';
End;
End;
End.
Espero que a alguien le sea de utilidad. Ojalá todo mi trabajo consistiese en hacer cosas como esta. Algún día no muy lejano...
Un abrazo superglobal.
Al González.