Unexpected behavior when using both alias this and object pointer

Ali Çehreli via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Thu Jan 12 13:54:21 PST 2017


Hiding a Foo right after Impl can be a solution. However, you need to 
pass 't', not '&t' to the C function because

- Although it may be unexpected, cast(void*) is the specified way of 
getting the address of a class object

- Taking the address of a class reference (which 't' is one), is just 
the address of the reference itself

So, you either have to do something similar to the following or pass 
void* to the C function.

import std.stdio: writeln;
import core.stdc.stdlib: malloc;

struct Impl {
     ubyte[8] payload;
}

struct ImplWithOwner {
     Impl impl;
     Foo owner;
}

class Foo {
     ImplWithOwner *io;

     Impl *payload() {
     // Guaranteed by D for structs:
     assert(cast(void*)io == cast(void*)&io.impl);
         return &io.impl;
     }

     alias payload this;

     this() {
         io = cast(ImplWithOwner*) malloc(Impl.sizeof);
         io.owner = this;
     }
}

static Foo asFoo(Impl* p) {
     return (cast(ImplWithOwner*)p).owner;
}

extern(C)
void actual_C_function(Impl* data, void function(Impl*) callback) {
     data.payload[0] = 42;
     callback(data);
}

extern(C)
void myCallback(Impl* p) {
     auto foo = p.asFoo;
     assert(foo.io.impl.payload[0] == 42);
}

void main() {
     auto t = new Foo();
     actual_C_function(t, &myCallback);
}

Ali



More information about the Digitalmars-d-learn mailing list