So one of the problems with generating D code for bindings to C++
is that there's no true/direct multiple inheritance.
If anyone happens to understand well how vtables work and the way
the compiler treats these things, is there a way to hackily make
semantically-equivalent objects?
An example:
```cpp
class Kickable {
void nonVirtual() { /* impl */ }
virtual void kick();
}
class Throwable {
virtual void throw();
}
class KickableThrowable : Kickable, Throwable {}
// KickableThrowable or KickableThrowable*, not really sure which
is more realistic
void takesKickableThrowable(KickableThrowable* thing) {}
```
Would making a class/struct that has the methods `nonVirtual()`,
`kick()`, and `throw()` be usable as an argument to
`takesKickableThrowable()`, since it would contain identical
members/layout?
```d
extern (C++)
class KickableThrowable {
void nonVirtual();
/* override */ void kick() {}
/* override */ void kick() {}
}
extern (C++)
void takesKickableThrowable(KickableThrowable thing);
takesKickableThrowable(new KickableThrowable());
```
adr had shown me a way to mimic multiple inheritance using
interfaces and mixin templates, would this be a viable approach?
- See: https://run.dlang.io/is/3rJyMt
```d
interface Abstract1 {
/* virtual */ void overrideMe1();
void sayHello();
mixin template Abstract1Impl() {
void sayHello() { import std.stdio; writeln("Hello"); }
}
}
interface Abstract2 {
/* virtual */ void overrideMe2();
void sayGoodbye();
mixin template Abstract2Impl() {
void sayGoodbye() { import std.stdio; writeln("Goodbye");
}
}
}
class MyClass : Abstract1, Abstract2 {
mixin Abstract1Impl;
mixin Abstract2Impl;
override void overrideMe1() { writeln("overrode 1"); }
override void overrideMe2() { writeln("overrode 2"); }
}
```
---
Also, what is the best way to debug and learn about vtables and
their impact on interopability in D?
Visual Studio has the "Struct Layout" extension (pictured below),
and `clang` and `cl.exe` have options to dump vtable/record
layouts:
```
$ cl.exe test.cpp /d1reportSingleClassLayoutMEOW
class BatMEOW size(40):
+---
0 | +--- (base class Mammal)
0 | &Mammal::Breathe
BatMEOW::$vftable@WingedAnimal@:
| -16
0 | &WingedAnimal::Flap
<SNIPPED>
BatMEOW::{dtor} this adjustor: 32
BatMEOW::__delDtor this adjustor: 32
BatMEOW::__vecDelDtor this adjustor: 32
vbi: class offset o.vbptr o.vbte fVtorDisp
Animal 32 8 4 0
```
```
$ clang -cc1 -fdump-vtable-layouts -emit-llvm test.cpp
VFTable for 'Animal' (3 entries).
0 | Animal RTTI
1 | Animal::~Animal() [scalar deleting]
2 | void Animal::Eat()
<SNIPPED>
```
```
$ clang -cc1 -fdump-record-layouts -emit-llvm test.cpp
*** Dumping AST Record Layout
0 | struct Animal
0 | (Animal vftable pointer)
| [sizeof=8, align=8,
| nvsize=8, nvalign=8]
*** Dumping AST Record Layout
0 | struct Mammal
0 | (Mammal vftable pointer)
8 | (Mammal vbtable pointer)
16 | struct Animal (virtual base)
16 | (Animal vftable pointer)
| [sizeof=24, align=8,
| nvsize=16, nvalign=8]
<SNIPPED>
```
![vtable inspector cpp](https://i.imgur.com/Xqw6jKG.gif)