Problem with casting instance reference to void* and back.

anonymous via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Mon Jul 27 06:11:29 PDT 2015


On Monday, 27 July 2015 at 12:03:06 UTC, Vlad Leberstein wrote:
> Hi! My use case requires interaction with C API which in turn 
> implies storing object instance reference as void *. I'm using 
> gdc 4.9.2 and everything worked fine with "object -> void * -> 
> object" conversion, but "object -> void * -> interface" failed. 
> The stripped-down example is something like this:
>
> interface TestInterface {
>     void testMethod();
> }
>
> class TestImpl : TestInterface {
>     void testMethod() {
>         writefln("TestImpl::testMethod\n");
>     }
> };
>
> void testDispathcer(void *rawSelf) {
>     auto self = cast(TestInterface) rawSelf;
>     // nothing happens
>     self.testMethod();
> }
>
>
> int main(string[] args) {
>     auto t = new TestImpl();
>     testDispathcer(cast(void *) t);
>     return 0;
> }
>
> However this works:
>
> void testDispathcer(TestImpl rawSelf) {
>     auto self = cast(TestInterface) rawSelf;
>     // TestImpl::testMethod is printed to stdout
>     self.testMethod();
> }
>
>
> int main(string[] args) {
>     auto t = new TestImpl();
>     testDispathcer(t);
>     return 0;
> }
>
> Is there any way to handle such situation without resorting to 
> templating dispatcher with every *Impl type? As second example 
> works as expected I presume that runtime loses some type 
> information to perform downcast and maybe it's possible to 
> extract it and store externally and merge back later?
>
> I'm quite new to D and sorry if the question is dumb. Any help 
> would be greatly appreciated! Thanks in advance!

In the first example, you pass a pointer to a class instance. You 
cannot get the vtbl entry for the interface like this. Instead 
try to do this in 2 steps:

---
import std.stdio;

interface TestInterface {
     void testMethod();
}

class TestImpl : TestInterface {
     void testMethod() {
         writefln("TestImpl::testMethod\n");
     }
};

void testDispathcer(void *rawSelf) {
     auto obj = cast(Object) rawSelf;
     auto self = cast(TestInterface) obj;
     // nothing happens
     self.testMethod();
}


int main(string[] args) {
     auto t = new TestImpl();
     testDispathcer(cast(void *) t);
     return 0;
}
---


More information about the Digitalmars-d-learn mailing list