编组指向字符串数组的指针

我在编组指向字符串数组的指针时遇到了一些麻烦。 它看起来像这样无害:

typedef struct { char* listOfStrings[100]; } UnmanagedStruct; 

这实际上是嵌入在另一个结构中,如下所示:

 typedef struct { UnmanagedStruct umgdStruct; } Outerstruct; 

非托管代码回调到托管代码,并将Outerstruct作为IntPtr返回,并分配内存并填入值。

管理世界:

 [StructLayout(LayoutKind.Sequential)] public struct UnmanagedStruct { [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStr, SizeConst=100)] public string[] listOfStrings; } [StructLayout(LayoutKind.Sequential)] public struct Outerstruct { public UnmanagedStruct ums; } public void CallbackFromUnmanagedLayer(IntPtr outerStruct) { Outerstruct os = Marshal.PtrToStructure(outerStruct, typeof(Outerstruct)); // The above line FAILS! it throws an exception complaining it cannot marshal listOfStrings field in the inner struct and that its managed representation is incorrect! } 

如果我将listOfStrings更改为IntPtr,那么Marshal.PtrToStructure可以工作,但现在我无法撕掉listOfStrings并逐个提取字符串。

编组除了非常基本的字符串之外的任何东西都是复杂的,并且充满了难以发现的边案例。 通常最好在结构定义中使用安全/简单路由,并添加一些包装器属性以稍微整理一下。

在这种情况下,我将使用IntPtr数组,然后添加一个包装器属性,将它们转换为字符串

 [StructLayout(LayoutKind.Sequential)] public struct UnmanagedStruct { [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStr, SizeConst=100)] public IntPtr[] listOfStrings; public IEnumerable Strings { get { return listOfStrings.Select(x =>Marshal.PtrToStringAnsi(x)); } } 

好的..我似乎已经开始工作了。 它应该被编组为IntPtr []

这似乎有效:

 [StructLayout(LayoutKind.Sequential)] public struct UnmanagedStruct { [MarshalAs(UnmanagedType.ByValArray, SizeConst=100)] public IntPtr[] listOfStrings; } for (int i = 0; i < 100; ++i) { if (listOfstrings[i] != IntPtr.Zero) Console.WriteLine(Marshal.PtrToStringAnsi(listOfStrings[i])); }