How do I get a variant from a pointer in Delphi?
Asked Answered
C

1

6

I need to be able to convert a naked pointer to a variant. I know that the pointer points to a variant, but I can't seem to get it back out. A straight cast (as I pretty much thought) fails:

Result := Variant(FAddress)^

returns a compiler error: [DCC Error] E2089 Invalid typecast

I've scoured the variants.pas unit as well, but nothing jumped out at me.

Obviously I'm missing something. What is the way to do this?

Corporeity answered 13/4, 2011 at 18:39 Comment(0)
P
16

If the pointer points at a Variant, then its type is PVariant. Type-cast it to that, and then dereference:

Result := PVariant(FAddress)^;

Better yet, declare FAddress with the right type to begin with, and then you don't need to typecast:

var
  FAddress: PVariant;

Result := FAddress^;

The compiler considers your attempted type-cast invalid because Variant is a bigger type than Pointer is. The compiler doesn't know where to get the additional data to create a full Variant value. And if the type-cast were valid, the use of the ^ operator isn't allowed on Variants anyway. You might have gotten away with this:

Result := Variant(FAddress^);

I've never liked that; if FAddress is an untyped pointer, then dereferencing it yields a value without any size or type at all, and it's just weird to type-cast such a thing.

Prognosis answered 13/4, 2011 at 18:41 Comment(7)
Funny, I don't have a problem with Variant(FAddress^). I don't see it as any different from PVariant(FAddress)^.Weald
Thanks, Rob, that seems to work. I'm actually modifying an existing library, and didn't want to (yet) make radical changes.Corporeity
@David, in Variant(FAddress^), the intermediate value in that expression has no type at all. I see it as momentarily programming "without a net," and that gives me the willies. In PVariant(FAddress)^, there's still a typeless thing somewhere, but we never access it directly. We assign a type to it first, and then start using it.Prognosis
@Rob I know what you are getting at, but think of it this way. Since you can't dereference a pointer typeless thing, how could it mean anything different from your preferred version? Another way to put it is that there isn't an intermediate value. There isn't an intermediate value in your version either.Weald
@Rob Or this way. In order to assign a variable, you need to specify the location and type of both lvalue and rvalue. You can't do assignment with just type, or just location. So you have to specify both and you can do that in either order. At least that's the mental model I've got!Weald
@David, in my mental model, there is an intermediate value. We start with FAddress, with type Pointer. Then we evaluate FAddress^ to get a value of type who-knows-what. Finally, we evaluate the type-cast to get a value of type Variant. In my preferred way, we evaluate PVariant(FAddress) first to get a value of type PVariant. Then we dereference that to get a value of type Variant. At the CPU level, those aren't all separate evaluation steps, but at the level I'm used to from formal study of programming-language analysis, they're all separate steps with distinct semantics.Prognosis
@Rob I'd probably always write it that way round too, for what it's worth. How do you feel about typeless const parameters. You don't feel the need to get the address of them, cast to a typed parameter and then de-reference do you?Weald

© 2022 - 2024 — McMap. All rights reserved.