The code at the end with extern(C++) prints:
fooImpl @ 0x7fa6503c1000
foo @ 0x7fa6503c1008
foo @ 0x7fa6503c1008
fooImpl @ 0x7fa6503c1008
If the interface and class are extern(D) it (correctly) prints:
fooImpl @ 0x7fa6503c1000
foo @ 0x7fa6503c1008
foo @ 0x7fa6503c1008
fooImpl @ 0x7fa6503c1000
Casting from the class to the interface works in both cases and adds 8 bytes to the pointer. Casting back from interface to the class only works for extern(D) and fails for extern(C++): there's no way to get the original pointer back except for manually subtracting 8 bytes.
Code to reproduce:
import core.stdc.stdio: printf;
extern(C++) interface Foo {
int foo();
}
extern(C++) class FooImpl: Foo {
override int foo() { return 42; }
}
void main() {
auto fooImpl = new FooImpl;
printf("fooImpl @ %p\n", fooImpl);
Foo foo = fooImpl;
printf("foo @ %p\n", foo);
printf("\n");
takingFoo(foo);
}
void takingFoo(Foo foo) {
printf("foo @ %p\n", foo);
FooImpl fooImpl = cast(FooImpl) foo; // oops
printf("fooImpl @ %p\n", fooImpl);
}
Comment #1 by sahmi.soulaimane — 2019-05-22T06:08:15Z
This would require dynamic casting which means druntime must know about cpp rtti.
Comment #2 by robert.schadek — 2024-12-13T19:00:38Z