 |
BorlandTalk.com Borland discussion newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Martin Harvey (Demon Acco Guest
|
Posted: Sun Jan 23, 2005 3:00 am Post subject: WANTED! Object streaming system. |
|
|
Hey folks,
I've looked everywhere, and I just can't seem to find exactly what it
is that I want. Basically, I want to load and save datastructures to
and from a stream (either a disk file, or a memory stream for
transmission). However, I've got a few constraints.
- I want to be able to stream fairly arbitrary classes - i.e. not
limited to TPersistent / TComponent descendants. However, I'm willing
to put up with the following limitations, which I think will cover the
difficulties:
a) Streamable classes must be declared {$M+}
b) For streaming of some custom properties, or BLOBS, where RTTI might
not do the trick, the classes can implement an optional interface
(IStreamable?)
- As far as input / output formats are concerned, I want to be able to
support both a textual (e.g. XML-like) format, and a binary (probably
Tag-Length-Value) format.
Most of the stuff I want to stream is basic properties (ordinal
types), and pointers to other streamable classes, with the exception
of the occasional large chunk of binary data.
I think I could do most of this with RTTI. The only big question mark
I have is supporting array properties - in particular, arrays of
pointers to other streamable classes. Is there an RTTI supported
"potted solution" to this, or am I going to have to implement an
ad-hoc solution?
- Licensing constraints: if I can't grab the source code & freely use
it, then I'd prefer to write my own.
So ... anyone know of anything off the shelf that would do the job? If
not, then I'll crack on with writing my own :-)
MH.
|
|
| Back to top |
|
 |
Peter Below (TeamB) Guest
|
Posted: Sun Jan 23, 2005 11:18 am Post subject: Re: WANTED! Object streaming system. |
|
|
In article <ad46v0hfre9dvuqvcip0l4m7k4hglp3abh (AT) 4ax (DOT) com>, Martin Harvey (Demon
Account) wrote:
| Quote: | a) Streamable classes must be declared {$M+}
b) For streaming of some custom properties, or BLOBS, where RTTI might
not do the trick, the classes can implement an optional interface
(IStreamable?)
- As far as input / output formats are concerned, I want to be able to
support both a textual (e.g. XML-like) format, and a binary (probably
Tag-Length-Value) format.
Most of the stuff I want to stream is basic properties (ordinal
types), and pointers to other streamable classes, with the exception
of the occasional large chunk of binary data.
|
The "pointers to other streamable classes" (i assume you mean objects here)
is a big problem. Pointers (memory addresses) are meaningless outside the
context of the running process, so you need to replace them by something else
that allows you to identify the referenced object *in the stream*. The VCL
streaming system uses the Name property for that purpose, which is why it is
limited to TComponent descendents for referenced objects and is limited in
other ways as well (the referenced objects need to have a known Owner, for
example, so they can be found using the Name).
This is one of the reasons why streamable classes usually need to be designed
for streaming from the word GO. This way you can build a unique ID of some
kind into the base class of the hierarchy. Streaming the reference for an
object would then stream the ID instead. Loading is even more complex since
the referenced object may not have been read from the stream yet when you
load its reference. So you need to build a fixup mechanism into the loader
process so the references can be resolved after the full stream has neen
loaded.
You can simplify the design by just streaming the referenced object directly
when you have to stream a reference. But that buys you other restrictions,
like not allowing more than one reference to a given object, no circular
references etc..
All in all not an easy task <g>.
--
Peter Below (TeamB)
Use the newsgroup archives :
http://www.mers.com/searchsite.html
http://www.tamaracka.com/search.htm
http://groups.google.com
http://www.prolix.be
|
|
| Back to top |
|
 |
