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)



Reply via email to