PInvoke – Marshal一个来自指针的结构数组

我试图在这个问题上回答这个问题

我的结构在C中看起来像这样

typedef struct drive_info_t { unsigned char drive_alias[32]; } drive_info_t; 

我的function在C中看起来像这样

 unsigned int get_drive_info_list(drive_info_t **list, unsigned int *item_count) { //fill list in native C //print out in native C printf("list.alias - %s\r\n",list[i]->drive_alias); } 

我的C#struct看起来像这样

 [StructLayout(LayoutKind.Sequential)] public struct drive_info_t { [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] public byte[] drive_alias; } 

我的C#函数声明如下所示

 [DllImport("mydll.dll", EntryPoint = "get_drive_info_list", CallingConvention = CallingConvention.Cdecl)] public static extern uint GetDriveInfoList(out System.IntPtr ptr_list_info, out System.IntPtr ptr_count); 

我正在这样调用C#函数

 IntPtr ptr_list_info = IntPtr.Zero; IntPtr ptr_cnt = IntPtr.Zero; ret = api.GetDriveInfoList(out ptr_list_info, out ptr_cnt); 

我正在整理这样的返回指针

 nAlloc = ptr_cnt.ToInt32(); int szStruct = Marshal.SizeOf(typeof(api.drive_info_t)); api.drive_info_t[] localStructs = new api.drive_info_t[nAlloc]; for (int i = 0; i < nAlloc; i++) { localStructs[i] = (api.drive_info_t)Marshal.PtrToStructure(ptr_list_info, typeof(api.drive_info_t)); ptr_list_info = new IntPtr(ptr_list_info.ToInt32() + (szStruct)); } 

像这样打印结构别名

 for (uint i = 0; i < localStructs.Length; i++) { Console.WriteLine("list.alias - {0}", System.Text.Encoding.Default.GetString(localStructs[i].drive_alias)); } 

谢谢你和我在一起..

这是我的输出在C#中的控制台应用程序上的样子。 你可以看到本机C dll打印到控制台它的值,但我的编组在某处弄乱了:

 ======================== C values ============================ list.alias - drv1 list.alias - drv2 list.alias - drv3 list.alias - drv4 ======================== C# values ============================ list.alias - drv1 list.alias - o£Q95drv2 list.alias - o£Q95drv3 list.alias - o£Q95drv4 

我不知道这个垃圾文本和偏移来自何处。

我负责.Net方面,如果需要,其他团队成员可以根据需要更改本机C,但本机C更改需要是跨平台的OSX / Windows / Linux。

提前致谢。

这是为什么参数类型没有定义接口的完美示例。 考虑

 drive_info_t **list 

这可能是指向结构数组的指针。 在这种情况下,可能是被调用者分配了数组。 这就是为什么使用指向数组的指针而不是数组的原因。

或者它可以是一个指向struct的指针数组。 这里数组将由调用者分配,结构可以由被调用者或调用者分配。 没办法告诉我们。

我们可以看出你的接口接受了一个指向struct的指针数组。 看看这段代码:

 list[i]->drive_alias 

很明显list是一个指向struct的指针数组。

这告诉您代码错误。 您使用了错误的模板,因为您错误地识别了语义。 下一步是返回接口的文档和调用代码的任何示例,以准确了解语义是什么。 谁分配和解除分配什么。

几乎可以肯定你会使用IntPtr[]来编组arrays,但除此之外我们不可能说出会发生什么。 我猜测调用者会分配结构但不依赖于猜测。 阅读文档和示例调用代码。

除此之外,第二个参数应该是ref uint或者可能out uint取决于函数的语义。 再一次,这是我们无法解决的问题。