John Herbster Guest
|
Posted: Sun Jan 23, 2005 1:12 pm Post subject: Re: WANTED! Object streaming system. |
|
|
"Martin Harvey (Demon Account)" <martin (AT) nospam_pergolesi (DOT) demon.co.uk>
wrote
| Quote: | ... to load and save data structures to and from a stream ...
|
Martin, I need something similar. Conventional databases
and tables are not doing the job. About a year ago, I started
a project to implement this, but I have not finished it. Here is
a brief statement of my goals:
Development of a structure for streaming object data to
and from a file stream. The goal is to be able to read
both old and new data on both old and new versions of
the object oriented code, kind of like a one-file object
oriented database (OODB). -- JohnH, 02/03/04
I defined a "structure" object (tBasicStrucObj) to be the
owner of all of the data objects which all are descendants
of a basic streamable data object (tBasicStreamObj).
When writing, the objects are given a number and an
index of the cross references is created and written to
the stream. The object class *definitions* have a name
and version number, which is streamed and used to
recreate the same on reloading. When loading data
written in extended versions is loaded in older programs,
the extended data which the old program does not know
how to handle is ignored -- kind of like how old versions
of Excel can read files created on newer version of Excel.
I avoid the use of RTTI and TPersistent / TComponent.
Regards, JohnH
|
|
| Back to top |
|
 |
Charles McAllister Guest
|
Posted: Sun Jan 23, 2005 7:33 pm Post subject: Re: WANTED! Object streaming system. |
|
|
"Martin Harvey (Demon Account)" <martin (AT) nospam_pergolesi (DOT) demon.co.uk> wrote
in message news:ad46v0hfre9dvuqvcip0l4m7k4hglp3abh (AT) 4ax (DOT) com...
| Quote: | a) Streamable classes must be declared {$M+}
b) For streaming of some custom properties, or BLOBS, where RTTI might
not do the trick, the classes can implement an optional interface
(IStreamable?)
snip
I think I could do most of this with RTTI. The only big question mark
I have is supporting array properties - in particular, arrays of
pointers to other streamable classes. Is there an RTTI supported
"potted solution" to this, or am I going to have to implement an
ad-hoc solution?
|
in order to keep things simple I think you'd have to add a few more
requirements of your objects...
c) streamable classes must be registered (e.g. RegisterClass, or if not
TPersistent then some custom registration scheme)
d) streamable class hierarchies must employ a virtual constructor
|
|
| Back to top |
|
 |
Rudy Velthuis [TeamB] Guest
|
Posted: Sun Jan 23, 2005 7:38 pm Post subject: Re: WANTED! Object streaming system. |
|
|
John Herbster wrote:
| Quote: |
Here is a brief statement of my goals:
Development of a structure for streaming object data to
and from a file stream. The goal is to be able to read
both old and new data on both old and new versions of
the object oriented code, kind of like a one-file object
oriented database (OODB). -- JohnH, 02/03/04
|
I guess you could find a plethora of good and existing ideas in the
borland.public.oodesign group.
--
Rudy Velthuis [TeamB] http://rvelthuis.bei.t-online.de
"It is a miracle that curiosity survives formal education." -- Albert
Einstein
|
|
| Back to top |
|
 |
Charles McAllister Guest
|
Posted: Sun Jan 23, 2005 7:42 pm Post subject: Re: WANTED! Object streaming system. |
|
|
"Charles McAllister" <charles (AT) avimark (DOT) net> wrote
| Quote: | d) streamable class hierarchies must employ a virtual constructor
Actually this is more of a design recomendation than a requirement. |
Typically objects that are automatically created use virtual constructors.
For example, TComponent's Create method is virtual.
|
|
| Back to top |
|
 |
