Should this always work?
Steven Schveighoffer
schveiguy at gmail.com
Sat May 1 16:06:05 UTC 2021
On 5/1/21 12:55 AM, frame wrote:
> I always thought as long as an object implements an interface, it should
> be able to cast it from a void* if it really points to a supporting object.
>
> I have the similar structure:
>
>
> ```d
> interface AI {
> string doSomething();
> }
>
> template S() {
> void foo() {
>
> }
> }
>
> abstract class A : AI {
> string doSomething() {
> return "Hello, World";
> }
> }
>
> class B : A {
> mixin S;
>
> void other() {
>
> }
> }
>
> auto b = new B;
> auto p = cast(void*) b;
> auto c = cast(AI) p;
>
> c.doSomething();
> ```
>
> But in my code with the real object, this generates a RangeError,
> AcccesError, memory garbage:
> ```d
> auto b = new B;
> auto p = cast(void*) b;
> auto c = cast(AI) p; // AI with corrupt data
>
> c.doSomething(); // error
> ```
>
> But this works:
> ```d
> auto b = new B;
> auto p = cast(void*) b;
> auto c = cast(A) p; // A with correct data
>
> c.doSomething(); // no error
> ```
>
> If the runtime could not successfully cast it to AI, it should return
> null. Am I wrong here?
An interface cast involves a thunk (constant pointer adjustment) to get
to the interface/object. The reason is because a class with interfaces
stores interface vtable pointers inside the object, and your interface
reference points at that. You can see when you cast between Object
(concrete) type and Interface type, the pointer value changes.
So this will not work. It *does* work for base classes, because the
class vtable pointer is stored at same point, and casting around class
references does not involve a thunk.
If you want this to work, you have to know whether the void* pointer is
pointing at an object, or an interface. If you know it's pointing at an
object, you can get to the interface via:
auto c = cast(AI)cast(Object)p;
Which will perform the appropriate thunks.
If you know it's a pointer to the AI interface directly, you can just
cast it directly.
-Steve
More information about the Digitalmars-d-learn
mailing list