前回の記事ですが、内容が多すぎて結構雑かなーと思いました。
補足説明をいれておきます。m(__)m
long型のサイズの違い
C言語、C++ではlong型のサイズは実装系依存で、つまり実行する環境によって変わりますが、Visual Studioでx64アプリケーション(LPP64)をビルドした場合、long型は4バイトとなります。(LinuxやmacOSなどのLP64環境では8バイトのようです。)
一方、C#のlong型は8バイトとして定義されています。
参考:整数型の一覧表 (C# リファレンス) | Microsoft Docs
名前が同じだからといってC++のlongをC#側でlongで受けてしまうと、例えば配列の前半部分に予期しない大きな値が入り、後半部分に0で埋まった値が入っているなどの予期せぬ動作が起こったりします。
C++でlong型で定義した関数は、C#側はint型(Int32型)で受けましょう。
C#側で文字列をstringとして使いたいとき
C++のconst char*型を、C#側でいくつかの方法でマーシャリングすることが出来ます。
参考:文字列に対する既定のマーシャリング | Microsoft Docs
参考:既定のマーシャリングの動作 | Microsoft Docs
C#側でstringとしてマーシャリングした場合は、stringのデコンストラクターが呼ばれるタイミングでメモリが解放されます。
前回malloc()でメモリ確保すると書きましたが、これだと本当にメモリリークが起きないのかが心配です。特にデバッグビルドで作成したdllを読み込ませた場合、_DEBUGが定義されているため、mallocが_malloc_dbgに書き換えられてしまうため、C#側で正しく解放できずUnityが落ちてしまうようです。
CoTaskMemAlloc()関数で確保するのが良いのでしょうか?
static const char* MallocString(const char* str) {
size_t n = strlen(str);
char* s = (char*)CoTaskMemAlloc(n+1);
memcpy(s, str, n + 1);
return s;
}
このようにした方が良いかもしれません。
VisualStudioでデバッグしたい
Visual StudioでUnity.exeのプロセスにアタッチすると、 VSのデバッガを使ってデバッグを行えます。ブレークポイントを貼れたりなど便利です。
dllでも同様にデバッグがしたいです。出来ればデバッグビルドでビルドしたdllを使いたいですが、 デフォルト設定のDebugビルドで作成したdllを読ませるとUnityが落ちてしまいます。
DLLのプロジェクトのプロパティで
C/C++ > コード生成 > ランタイムライブラリでデバッグのdllを使っていると落ちるようです。