Martin Harvey (Demon Acco Guest
|
Posted: Sun Jan 23, 2005 10:15 pm Post subject: Re: WANTED! Object streaming system. |
|
|
On Sun, 23 Jan 2005 12:18:02 +0100, "Peter Below (TeamB)"
<100113.1101 (AT) compuXXserve (DOT) com> wrote:
| Quote: | In article <ad46v0hfre9dvuqvcip0l4m7k4hglp3abh (AT) 4ax (DOT) com>, Martin Harvey (Demon
Account) wrote:
The "pointers to other streamable classes" (i assume you mean objects here)
is a big problem. Pointers (memory addresses) are meaningless outside the
|
<snip>
| Quote: | other ways as well (the referenced objects need to have a known Owner, for
example, so they can be found using the Name).
|
Yep. I've been round this loop before, since I wrote a syteaming
system quite a few years back: my general plan was to have a way of
recursing through all the objects in the datastructure, effectively
getting them to register with the streaming engine, so that I could
generate a fix-up table.
Originally, in the old system, the registration and marshalling was
done manually via virtual methods in the streamable classes. I'm
planning to have a very similar system with:
- Streaming:
- Registration step (discover all objects)
- Generate fix-up table.
- Marshal all data fields in objects, using fix up table if object
references.
- De-streaming.
- Load fix-up table.
- Polymorphically create all objects.
- Un marshal fields, and if there's a "disconnected" class, then
warn, and destroy it.
The only difference is that this time, I'd like to cope with most of
the simple cases via RTTI, and then have an interface that the classes
support for more unusual or complex cases.
| Quote: | This is one of the reasons why streamable classes usually need to be designed
for streaming from the word GO. This way you can build a unique ID of some
kind into the base class of the hierarchy.
|
Well, I do plan on having a base class, such that a;; streamed classes
descend from it - my issue is that in any particular project that
streaming classes are involved, I might want that particular base
class to be somewhere else in the heirarchy - hence why, for any
particular project, I'd like the base class, to be declared $M+ and
implement an "IStreamable" interface. For the current project the
class type (TTransferrable) looks to be about here in the heirarchy:
TObject ->
TTrackable -> TLoggable -> TMultiThreadData -> TTransferrable
However, for other projects, it might be:
TObject -> TPersistent -> TOtherTransferrable.
So, I could initially set the syteaming system up with a class
reference type which indicated what all the classes must descend from.
| Quote: | All in all not an easy task <g>.
|
Well, I've done it before, so I'm familiar with most of the pitfalls -
the only additions I want this time are:
- Flexible base class by using an interface to implement "plug in"
functionality for nonstandard streaming.
- Handling of basic properties via RTTI.
The latter I think I can do via scrutinising TypInfo. The former I'm
not so sure about, because I haven't used interfaces much in Delphi.
- Is there a decent way of checking: "Does object X implement
interface Y"?
- Additionally, I want the interface to just be a table of function
pointers that can be acquired. I *don't* want to implement reference
counting (AddRef, Release) on the interface, because the lifetime of
the objects is managed separately.
MH.
|
|
| Back to top |
|
 |
Martin Harvey (Demon Acco Guest
|
Posted: Sun Jan 23, 2005 10:25 pm Post subject: Re: WANTED! Object streaming system. |
|
|
On Sun, 23 Jan 2005 13:33:40 -0600, "Charles McAllister"
<charles (AT) avimark (DOT) net> wrote:
| Quote: | in order to keep things simple I think you'd have to add a few more
requirements of your objects...
c) streamable classes must be registered (e.g. RegisterClass, or if not
TPersistent then some custom registration scheme)
d) streamable class hierarchies must employ a virtual constructor
|
Ah yes ... this will be required for polymorphic creation on the
receiving side. Been there before - failure to do these two things
results in an A.V :-)
Additionally, that means that if I want to have a variable base class,
then I need to register a "creation function" with the sytreaming
system, so that the class reference can be typecast appropriately,
e.g:
TStreamableBase
public
constructor Create; virtual;
end;
TStreamableBaseClass = class of TStreamableBase;
function CustomCreate(ClassName: string): TObject;
var
RawClass: TClass;
begin
result := nil;
RawClass := FindClass(ClassName);
if RawClass.DescendsFrom(TStreamableBaseClass) then
result := TStreamableBaseClass(RawClass).Create;
end;
However, I notice that GetClass and FindClass return TPersistentClass,
I'm assuming because you need $M+.... I suspect that for arbitrary
classes not descending from TPersistent, I'd need to create my own
versions of FindClass and GetClass which could do the traversal and
return something of type TClass.
Question is, will this work? Does RegisterClass add the RTTI info into
the same place that TypInfo reads out of? All the delphi help says is
"Registers it with the streaming system", which *might* not
necessarily be the same thing...
Alternatively, I just restrict the base class type to be a child of
TPersistent....
MH.
|
|
| Back to top |
|
 |
