記録のために、私はこれを機能させるためのほとんどの方法を取得し、適切な C ファイルを C++ プロジェクトにプルすることになりました (コードの互換性の問題と戦っていたため、必要でさえありませんでした)。
この質問に直面している人々に役立つかもしれない途中で私が拾ったいくつかのヒントを次に示します。
配列のマーシャリング
double*
C では、double へのポインター ( ) と double の配列( )の間に違いはありませんdouble*
。相互運用するときは、あいまいさを解消できる必要があります。の配列を渡す必要がdouble
あったため、署名は次のようになります。
[DllImport(@"PathToDll")]
public static extern Foo(
[MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)[In] double[] x,
[MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)[Out] double[] y,
int x_size,
int y_size)
C では、配列の長さに関する追加情報が必要であり、別のパラメーターとして渡す必要があります。マーシャリングは、このサイズがどこにあるかを知る必要もあるため、SizeParamIndex
パラメーターのリスト内のサイズ パラメーターのゼロから始まるインデックスを示す を指定します。
また、配列を渡す方向も指定します。この例x
では、 に渡され Foo
、「送り返されます」y
。
呼び出し規約
これが意味することの詳細を実際に理解する必要はありません (つまり、私は理解していません)。異なる呼び出し規則が存在し、それらが両側で一致する必要があることを知っておく必要があります。C# のデフォルトはStdCall
、C のデフォルトは ですCdecl
。これは、使用している側のデフォルトと異なる場合にのみ、呼び出し規約を明示的に指定する必要があることを意味します。
これは、コールバックの場合は特に厄介です。C
fromにコールバックを渡す場合C#
、そのコールバックを で呼び出すことを意図していますがStdCall
、渡すときは を使用していますCdecl
。これにより、次の署名が生成されます (コンテキストについては、この質問を参照してください)。
//=======C-code======
//type signature of callback function
typedef int (__stdcall *FuncCallBack)(int, int);
void SetWrappedCallback(FuncCallBack); //here default = __cdecl
//======C# code======
public delegate int FuncCallBack(int a, int b); // here default = StdCall
[DllImport(@"PathToDll", CallingConvention = CallingConvention.Cdecl)]
private static extern void SetWrappedCallback(FuncCallBack func);
コールバックのパッケージ化
明らかですが、すぐにはわかりませんでした:
int MyFunc(int a, int b)
{
return a * b;
}
//...
FuncCallBack ptr = new FuncCallBack(MyFunc);
SetWrappedCallback(ptr);
.def ファイル
C++ プロジェクトから公開する (DllImport
編集する) 関数はすべて、ModDef.def
ファイル内で把握する必要があります。その内容は次のようになります。
LIBRARY MyLibName
EXPORTS
SetWrappedCallback @1
外部「C」
C++ から C 関数を使用する場合は、それらを として宣言する必要がありますextern "C"
。C 関数のヘッダー ファイルをインクルードする場合は、次のようにします。
extern "C" {
#include "C_declarations.h"
}
プリコンパイル済みヘッダー
コンパイル エラーを回避するために私がしなければならなかったもう 1 つのことは、「C」ファイルごとにプリコンパイル済みヘッダーを使用しないようRight-click -> Properties -> C/C++ -> Precompiled Headers
に設定することでした。Precompiled header