knightly

Blog Archives

Writing objects into memory for usage in another application

New programming languages like .NET has serialization to send a object from the one to another. In delphi 7 you have to write your own serialization. One of the ways i’ve tried to use is to copy complete objects into memory and restructure the same object in a completely other application. I did this by using FileMappings and Mutexes.  A sample of that code you can find below. Bare in mind that this has been written for my own custom objects but feel free to enhance it.

The code used for this;


unit uMemoryMappings;

interface

uses Classes, Windows, Messages, ShellApi, oObjects, SysUtils, uNetworkResources;

//just a demo object for this code sample
//
type TDemoObject = class(TObject)
private
FIndex : Integer;
FName : String;
public
{}
published
property Index : Integer read FIndex write FIndex;
property Name : String read FName write FName;
end;

//Structure cotnaining the object(s) you want to transfer
//
type TMemoryObject = record
myDemoObject : TDemoObject;
end;

//MXNaming should be unique. Using a GUID ensures the name will be unique.
//
const
_Name   : String = '{CE8DEDB3-638E-475A-870C-DE5F935CB4A5}';
_MXName : String = '{E699BFEA-1C49-49B2-8E9C-CC569E3C2FED}';

var
FileMapping : THandle;
MXHandle    : THandle;

oMemoryObj  : TMemoryObject;

type
PMemoryObj = ^TMemoryObject;

procedure SaveData(rObject : TMemoryObject );
function ReadData : TMemoryObject;
procedure CloseMemoryObjectFile;
procedure CreateMemoryObjectFile;

implementation

//We simply create a file in memory containing the object. Because we might want to use it in a threading model we use
//Mutexes to be sure it won't be overwritten by other threads.
procedure CreateMemoryObjectFile;
begin
FileMapping := CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE, 0, SizeOf(TMemoryObject), PChar(_Name));
if FileMapping <> 0 then
begin
if GetLastError = ERROR_ALREADY_EXISTS then
begin
CloseHandle(FileMapping);
FileMapping := OpenFileMapping(FILE_MAP_ALL_ACCESS, False, PChar(_Name));
end;
end;

if (FileMapping <> 0) then
MXHandle := CreateMutex(nil, False, PChar(_MXName));

if (FileMapping = 0) or (MXHandle = 0) then
Raise Exception.Create('Error allocating memory');
end;

//Closes the Handles and mutexes
procedure CloseMemoryObjectFile;
begin
if FileMapping <> 0 then
CloseHandle(FileMapping);
if MXHandle <> 0 then
CloseHandle(MXHandle);
end;

//Writes the object to the registered memory block.
procedure SaveData(rObject : TMemoryObject );
var
oData : PMemoryObj;
begin
WaitForSingleObject(MXHandle, INFINITE);
try
oData := MapViewOfFile(FileMapping, FILE_MAP_WRITE, 0, 0, SizeOf(TMemoryObject));
try
oData^.myDemoObject := rObject.myDemoObject;
finally
UnmapViewOfFile(oData);
end;
finally
ReleaseMutex(MXHandle);
end;
end;

//Reads the data stored in the memory block.
function ReadData : TMemoryObject;
var
oData : PMemoryObj;
begin
WaitForSingleObject(MXHandle, INFINITE);
try
oData := MapViewOfFile(FileMapping, FILE_MAP_READ, 0, 0, SizeOf(TMemoryObject));
try
if Assigned(oData^.myDemoObject) then Result.myDemoObject := oData^.myDemoObject;
finally
UnmapViewOfFile(oData);
end;
finally
ReleaseMutex(MXHandle);
end;
end;

end.

Programming Community Index for November 2008

Just for fun;

This morning i’ve received an message from the Delphi community to get the Delphi programming language at the top. To get a glance of the position of your preferred programming language please follow this link;

http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html

Last week i did some research about running threads from within delphi in a asynchronous way meaning a webservice call is made from the client, the webservice picks it up sending true or false back to the client indicating that the call has been made, processing the call and fires a OnDone event to the client containing the response.

Doing webservices this way allowes the client to continue working without waiting for the response. Within the .NET webservice techniques it is allready possible to execute webservices this way (SOAP version 1.2). The lastest delphi versions 2005+ allready support those features but Delphi 7 doesn’t.

I’m allready able to start a new trhead from within the call method and process a large amount of data using a cache system. The only bit i’m stuck with is to post back the OnDone event to the client.