Martin Harvey (Demon Acco Guest
|
Posted: Sun Jan 23, 2005 10:25 pm Post subject: Re: WANTED! Object streaming system. |
|
|
On Sun, 23 Jan 2005 13:42:49 -0600, "Charles McAllister"
<charles (AT) avimark (DOT) net> wrote:
| Quote: | Actually this is more of a design recomendation than a requirement.
Typically objects that are automatically created use virtual constructors.
For example, TComponent's Create method is virtual.
|
If the constructor isn't virtual, then it won't get invoked for
polymorphic creation, which is probably not what I want...
MH.
|
|
| Back to top |
|
 |
Charles McAllister Guest
|
Posted: Mon Jan 24, 2005 12:06 pm Post subject: Re: WANTED! Object streaming system. |
|
|
Martin Harvey (Demon Account) wrote:
| Quote: | function CustomCreate(ClassName: string): TObject;
var
RawClass: TClass;
begin
result := nil;
RawClass := FindClass(ClassName);
if RawClass.DescendsFrom(TStreamableBaseClass) then
result := TStreamableBaseClass(RawClass).Create;
end;
However, I notice that GetClass and FindClass return TPersistentClass,
I'm assuming because you need $M+.... I suspect that for arbitrary
classes not descending from TPersistent, I'd need to create my own
versions of FindClass and GetClass which could do the traversal and
return something of type TClass.
You're custom FindClass will have to lookup the class in a list that you maintain. I use TClassList |
for this.
| Quote: | Question is, will this work? Does RegisterClass add the RTTI info into
the same place that TypInfo reads out of? All the delphi help says is
"Registers it with the streaming system", which *might* not
necessarily be the same thing...
You dont need to call RegisterClass to get RTTI to work. $M+ is sufficient for that. |
| Quote: | Alternatively, I just restrict the base class type to be a child of
TPersistent....
Too limiting and not necessary. For instance, you might want a streamable base class for supporting |
interfaces.
|
|
| Back to top |
|
 |
Charles McAllister Guest
|
Posted: Mon Jan 24, 2005 12:30 pm Post subject: Re: WANTED! Object streaming system. |
|
|
Martin Harvey (Demon Account) wrote:
- I want to be able to stream fairly arbitrary classes - i.e. not
| Quote: | limited to TPersistent / TComponent descendants. However, I'm willing
to put up with the following limitations, which I think will cover the
difficulties:
Here's some code that will stream any TObject. |
It won't however, do recursive style streaming of child objects.
Here's how I handle child objects. I publish both the child object as well as the child's unique
ID. I stream only the ID. Child references get created after loading from a stream takes place,
and only by 'fetch on demand'. This requirement, that all objects have a unique ID, may not fit for
your needs.
{$include mcs.inc}
unit umcsPropertyInfo;
interface
uses
SysUtils,
Classes,
Contnrs,
TypInfo,
umcsUtils;
const
SupportedPropertyTypes: set of TTypeKind = [
tkSet,
tkEnumeration,
tkInteger, //Byte, Smallint, Word, Integer
tkChar,
tkFloat, //Double, Single
tkString, //ShortString
tkLString, //string
tkInterface];
type
TmcsPropertyInfo = class (TObject)
private
FPropertyCount: Integer;
FPropList: PPropList;
function _GetPropInfo(AObject: TObject; Index: Integer): PPropInfo;
function GetPropInfoByName(AObject: TObject; PropName: string): PPropInfo;
function _GetTypeData(AObject: TObject; Index: Integer): PTypeData;
function GetTypeDataByName(AObject: TObject; PropName: string): PTypeData;
function GetPropertyClass(AObject: TObject; Index: Integer): TClass;
function GetPropertyClassByName(AObject: TObject; PropName: string): TClass;
protected
property PropList: PPropList read FPropList;
public
constructor Create(AObject: TObject);
destructor Destroy; override;
procedure PropertiesToStream(AObject: TObject; AStream: TStream); virtual;
procedure StreamToProperties(AStream: TStream; AObject: TObject); virtual;
function IndexOf(AObject: TObject; PropName: string): Integer;
property PropertyCount: Integer read FPropertyCount;
property PropertyClass[AObject: TObject; Index: Integer]: TClass read GetPropertyClass;
property PropertyClassByName[AObject: TObject; PropName: string]: TClass read
GetPropertyClassByName;
property TypeData[AObject: TObject; Index: Integer]: PTypeData read _GetTypeData;
property TypeDataByName[AObject: TObject; PropName: string]: PTypeData read
GetTypeDataByName;
property PropInfo[AObject: TObject; Index: Integer]: PPropInfo read _GetPropInfo;
property PropInfoByName[AObject: TObject; PropName: string]: PPropInfo read
GetPropInfoByName;
end;
implementation
{- TmcsPropertyInfo }
constructor TmcsPropertyInfo.Create(AObject: TObject);
var
Index: Integer;
PropInfo: PPropInfo;
begin
inherited Create;
FPropertyCount := GetPropList(AObject.ClassInfo, tkAny, nil, False);
GetMem(FPropList, FPropertyCount * SizeOf(Pointer));
//Assert(Assigned(FPropList)); FProplist is nil if FPropertyCount = 0
// its ok if FPropList is nil...
FPropertyCount := GetPropList(AObject.ClassInfo, tkAny, FPropList, False);
for Index := 0 to FPropertyCount - 1 do
begin
PropInfo := GetPropInfo(AObject, FPropList^[Index].Name);
Assert(PropInfo.PropType^^.Kind in SupportedPropertyTypes,
Format('Unsupported streamable property %s', [PropInfo.PropType^^.Name]));
end;
end;
destructor TmcsPropertyInfo.Destroy;
begin
if Assigned(FPropList) then
FreeMem(FPropList, FPropertyCount * SizeOf(Pointer));
inherited;
end;
procedure TmcsPropertyInfo.PropertiesToStream(AObject: TObject; AStream: TStream);
var
PropIndex: Integer;
PropInfo: PPropInfo;
procedure WriteOrdProperty;
var
TempInt: Integer;
begin
TempInt := GetOrdProp(AObject, PropInfo);
AStream.Write(TempInt, SizeOf(TempInt));
end;
procedure WriteFloatProperty;
var
TempDouble: Double;
begin
TempDouble := GetFloatProp(AObject, PropInfo);
AStream.Write(TempDouble, SizeOf(TempDouble));
end;
procedure WriteStrProperty;
begin
umcsUtils.WriteStringToStream(GetStrProp(AObject, PropInfo), AStream);
end;
begin
for PropIndex := 0 to FPropertyCount - 1 do
begin
PropInfo := GetPropInfo(AObject, FPropList[PropIndex].Name);
case PropInfo.PropType^^.Kind of
tkSet, tkEnumeration, tkInteger, tkChar:
WriteOrdProperty;
tkFloat:
WriteFloatProperty;
tkLString,
tkString:
WriteStrProperty;
else
end;
end;
end;
procedure TmcsPropertyInfo.StreamToProperties(AStream: TStream; AObject: TObject);
var
PropIndex: Integer;
PropInfo: PPropInfo;
procedure ReadOrdProperty;
var
TempInt: Integer;
begin
AStream.Read(TempInt, SizeOf(TempInt));
SetOrdProp(AObject, PropInfo, TempInt);
end;
procedure ReadFloatProperty;
var
TempDouble: Double;
begin
AStream.Read(TempDouble, SizeOf(TempDouble));
SetFloatProp(AObject, PropInfo, TempDouble);
end;
procedure ReadStrProperty;
var
TempStr: string;
begin
TempStr := umcsUtils.ReadStringFromStream(AStream);
SetStrProp(AObject, PropInfo, TempStr);
end;
begin
for PropIndex := 0 to FPropertyCount - 1 do
begin
PropInfo := GetPropInfo(AObject, FPropList[PropIndex].Name);
case PropInfo.PropType^^.Kind of
tkSet, tkEnumeration, tkInteger, tkChar:
ReadOrdProperty;
tkFloat:
ReadFloatProperty;
tkLString,
tkString:
ReadStrProperty;
else
raise Exception.CreateFmt('Unsupported streamable property %s', [PropInfo.PropType^^.Name]);
end;
end;
end;
function TmcsPropertyInfo._GetPropInfo(AObject: TObject; Index: Integer): PPropInfo;
begin
Assert(Assigned(FPropList));
Assert(Assigned(FPropList^[Index]));
Result := GetPropInfo(AObject, FPropList^[Index].Name);
end;
function TmcsPropertyInfo.GetPropInfoByName(AObject: TObject; PropName: string): PPropInfo;
begin
Result := GetPropInfo(AObject, PropName);
end;
function TmcsPropertyInfo._GetTypeData(AObject: TObject; Index: Integer): PTypeData;
begin
Result := GetTypeData(_GetPropInfo(AObject, Index).PropType^);
end;
function TmcsPropertyInfo.GetTypeDataByName(AObject: TObject; PropName: string): PTypeData;
var
APropInfo: PPropInfo;
begin
APropInfo := GetPropInfoByName(AObject, PropName);
if Assigned(APropInfo) then
Result := GetTypeData(APropInfo.PropType^)
else
Result := nil;
end;
function TmcsPropertyInfo.GetPropertyClass(AObject: TObject; Index: Integer): TClass;
var
APropInfo: PPropInfo;
begin
Result := nil;
APropInfo := PropInfo[AObject, Index];
if APropInfo.PropType^^.Kind = tkClass then
Result := TypeData[AObject, Index].ClassType;
end;
function TmcsPropertyInfo.GetPropertyClassByName(AObject: TObject; PropName: string): TClass;
begin
Result := nil;
if PropInfoByName[AObject, PropName].PropType^^.Kind = tkClass then
Result := TypeDataByName[AObject, PropName].ClassType;
end;
function TmcsPropertyInfo.IndexOf(AObject: TObject; PropName: string): Integer;
var
APropInfo: PPropInfo;
begin
APropInfo := PropInfoByName[AObject, PropName];
if Assigned(APropInfo) then
Result := APropInfo.NameIndex
else
Result := -1;
end;
end.
umcsUtils.pas:
procedure WriteStringToStream(InStr: string; AStream: TStream);
var
TempInt: Integer;
begin
TempInt := Length(InStr);
AStream.Write(TempInt, SizeOf(TempInt));
if TempInt > 0 then
AStream.Write(InStr[1], TempInt);
end;
function ReadStringFromStream(AStream: TStream): string;
var
TempInt: Integer;
begin
AStream.Read(TempInt, SizeOf(TempInt));
if TempInt > 0 then
begin
SetLength(Result, TempInt);
AStream.Read(Result[1], TempInt);
end
else
Result := EmptyStr;
end;
|
|
| Back to top |
|
 |
Martin Harvey (Demon Acco Guest
|
Posted: Mon Jan 24, 2005 7:24 pm Post subject: Re: WANTED! Object streaming system. |
|
|
On Mon, 24 Jan 2005 06:30:28 -0600, Charles McAllister
<charles (AT) avimark (DOT) net> wrote:
| Quote: | Here's some code that will stream any TObject.
It won't however, do recursive style streaming of child objects.
Here's how I handle child objects. I publish both the child object as well as the child's unique
ID. I stream only the ID. Child references get created after loading from a stream takes place,
and only by 'fetch on demand'. This requirement, that all objects have a unique ID, may not fit for
your needs.
|
Thank You! That's very useful to me :-)
Actually, quite a few things become clear now, which I questioned a
bit in my previous post.
1) TObject.GetClassInfo returns the pointer to the TypeInfo for the
class, which provides the class name, and if you get the type data as
well, then you can get the class type. Fine.
2) I was wondering why, if something was declared as $M+, you couldn't
polymorphically create it without registration.
Looking more carefully at the info for class type tkClass, I notice
that you can get to the type info for the parent class, but not any of
the children.
Additionally even if the above were not the case, if your class is not
a descendant of TPersistent, there's a chance that having navigated
back to the type data for TObject, since it's not $M+, you might find
that there's not enough info there to work with anyway.
OK - now mostly makes sense. For my polymorphic creation, looks like
I'll have to maintain my own list as you say, and then once the
"shared" streaming system has located the class, it'll have to call a
function in the particular app to typecast the resulting class type to
ensure the virtual constructor gets called.
Cool, so now all I have to fret about it how to do this darn interface
thing to allow plug-in behaviour for classes that want special
attention. My main concern is BLOBS, and also the fact that I'll
probably have a class with an array property of class references - but
maybe RTTI will cope with that, I'll have to RTFM a bit more.
MH.
|
|
| Back to top |
|
 |
