How does inheritance and vtables work wrt. C++ and interop with D? Fns w/ Multiple-inheritance args impossible to bind to?
evilrat
evilrat666 at gmail.com
Tue May 25 06:02:55 UTC 2021
On Tuesday, 25 May 2021 at 02:47:19 UTC, Gavin Ray wrote:
>
> Unfortunately, it does not work if I try to add `final int
> getSomething()` or the other one to the D interfaces, it throws
> a symbol error because the mangled names are slightly different:
>
> ```sh
>
> unresolved external symbol "public: int __cdecl
> Base1::getSomething(void)"
> (?getSomething at Base1@@QEAAHXZ)
> 0000000000000000 T ?getSomething at Base1@@QEAA?BHXZ # < "nm"
> output
> ```
>
> If I use `nm` and list the symbols, and then try to manually
> use the mangling scheme, it almost works but because the return
> types differ it won't compile =/
> ```d
> extern class Derived : Base1, Base2
> {
> int someInt;
>
> pragma(mangle, "?getOtherThing at Base2@@QEAA?BHXZ")
> int getOtherThing();
> }
> ```
>
> ```sh
> main.d(29): Error: Function type does not match previously
> declared function with the same mangled name:
> `?getOtherThing at Base2@@QEAA?BHXZ`
> main.d(29): Previous IR type: i32 (%main.Base2*)
> main.d(29): New IR type: i32 (%main.Derived*)
> ```
That's just LDC thing, should work with DMD.
Are you sure `getOtherThing` marked final? Because in your C++
class it is not virtual and in your example it is not final as
well.
In C++ having multiple bases with final method means that both
Base1 and Base2 have their own instances of that method.
Anyway in order to call it you'll have to cast manually to target
base.
i.e. if you want to call `Base1::getOtherThing` and you have
`Derived` you'll have to cast to `Base1`.
```d
Derived d;
// d.getOtherThing(); // likely won't link
(cast(Base1)d) .getOtherThing(); // will call Base1 variant
(cast(Base2)d) .getOtherThing(); // will call Base2 variant
```
It is also possible that you'll have to put them in using mixin
template so it will create scope for them that doesn't collide
with each other, though I think it's more of a hack than a
feature.
Something like
```d
class Derived
{
mixin base1; // has final getOtherThing
mixin base2; // has final getOtherThing
}
```
then you can call it almost like in C++
```d
d.base1.getOtherThing();
d.base2.getOtherThing();
```
Anyway all this stuff requires thorough research & testing as
such ABI tinkering is very easy to mess up and very hard to
debug, for example if you mess up the order(functions layout) it
can land on another final method call that seemingly work but in
debugger you'll see that you can't hit breakpoint in that method.
Happy debugging time!
More information about the Digitalmars-d-learn
mailing list