I've always been under the impression that objects in Delphi are in fact references to memory locations, which in turn I've imagined were stored as pointer variables.
Now, I want to make a TValue from an object. Consider this:
TValue.Make(AObject, TypeInfo(TMyObject), val);
where val: TValue
. This won't work. In fact, subsequent usage of val
will lead to an access violation. However, if we use the address-of operator, like so:
TValue.Make(@AObject, TypeInfo(TMyObject), val);
all is good. For me, this was unexpected, as I thought AObject was (under the hood) in fact a pointer. Am I wrong or is this a quirk with the TValue.Make method? Could someone please enlighten me?
procedure Foo;
var
I: Integer; // value type
O: TObject; // reference type
begin
@I; // Get a pointer to I
O := TObject.Create;
@O; // Get a pointer to the memory "behind" the reference O
end;
Normally that doesn't matter much, because the compiler knows when to dereference and when not to.
In the case of TValue.Make
the function takes a pointer.
Make(O...
the compiler will hard cast the reference to a pointer (which points to the stack).Make(@O...
the compiler will first dereference and then create a pointer to the location on the heap.So you have to give the compiler a hint in this case, because it doesn't know which kind of pointer the TValue.Make
expects.
The ABuffer argument you pass to TValue.Make is the pointer to the value you want to store inside the TValue. It does not matter if the type itself is a pointer type or not. So you have to pass the reference to AObject even if AObject itself is also a pointer.
In the example you posted I would prefer to use the TValue.From<T> method:
val := TValue.From<TMyObject>(AObject);
If the typeinfo is not known at compiletime you have to use TValue.Make - otherwise TValue.From<T> is easier to use.
In your example, AObject is a reference to an object, not the object itself. This is the way to declare object reference in Delphi as opposed to other language where you must explicitly add refrence or pointer to the object.
So AObject or @AObject should work the same in your case, but as TValue.Make()
take a pointer to a buffer in the first parameter, you should provide Addr(AObject)
or @AObject
to the function.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With