Charles McAllister Guest
|
Posted: Mon Jan 24, 2005 7:50 pm Post subject: Re: WANTED! Object streaming system. |
|
|
Martin Harvey (Demon Account) wrote:
| Quote: | Okay, here's where I look *really* stupid. I'm fairly familiar with
interfaces in C++, but not in Delphi, and I might need a quick
refresher here:
Can classes descending from TPersistent not support interfaces?
In which case, which classes can support interfaces?
All classes can support interfaces. Its just that if you happen to be directly descending from |
TObject, and you want to support an interface, you'll have to do a bit of work. See
TInterfacedObject's implementation for what is required. You might also have found
TInterfacedPersistent, which can be handy to use, but is not reference counted. So you lose out on
some automatic memory management.
| Quote: | Delphi "attaches" interfaces to classes in a similar way to C++?
The interfaces are basically a set of extra virtual method tables in
disguise?
Delphi does a bit more I think. The compiler always inserts method calls to _AddRef and _Release, |
whenever an interface reference goes out of scope. Once the reference count goes to zero, the
interface is automatically freed. A class supporting an interface can opt to pass -1 as a result to
those two methods, in which case the interface reference will never be freed automatically.
TInterfacedObject will reference count, but TInterfacedPersistent and TComponent will not.
| Quote: | I notice that TInterfacedObject does basically what one would expect
for interfaces.
However, what if I want to ditch the refcounting and such like, and
query another object (not a child of TInterfacedObject) directly for
the interface? I'm assuming I use TObject.GetInterface.
This would be very useful, because the objects I want to export a
streamable interface are probably not going to derive from
TInterfacedObject.
However, what happens with the general lack of ref counting and such
like, and matching up the GUID is now a mystery to me ....
Sorry to look so stupid ... I need to RTFM a bit more.
If you can get a copy, most people on this group recommend Eric Harmon's "Delphi COM Programming" to |
give a good introduction to interfaces.
http://www.amazon.com/exec/obidos/tg/detail/-/1578702216/qid=1106596127/sr=1-2/ref=sr_1_2/103-1412497-0871865?v=glance&s=books
|
|
| Back to top |
|
 |
Charles McAllister Guest
|
Posted: Mon Jan 24, 2005 7:52 pm Post subject: Re: WANTED! Object streaming system. |
|
|
| Quote: | Sorry to look so stupid ... I need to RTFM a bit more.
....and you don't look stupid. You're actually asking all the right questions.  |
|
|
| Back to top |
|
 |
Peter Morris [Droopy eyes Guest
|
Posted: Mon Jan 24, 2005 7:58 pm Post subject: Re: WANTED! Object streaming system. |
|
|
| Quote: | Right. $M+ puts RTTI in. That is to say (in Delphi land) that all of the
functions in TypInfo.pas are available. These functions allow you to
determine property information in the published section of a class. None
of those functions allow you to get a TClass from a class name.
|
Calling RegisterClass will do no harm. Additionally, I have had occasions
where FindClass will return nil unless I use RegisterClass first.
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|