osiete03 の回答履歴
- PINVOKEで構造体配列をマーシャルする方法
Cで作ったdll内の関数を.NET(C#)のプログラムからPINVOKEを介して呼び出そうとしているのですが、構造体の配列を引数として渡すにはどうするべきかわかりません。データの流れる向きは、両方向 [In, Out] です。下記の方法を試してうまくいかないのですが、どこが悪いのでしょうか?下記サンプルはうまくいかないのですが、構造体の配列をメンバーに持った構造体を使ってデータを受け渡そうとしています。もしかして、IntPtrを使って自分でマーシャリングしないとできませんか? 助言いただきたく、おねがいいたします。 -- 呼び出し側 -- using System; using System.Runtime.InteropServices; using System.Text; namespace MarshalTest { [StructLayout(LayoutKind.Sequential)] class Data { private const int buffersize = 256; [MarshalAs(UnmanagedType.I4)] public int count; [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = buffersize)] public Byte[] data; public Data() { count = 0; data = new Byte[buffersize]; } } [StructLayout(LayoutKind.Sequential)] class DataBundle { private const int buffersize = 8; [MarshalAs(UnmanagedType.I4)] public int count; [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.LPStruct, SizeConst = buffersize)] public Data[] data; public DataBundle() { count = 0; data = new Data[buffersize]; for (int idx = 0; idx < buffersize; idx++) { data[idx] = new Data(); } } } class Program { [DllImport("NativeDll.dll")] private static extern void test1([Out] Data data); [DllImport("NativeDll.dll")] private static extern void test2([Out] DataBundle data); static void Main(string[] args) { #if false // これはできます。 Data data = new Data(); test1(data); System.Console.WriteLine(Encoding.ASCII.GetString(data.data, 0, data.count)); #else // これができません。 DataBundle data = new DataBundle(); test2(data); for (int idx = 0; idx < data.count; idx++) { System.Console.WriteLine(Encoding.ASCII.GetString(data.data[idx].data, 0, data.data[idx].count)); } #endif } } } -- 呼ばれ側 -- #include <Windows.h> extern "C" { #define MAX_DATA 256 #define MAX_BUNDLE 8 struct Data { int count; char data[MAX_DATA]; }; struct DataBundle { int count; Data data[MAX_BUNDLE]; }; __declspec(dllexport) void __stdcall test1(Data *data); __declspec(dllexport) void __stdcall test2(DataBundle *data); }; void __stdcall test1(Data *data) { const char *text = "osite !! goo !!"; data->count = strlen(text); strcpy(data->data, text); data->data[strlen(text)] = '\0'; } void __stdcall test2(DataBundle *data) { const char *text = "osite !! goo !!"; for (int idx = 0; idx < MAX_BUNDLE; idx++) { strcpy(data->data[idx].data, text); data->data[idx].data[strlen(text)] = '\0'; } } 以上です。