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

Interfacing D To Legacy C++ Code

Embed Size (px)

Citation preview

Page 1: Interfacing D To Legacy C++ Code

Interfacing D WithC++

by Walter Bright

dlang.org

Page 2: Interfacing D To Legacy C++ Code

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

Page 3: Interfacing D To Legacy C++ Code

C Interop

extern ( C ) { void* malloc(size_t); void free(void*);}

Page 4: Interfacing D To Legacy C++ Code

C++ Interop?

Page 5: Interfacing D To Legacy C++ Code

● Name mangling● Templates● SFINAE● Namespaces● Overloading● Argument Dependent Lookup

Page 6: Interfacing D To Legacy C++ Code

Inconceivable!

--The Princess Bride

Page 7: Interfacing D To Legacy C++ Code

● RTTI● Virtual functions● Exceptions● Special member functions● Operator overloading● Const

Oh My!

Page 8: Interfacing D To Legacy C++ Code

Imposserous!

– The Wizard of Oz

Page 9: Interfacing D To Legacy C++ Code

You'd have to build a whole C++ front end into the language!

Page 10: Interfacing D To Legacy C++ Code

Or Maybe Not...

Page 11: Interfacing D To Legacy C++ Code

Don't have to compile C++,just have to link to it

Page 12: Interfacing D To Legacy C++ Code

D doesn't have an analog of everythingC++ has, so if we can be a bit plastic on

both sides...

Page 13: Interfacing D To Legacy C++ Code

extern (C++){ uint foo(ref char* p);}

Should connect to:

extern “C++”{ unsigned foo(char*& p);}

Page 14: Interfacing D To Legacy C++ Code

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

Page 15: Interfacing D To Legacy C++ Code

What About

extern “C++” void foo(long x);

(long doesn't seem to have a D analog)

Page 16: Interfacing D To Legacy C++ Code

struct __c_long { this(int x) { lng = x; } int lng; alias lng this;}

Page 17: Interfacing D To Legacy C++ Code

Unsolved Const Problem

int ****const*** func();

?func@@YAPAPAPBQAPAPAPAHXZ

const(int ****)*** func();

?func@@YAPAPAPBQBQBQBHXZ

Page 18: Interfacing D To Legacy C++ Code

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!

Page 19: Interfacing D To Legacy C++ Code

Struct Member Functions

The same

Page 20: Interfacing D To Legacy C++ Code

Polymorphism (virtual functions)

● D classes have virtual functions– But object layout is different

– vtbl[] layout is different

Page 21: Interfacing D To Legacy C++ Code

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); }}

Page 22: Interfacing D To Legacy C++ Code

Or Simply

extern (C++) class C { void func() { … }}

Page 23: Interfacing D To Legacy C++ Code

Multiple Inheritance

Not even once!

Lord of the Rings

Page 24: Interfacing D To Legacy C++ Code

Floor Wax or Dessert Topping?

Value or reference type?

Page 25: Interfacing D To Legacy C++ Code

C++ Namespaces

namespace N { namespace M { void foo(); }}

namespace N { // not closed void bar();}

Page 26: Interfacing D To Legacy C++ Code

D Name Spaces

● module● struct● class● mixin template

Page 27: Interfacing D To Legacy C++ Code

Extend C++ Declaration

extern (C++, N.M) { void foo();}

extern (C++, N) { void bar();}

Page 28: Interfacing D To Legacy C++ Code

C++ Templates

● SFINAE● Partial ordering● Dependent lookup● Point of instantiation● Primary template● Template templates

Page 29: Interfacing D To Legacy C++ Code
Page 30: Interfacing D To Legacy C++ Code

Ignore All That

It's just a name mangling problem.

Page 31: Interfacing D To Legacy C++ Code

C++:

template<class X, int C>struct Boo { X v[C];};

D:

extern (C++)struct Boo(X, int C) { X[C] v;}

Page 32: Interfacing D To Legacy C++ Code

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

Page 33: Interfacing D To Legacy C++ Code

Now It's Time to Justify My Existence

Page 34: Interfacing D To Legacy C++ Code

Interface to STL!

Let's try and hook up to

std::vector<T>

Page 35: Interfacing D To Legacy C++ Code

std.vector!int p;func(p);

calls:

void func(std::vector<int, std::allocator<int> > *p);

Page 36: Interfacing D To Legacy C++ Code

extern (C++, std) { class vector(T, A = allocator!T) { final void push_back(ref const T); }}

Page 37: Interfacing D To Legacy C++ Code

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); }}

Page 38: Interfacing D To Legacy C++ Code

Biggest Remaining Problem

● Catching C++ exceptions– which are by value

– D exceptions are by reference

Page 39: Interfacing D To Legacy C++ Code

Tl,Dr;

● Can get pretty far● Need to be flexible on both ends● Interfaces to STL are not portable● and requires non-trivial expertise

Page 40: Interfacing D To Legacy C++ Code

● It'll never be 100%● But it's tractable● And infinitely better than C wrappers● No longer locked in to existing C++ code