Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

TMemoryStream: Can we share?

150 views
Skip to first unread message

Douglas Keene, M.D.

unread,
Jun 14, 2001, 3:57:49 PM6/14/01
to
Is there a way for delphi program using a variable of type TMemoryStream to
setup a chunk of memory for another delphi program with a variable of type
TMemoryStream to communicate with one another? I know there's a SetPointer
method, but it's not accessable from TMemoryStream.

Thanks


Carl Caulkett

unread,
Jun 14, 2001, 4:52:26 PM6/14/01
to
In article <3b2916fb_2@dnews>, dke...@mail.com says...

I wonder if Deborah Pate's TMapStream class might be the anser. Have a
look under the MapFiles entry at
http://www.djpate.freeserve.co.uk/GetCode.htm

--
Carl

Peter Below (TeamB)

unread,
Jun 15, 2001, 8:48:27 AM6/15/01
to
In article <3b2916fb_2@dnews>, M.D. Douglas Keene wrote:
> Is there a way for delphi program using a variable of type TMemoryStream to
> setup a chunk of memory for another delphi program with a variable of type
> TMemoryStream to communicate with one another?

You can copy the content of a memory stream to a memory-mapped file, and that
can be accessed from another process. You can also send the data in the
memory mapped file directly to another process using a WM_COPYDATA message.
To get stream-style read access to the memory (both approaches give you a
pointer to the memory on the receiver side) you can use this class:

{== Unit ROMemStream ==================================================}
{: Implements a TStream descendent that gives read-only access to a
memory block referenced by a pointer.
@author Dr. Peter Below
@desc Version 1.0 created 20 November 2000<BR>
Current revision 1.0<BR>
Last modified 20 November 2000<P>
Last review 17.04.2001<P>
}
{======================================================================}
Unit ROMemStream;
Interface

Uses Classes, Sysutils;

Type
{: A class giving stream-style access (read-only) to a memory block
referenced by a pointer. }
TReadOnlyMemoryStream = Class( TStream )
private
FMemory: PChar; { address of memory block }
FPosition: Integer; { current offset inside block, 0-based }
FSize: Integer; { size of memory block, in bytes }
protected
Procedure SetSize(NewSize: Longint); override;
public
Function Read(var Buffer; Count: Longint): Longint; override;
Function Write(const Buffer; Count: Longint): Longint; override;
Function Seek(Offset: Longint; Origin: Word): Longint; override;

Constructor Create( aPointer: Pointer; aSize: Integer );

property Memory: PChar read FMemory;
property Size: Integer read FSize;
End; { TReadOnlyMemoryStream }

EROMemStreamError = class( EStreamError );

Implementation

ResourceString
{$IFDEF GERMAN}
eStreamIsNotResizable =
'TReadOnlyMemoryStream.SetSize: Die Größe dieses Streams kann '+
'nicht geändert werden.';
eStreamIsReadonly =
'TReadOnlyMemoryStream.Write: Aus diesem Stream kann nur gelesen '+
'werden.';
{$ELSE}
eStreamIsNotResizable =
'TReadOnlyMemoryStream.SetSize: The size of this stream cannot be '+
'changed.';
eStreamIsReadonly =
'TReadOnlyMemoryStream.Write: This stream is read-only.';
{$ENDIF}

{-- TReadOnlyMemoryStream.Create --------------------------------------}
{: Stores the passed parameters
@Param aPointer is the address of the memory block to use
@Param aSize is the size of the memory block
@Precondition aPointer <> nil, aSize > 0
@Desc The passed pointer remains property and responsibility of the
caller, the object is only reading from the memory and will not free
or reallocate it. The caller has to make sure the pointer stays
valid for the lifetime of the object!
}{ Created 20.11.2000 by P. Below
-----------------------------------------------------------------------}
Constructor TReadOnlyMemoryStream.Create( aPointer: Pointer; aSize: Integer
);
Begin { Create }
Assert( Assigned( aPointer ));
Assert( aSize > 0 );

inherited Create;
FMemory := aPointer;
FSize := aSize;
FPosition := 0;
End; { TReadOnlyMemoryStream.Create }

{-- TReadOnlyMemoryStream.SetSize -------------------------------------}
{: Accessor for inherited property Size (write)
@Raises EROMemStreamError since the streams size cannot be changed
}{ Created 20.11.2000 by P. Below
-----------------------------------------------------------------------}
Procedure TReadOnlyMemoryStream.SetSize( NewSize: Longint );
Begin { SetSize }
raise EROMemStreamError.Create( eStreamIsNotResizable );
End; { TReadOnlyMemoryStream.SetSize }

{-- TReadOnlyMemoryStream.Read ----------------------------------------}
{: Reads bytes from the stream.
@Param Buffer is the receptacle for the read bytes
@Param Count is the number of bytes to read
@Returns the actual number of bytes read, which may be less than count
@Desc Copies the requested number of bytes into Buffer and increments
the internal position accordingly. If less than count bytes remain
until the end of stream only the bytes available are transferred.
}{ Created 20.11.2000 by P. Below
-----------------------------------------------------------------------}
Function TReadOnlyMemoryStream.Read( var Buffer; Count: Longint ): Longint;
Var
pCurrent: PChar;
Begin { Read }
If ( FPosition + count ) > FSize Then
Result := FSize - FPosition
Else
Result := count;
pCurrent := FMemory + FPosition;
Move( pCurrent^, Buffer, Result );
Seek( Result, soFromCurrent );
End; { TReadOnlyMemoryStream.Read }

{-- TReadOnlyMemoryStream.Write ---------------------------------------}
{: Raises an exception since the stream is read-only.
@Raises EROMemStreamError
}{ Created 20.11.2000 by P. Below
-----------------------------------------------------------------------}
Function TReadOnlyMemoryStream.Write( const Buffer; Count: Longint ):
Longint;
Begin { Write }
raise EROMemStreamError.Create( eStreamIsReadonly );
End; { TReadOnlyMemoryStream.Write }

{-- TReadOnlyMemoryStream.Seek ----------------------------------------}
{: Moves the internal stream position
@Param Offset is the amount to move in the stream
@Param Origin defines where to start
@Returns the new stream position
@Desc Calculates and returns the new stream position. The position will
be clipped to the available range, trying to seek beyond the end of
stream will not raise an exception but leave the position at the end
of stream.
}{ Created 20.11.2000 by P. Below
-----------------------------------------------------------------------}
Function TReadOnlyMemoryStream.Seek( Offset: Longint; Origin: Word ):
Longint;
Begin { Seek }
Case Origin Of
soFromBeginning: FPosition := Offset;
soFromCurrent : Inc( FPosition, Offset );
soFromEnd : FPosition := FSize + offset;
Else
Assert(False, 'TReadOnlyMemoryStream.Seek: invalid Origin!' );
End; { Case }
If FPosition < 0 Then
FPosition := 0
Else If FPosition > FSize Then
FPosition := FSize;
Result := FPosition;
End; { TReadOnlyMemoryStream.Seek }

End { ROMemStream }.

Peter Below (TeamB) 10011...@compuserve.com)
No e-mail responses, please, unless explicitly requested!
Note: I'm unable to visit the newsgroups every day at the moment,
so be patient if you don't get a reply immediately.

Carl Caulkett

unread,
Jun 16, 2001, 6:30:24 AM6/16/01
to
In article <3b2916fb_2@dnews>, dke...@mail.com says...

Hi Doug,

I tried to contact you about the TMapFiles link but cannot get through.
Let me know if you still need the files, or whether Peter's reply has
solved the problem.

Cheers,
Carl

0 new messages