- ベストアンサー
PINVOKEで構造体配列をマーシャルする方法
- C#からPINVOKEを介してCで作成したdll内の関数を呼び出す際、構造体の配列を引数として渡す方法について調査しています。
- 現在試している方法ではうまくいっていないため、問題点を特定することができません。
- 構造体の配列をメンバーに持つ構造体を使用してデータの受け渡しを試みていますが、可能性としてはIntPtrを使用して自分でマーシャリングする必要があるかもしれません。
- みんなの回答 (1)
- 専門家の回答
質問者が選んだベストアンサー
自分でマーシャリングすればできます。 -- 呼び出し側 -- 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]; } } class Program { [DllImport("NativeDll.dll")] private static extern void test3([In, Out] IntPtr data); static void Main(string[] args) { Data[] data = new Data[4]; for (int idx = 0; idx < 4; idx++) { data[idx] = new Data(); } IntPtr result = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Data)) * 4); IntPtr pos = new IntPtr(result.ToInt32()); for (int idx = 0; idx < 4; idx++) { Marshal.StructureToPtr(data[idx], pos, true); pos = IntPtr.Add(pos, Marshal.SizeOf(typeof(Data))); } test3(result); pos = new IntPtr(result.ToInt32()); for (int idx = 0; idx < 4; idx++) { data[idx] = (Data)Marshal.PtrToStructure(pos, typeof(Data)); pos = IntPtr.Add(pos, Marshal.SizeOf(typeof(Data))); } for (int idx = 0; idx < 4; idx++) { System.Console.WriteLine(Encoding.ASCII.GetString(data[idx].data, 0, data[idx].count)); } Marshal.FreeHGlobal(result); } } } -- 呼ばれる側 -- #include <Windows.h> extern "C" { #define MAX_DATA 256 struct Data { int count; char data[MAX_DATA]; }; __declspec(dllexport) void __stdcall test3(Data *data); }; void __stdcall test3(Data *data) { const char *text = "osite !! goo !!"; for (int idx = 0; idx < 4; idx++) { strcpy(data[idx].data, text); data[idx].data[strlen(text)] = '\0'; data[idx].count = strlen(text); } }