C# から C dll に構造体の配列を渡したい。
C での構造体定義:
typedef struct{
BYTE name[32];
DWORD age;
}DATA;
次のように構造体をマーシャリングしました。
[StructLayout(LayoutKind.Sequential)]
public struct DATA
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
public byte[] name;
public int age;
}
私が伝えたいC関数定義:
void test_data(DATA * pStruct, DWORD length){
_tprintf("test start\n");
if (!pData)
{
_tprintf("pData is NULL\n");
}
unsigned int i,j;
for(i = 0; i < length; i++){
_tprintf("name: ");
for(j = 0; j < 32; j++){
_tprintf("%x ",pData[i].name[j]);
}
_tprintf("\n");
_tprintf("age: %d",pData[i].age);
_tprintf("\n");
}
_tprintf("test finish\n");
}
C# の関数シグネチャ:
[DllImport("a.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void test_data(ref DATA pData, int length);
C# でのセットアップ:
int length = 10;
DATA[] arr = new DATA[length];
for(int i = 0; i < length; i++){
arr[i].name = new byte[32];
arr[i].age = 10;
}
test_data(ref arr[0], length);
しかし、私はこれらの出力を得ました:
test start
name: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
age: 10
name: 7c 67 9a 2 a 0 0 0 1 0 0 0 2 0 0 0 eb 9 77 67 a4 eb 8f 0 0 0 0 0 2 0 0 0
age: 43673448
test finish
最初のものは正しいですが、2番目のものは奇妙に思えます。参照の渡し方やセットアップの仕方に問題があると思います。
ここでSCardTransmit 関数の pinvoke Web から着想を得ました。ここでは、C# のバイト配列を Cbyte *
のref rapdu[0]
これを正しく行う方法は?
これは、構造体の配列をマネージド コードからネイティブ コードにマーシャリングする方法ではありません。
P/Invoke 宣言で:
[DllImport("a.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void test_data(ref DATA pData, int length);
ref DATA pData
単一のDATA
オブジェクトへのポインターにマーシャリングします。残りの配列が一緒に送信されるという保証はありません。構造体がblittableである場合は機能していた可能性があります。その場合、マーシャリングは単に配列を固定し、そのアドレスをそのまま C 関数に渡す必要があるためです。しかし、残念なことに、構造体には参照型である配列が含まれています。これを C 関数に渡すと、マーシャラーはコピーを実行して、正しいレイアウトの構造体を取得する必要があります。したがって、 を渡すと、コピーが 1 つだけ送信され、C コードがバッファの最後からすぐに移動し、未定義の動作に遭遇します。また、より哲学的なレベルでは、配列であると想定されていることもあまり明確ではありません。ref arr[0]
pData
代わりに、バッチ全体を送信するには、ドキュメントで説明されているように、引数を配列として宣言するだけで、マーシャラーが残りを行います。
[DllImport("a.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void test_data(DATA[] pData, int length);
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加