D言語でBox2Dを使ってみる。
とりあえずこれで動いたのでメモってみますが、D言語もdllも大して知らないのでつっこみ歓迎です。
連携方針
dllつくる
Box2Dをもとにして。使いたい関数のラッパーを適当に作る。Cのインターフェースなので、extern "C"で囲ってください。
extern "C" { __declspec(dllexport) int func(int a, int b, int c); }
みたいな感じでexportする。
D言語からC++のインスタンスは直接扱えない(ですよね?)ので、常にdll側で操作するようにする。そのために、インスタンスを作ってポインタを返したり、引数にインスタンスへのポインタを引数にとる関数をつくる。たとえばこんなんでしょうか。
extern "C" { __declspec(dllexport) Object *create_instance(); __declspec(dllexport) int set_x(Object *o, int x); __declspec(dllexport) void delete_instance(Object *o); }
そんなこんなでBOX2D.DLLができる。
インポートライブラリつくる
こんな感じのBox2D.defを書く。
LIBRARY "BOX2D.DLL" EXPORTS _func@12 _create_instance@0 _set_x@8 _delete_instance@4
@の後ろの数字は引数のバイト数で、これを間違うとうまくいかないです。
で、このdefからimplibを使ってインポートライブラリBox2D.libを作る。
implib /system Box2D.lib Box2D.def
implibはこの辺からダウンロードできる。
http://www.digitalmars.com/ctg/implib.html
D言語から使う
extern (Windows) { pragma ( lib, "Box2D.lib" ); int func(int a, int b, int c); void* create_instance(); int set_x(void* o, int x); void delete_instance(void *o); }
これでdll側のfuncが使えるようになります。すごいね!
C++側のインスタンスへのポインタがvoid*なのはアレなので、C++側のクラス名をtypedefしておいたほうがいいかも。
補足
defファイルを
LIBRARY "lib\BOX2D.DLL" EXPORTS _func@12 _set_x@8
みたいに書いておけば、DLLをlibディレクトリに突っ込んでおけるので、exeと同じところが散らからずに済む。