謎's キッチン

謎のひとりごと。Amazon欲しい物リストはこちら: https://www.amazon.co.jp/hz/wishlist/ls/CCPOV7C6JTD2

D言語とC++のブリッジでgetDを消してみた。

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