C#からアンマネージC ++関数を取得する
質問
信頼できるANSI標準Cコードがいくつかあります。つまり、ソースは持っていますが、別の言語に翻訳したり、呼び出し引数を変更したりすることはできません。これらのアクションは権限を無効にするためです。 150以上の関数があります。
Visual Studio 2009のC ++コンパイラを使用してコンパイルできるように、ファイル名を.Cから.CPPに変更するなど、偶発的な変更を加えることができます。コンパイラ指令なども追加できます。必要に応じて、ラッパーレイヤーを通過することもできます。
もう1つの制限は、私の会社がC#コードで unsafe キーワードを使用することをしないことです。
C#プログラムからこれらの関数を取得する必要があります。
典型的なC / C ++関数は次のようになります。
double SomeFunction(double a、double [3] vec、double [3] [3] mat);
配列の内容が入力されることもあれば、出力されることもあります。まれに両方が含まれることもあります。
最初に、アンマネージDLLを作成しようとしました(Extern Cとマークされた関数を使用)。単純な引数(int、double)のみを持つ関数は正常に機能しましたが、配列をマーシャリングする方法を判断できませんでした。 (実際、サンプルコードをいくつか見つけましたが、150回複製するのは非常に複雑で不合理でした。)
次に、同じソリューション内で、C ++とC#の2つのプロジェクトを試しました。 C ++プロジェクトでは、アンマネージとしてマークされた元の関数を呼び出したマネージ関数を作成しました。これは非常に簡潔でシンプルで、繰り返しますが、シンプルな引数は問題なく機能しました。しかし、配列の場合、C#からC ++の境界を越えて引数の型を一致させる方法が見つかりませんでした。
引数 '2': 'double []'から 'double *'に変換できません
(そして上記のように、安全ではないポインタを使用することはできません。)
確かに、私がやろうとしていることは可能でなければなりません。
これらの機能を取得する最良の方法は何ですか?
(上記の関数を使用したサンプルコードは本当にクールです。)
解決
サンプルC / C ++実装:
extern "C" __declspec(dllexport)
double SomeFunction(double a, double vec[3], double mat[3][3]) {
double sum = a;
for (int ix = 0; ix < 3; ++ix) {
sum += vec[ix];
for (int iy = 0; iy < 3; ++iy) {
sum += mat[ix][iy];
}
}
return sum;
}
サンプルC#の使用法:
private void Form1_Load(object sender, EventArgs e) {
double[] vec = new double[3];
double[,] mat = new double[3, 3];
for (int ix = 0; ix < 3; ++ix) {
vec[ix] = ix;
for (int iy = 0; iy < 3; ++iy) {
mat[ix, iy] = (ix + 1) * iy;
}
}
double sum = SomeFunction(1, vec, mat);
}
[System.Runtime.InteropServices.DllImport("cpptemp8.dll")]
private static extern double SomeFunction(double a, double[] vec, double[,] mat);
他のヒント
externおよびP / Invokeソリューションが機能しない場合は、おそらくラッパーが最善の策です。マネージコードとアンマネージコードの両方を使用するマネージC ++ DLLを作成します。 C DLLの関数の単なるラッパーである.NETクラスをこのDLLに追加します。 C#コードはC ++ .NETクラスを呼び出すことができ、C関数を次に転送します。
この方法により、ランタイムに依存せずに、.NETとアンマネージコード間の変換を自分で記述できます。
swigを使用すると、ピンボークが生成されます