Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Interfacing D To Legacy C++ Code

Interfacing D To Legacy C++ Code

C++ programmers have developed a vast investment of existing code. Use of this code from
other languages is normally impractical. Walter shows how
this code can be accessible from the D programming language.

C is the lingua franca of the programming language industry. By presenting a C interface, most languages can connect with one another, and connect to a vast treasure house of C code. But C++ code is very hard to provide an interface too, and almost no languages even attempt it. I'd long ago decided that in order to provide a direct interface from D to C++ would require essentially adding the full semantics of a C++ compiler to D, and that would be impractical. But the idea persistently recurs, as there is a lot of interest in interfacing D to legacy C++ code.

It turns out that we actually can, with minor adjustments to D, directly interface to quite a bit of C++, especially if one is willing to be a bit flexible on both the C++ and D sides. This presentation goes through the principles on how this works, what works and what doesn't work, and how one can retain an investment in C++ code while migrating to D.

Walter Bright is the creator and first implementer of the D programming language and has implemented compilers for several other languages. He's an expert in all areas of compiler technology, including front ends, optimizers, code generation, interpreter engines and runtime libraries. Walter regularly writes articles about compilers and programming, is known for engaging and informative presentations, and provides training in compiler development techniques. Many are surprised to discover that Walter is also the creator of the wargame Empire, which is still popular today over 30 years after its debut.


Northwest C++ Users' Group

January 21, 2015


  1. Interfacing D With C++ by Walter Bright dlang.org

  2. C is the Lingua Franca • Most every language has

    some sort of interface with C • And, of course, the classic being C++ is built on top of C
  3. C Interop extern ( C ) { void* malloc(size_t); void

    free(void*); }
  4. C++ Interop?

  5. • Name mangling • Templates • SFINAE • Namespaces •

    Overloading • Argument Dependent Lookup
  6. Inconceivable! --The Princess Bride

  7. • RTTI • Virtual functions • Exceptions • Special member

    functions • Operator overloading • Const Oh My!
  8. Imposserous! – The Wizard of Oz

  9. You'd have to build a whole C++ front end into

    the language!
  10. Or Maybe Not...

  11. Don't have to compile C++, just have to link to

  12. D doesn't have an analog of everything C++ has, so

    if we can be a bit plastic on both sides...
  13. extern (C++) { uint foo(ref char* p); } Should connect

    to: extern “C++” { unsigned foo(char*& p); }
  14. D C++ char char byte signed char ubyte unsigned char

    short short ushort unsigned short int int uint unsigned long long long ulong unsigned long long
  15. What About extern “C++” void foo(long x); (long doesn't seem

    to have a D analog)
  16. struct __c_long { this(int x) { lng = x; }

    int lng; alias lng this; }
  17. Unsolved Const Problem int ****const*** func(); ?func@@YAPAPAPBQAPAPAPAHXZ const(int ****)*** func();

  18. Struct Layout Matches C++ C++: struct s { unsigned a;

    char c; double d; }; D: struct s { uint a; char c; double d; } Static members too!
  19. Struct Member Functions The same

  20. Polymorphism (virtual functions) • D classes have virtual functions –

    But object layout is different – vtbl[] layout is different
  21. D Supports COM Interfaces import std.c.windows.com; interface IHello : IUnknown

    { extern (Windows) int Print(); } class CHello : ComObject, IHello { HRESULT Print() { MessageBoxA(null, “hello”, null, MB_OK); } }
  22. Or Simply extern (C++) class C { void func() {

    … } }
  23. Multiple Inheritance Not even once! Lord of the Rings

  24. Floor Wax or Dessert Topping? Value or reference type?

  25. C++ Namespaces namespace N { namespace M { void foo();

    } } namespace N { // not closed void bar(); }
  26. D Name Spaces • module • struct • class •

    mixin template
  27. Extend C++ Declaration extern (C++, N.M) { void foo(); }

    extern (C++, N) { void bar(); }
  28. C++ Templates • SFINAE • Partial ordering • Dependent lookup

    • Point of instantiation • Primary template • Template templates
  29. None
  30. Ignore All That It's just a name mangling problem.

  31. C++: template<class X, int C> struct Boo { X v[C];

    }; D: extern (C++) struct Boo(X, int C) { X[C] v; }
  32. Toto Too! C++: template<class T> T func(T t) { return

    t; } func(3); ??$func@H@@YAHH@Z D: extern(C++) T func(T)(T t) { return t; } func(3); ??$func@H@@YAHH@Z Wizard of Oz
  33. Now It's Time to Justify My Existence

  34. Interface to STL! Let's try and hook up to std::vector<T>

  35. std.vector!int p; func(p); calls: void func(std::vector<int, std::allocator<int> > *p);

  36. extern (C++, std) { class vector(T, A = allocator!T) {

    final void push_back(ref const T); } }
  37. extern (C++, std) { struct allocator(T) { alias size_type =

    size_t; void deallocate(T* p, size_type sz) { (cast(__gnu_cxx.new_allocator!T*)&this).deallocate(p, sz); } } } extern (C++, __gnu_cxx) { struct new_allocator(T) { alias size_type = size_t; void deallocator(T*, size_type); } }
  38. Biggest Remaining Problem • Catching C++ exceptions – which are

    by value – D exceptions are by reference
  39. Tl,Dr; • Can get pretty far • Need to be

    flexible on both ends • Interfaces to STL are not portable • and requires non-trivial expertise
  40. • It'll never be 100% • But it's tractable •

    And infinitely better than C wrappers • No longer locked in to existing C++ code