C++のmangleが面倒なのでコンストラクタの引数には未対応。メンバ変数に未対応(そもそもD言語側の実装も対応していない)。
#include <iostream> using namespace std; class D{ public: D(); ~D(); virtual int bar(int i, int j, int k); }; D::D(){ printf("start\n"); } D::~D(){ printf("end\n"); } int D::bar(int i, int j, int k){ cout << "i = " << i << endl; cout << "j = " << j << endl; cout << "k = " << k << endl; return 8; };
import std.metastrings; extern (C++){ interface D{ int bar(int i, int j, int k); } } extern(C){ void* _Znwj(uint); void _ZdlPv(void*); } template cpp_decl(T){ const cpp_decl = "extern(C) extern char* _ZTV"~ToString!(T.stringof.length)~T.stringof~";"; } template cpp_constructor(T, ARGS...){ const cpp_constructor = "extern(C) void _ZN"~ToString!(T.stringof.length)~T.stringof~"C1Ev(void*);";//fixme: mangle and type } template cpp_destructor(T){ const cpp_destructor = "extern(C) void _ZN"~ToString!(T.stringof.length)~T.stringof~"D1Ev(void*);"; } T cpp_new(T, ARGS...)(ARGS args){ const fn="_ZN"~ToString!(T.stringof.length)~T.stringof~"C1Ev";//fixme: mangle void* rv; rv = _Znwj(T.sizeof); static if(is(typeof(mixin(fn)))){ mixin("alias "~fn~" init;"); init(rv, args); }else static if(ARGS.length==0){ *cast(void**)rv = mixin("&_ZTV"~ToString!(T.stringof.length)~T.stringof)+2; }else static assert(0); return cast(D)rv; } void cpp_delete(T)(T obj){ const fn="_ZN"~ToString!(T.stringof.length)~T.stringof~"D1Ev"; static if(is(typeof(mixin(fn)))){ mixin("alias "~fn~" term;"); term(cast(void*)obj); } _ZdlPv(cast(void*)obj); } mixin(cpp_decl!(D)); mixin(cpp_constructor!(D));//コンストラクタが無い場合は削除 mixin(cpp_destructor!(D));//デストラクタが無い場合は削除 void main(){ D d = cpp_new!(D); d.bar(9,10,11); cpp_delete(d); }