According to Pierre Phaneuf:
I just checked out the new bpcompat sources... Did anyone actually *USED* the OBJECTS.PAS unit??? More specifically, the TStream Put and Get methods? They are obviously broken...
This is a very first release, and the `tStream' object is marked as "{ !!! not complete !!! }". Now you know what was meant with the statement "and some of the routines do not work well" in the announcement.
Ok, so those are difficult parts, but still... What I need is two things: a way to tell what is the real type of an object like the typeof() function (didn't check if it was there),
It is there since gpc-970510 (see the announcement).
and a way to construct an object of an type as returned by typeof().
From the announcement of gpc-970510:
* `TypeOf' applied to object variables works now, too. As a GPC extension, you can explicitly assign a value to "TypeOf ( MyObj )" if extended syntax is ON (*$X+*).
This means that, with (*$X+*), you can explicitly assign a `TypeOf' to an object. I implemented this extension just for the purpose to write the `tStream.Get' method. (In BP, this is achieved with assembler, but we want to have it portable for GPC.)
Something that would enable me to do something so that new(typeof(TMyObject), Init) creates an instance of TMyObject, calls Init and returns a pointer to the newly created object would be just *perfect*.
Please add it to `objects.pas'! My suggestion:
1) Write a `RegisterType' function, so you can read the `ObjType' out of the stream and look up its `VmtLink'.
2) Replace the `New' in `tStream.Get' by a `GetMem' with the Size read off the VMT (a Word variable at the very beginning of the VMT).
3) Explicitly assign `VmtLink' to `TypeOf ( the new object )'.
4) Call the object's `Load' constructor.
Please join us in improving GPC!
Greetings,
Peter
Dipl.-Phys. Peter Gerwinski, Essen, Germany, free physicist and programmer peter.gerwinski@uni-essen.de - http://home.pages.de/~peter.gerwinski/ [970201] maintainer GNU Pascal [970510] - http://home.pages.de/~gnu-pascal/ [970125]
On Fri, 23 May 1997, Peter Gerwinski wrote:
From the announcement of gpc-970510:
- `TypeOf' applied to object variables works now, too. As a GPC extension, you can explicitly assign a value to "TypeOf ( MyObj )" if extended syntax is ON (*$X+*).
This means that, with (*$X+*), you can explicitly assign a `TypeOf' to an object. I implemented this extension just for the purpose to write the `tStream.Get' method. (In BP, this is achieved with assembler, but we want to have it portable for GPC.)
I actually had it done without assembler in BP in a compatible manner (in my own version of the stream system), but still incompatible.
Something that would enable me to do something so that new(typeof(TMyObject), Init) creates an instance of TMyObject, calls Init and returns a pointer to the newly created object would be just *perfect*.
Please add it to `objects.pas'! My suggestion:
Write a `RegisterType' function, so you can read the `ObjType' out of the stream and look up its `VmtLink'.
Replace the `New' in `tStream.Get' by a `GetMem' with the Size read off the VMT (a Word variable at the very beginning of the VMT).
Ah, I didn't knew the size was at the beginning of the VMT... But this isn't quite the Right Way (if the VMT format changes for whatever reason), no?
Explicitly assign `VmtLink' to `TypeOf ( the new object )'.
Call the object's `Load' constructor.
This could cause problems. How shall I call the Load constructor?
function CreateObject(VMTLink: pointer; S: PStream): PObject; var P: PObject; Size: ^word; begin Size:=VMTLink; getmem(P, Size^); TypeOf(P):=VMTLink; P^.Load(S); end;
This wouldn't work (in BP at least), since this will call TObject's Load constructor and it will reset the type of the object to TObject, whatever has been set with TypeOf().
On the other hand, if I call it using a pointer to the Load constructor (so that I get the right constructor), I don't even have to set the TypeOf() of the object, since it is set by the constructor itself (like in BP), but I have to do the method call by hand, just like the assembler part in the Borland OBJECTS.PAS or my no-assembler solution (which looked like the following and is just as dependent on compilers internals).
type TLoadConstructor = function(S: PStream; VMTOffset: word; ASelf: pointer): pointer;
(I'm not quite that sure about the parameter order, it is important)
Then I called the constructor like this:
P:=TLoadConstructor(LoadPtr^)(S, ofs(VMTLink), nil);
The "nil" for self causes the constructor to allocate the right amount of memory for the object before calling the constructor. The pointer to the object instance is returned by the function. Note that this produces almost the same code (in BP) as a new() function call, but this is extremely dependent on the compilers internals!
I guess that we cannot extend new() so that passing it a VMT pointer would make it instantiate the correct object type and call the right constructor, but how does it work when it gets PObject as a first parameter? Maybe some meta-function that returns the type itself? ;-)
What do you think?
"The use of COBOL cripples the mind; its teaching should, therefore, be regarded as a criminal offense." - Edsger W. Dijkstra.