C++とC#
対象
- 衝動的にC++(native)を動かしたい人
- dryな関係で居たい人
- 再配布パッケージをインストールしたくない人
結論
以下のような構成をとることが多い。
説明
C++プロジェクトについて
.NET 互換CLIライブラリをC++側で書くのが一番の近道。
しかし、CLIライブラリは/MD(動的リンク:マルチスレッド)のみ、/MT(静的リンク:マルチスレッド)には対応していない。[要出典]
動的リンクとしたとき、再配布パッケージは必須となってしまう。[要出典]
再配布パッケージを使用しないようにするためには、/MDを指定しなくてはならない。
Visual Studio 2015 (v140)からは再配布パッケージに使用されるvcruntime.dllの依存関係が多くなってしまったこと(マージモジュールになったから?)により、再配布をするにはパッケージが必要になってしまったように見受けられる。
以前はmsvcr120.dll単体+αで事足りていた。(Windows 7をターゲットとする場合)
Visual Studio | Platform Toolset | DLL | .NET |
---|---|---|---|
2015 | v140 | vcruntime.dll | 4.5.2/4.6 |
2013 | v120 | msvcr120.dll | 4.5.1 |
2012 | v110 | msvcr110.dll | 4.5 |
コールバックをC++側に渡すときの注意点
以下のようなコードがあったとする。
var cls = CPlusPlusMethod_Factory();
CPlusPlusMethod(cls, new Action(()=>DoSomething()));
Actionがメソッドを抜ける前に実行され、参照されなくなるなら、問題はないが、
たいていはコールバックとして関数を登録しているケースが多い。
マネージドコードからアンマネージドコードへコールバックを渡すだけでは、
参照が増えず、即座にGCされてしまい、不正アクセスの例外が発生する。
そのため、以下のようにC++側のコードが生きている間は、コールバックを参照として保持すべき。
var avoidgc = new List<Delegate>(); var cls = CPlusPlusMethod_Factory(); var action = new Action(()=>DoSomething()); avoidgc.Add(action); CPlusPlusMethod(cls, action);
※上記記述はrubyの何かの記事のパクリです。出典を探し出せなくて困っているので、後日見つけたらリンクします