我有一个我正在尝试使用的非托管 DLL,它使用了一些嵌套结构,并在它们的末尾保留了成员。我在将它们转换为 C# 时遇到问题。
我试图将代码精简到必要的部分。ParentStruct 具有三个不同子结构的四个实例的成员。所有这三个不同的子结构都有 void* 数组来保留内存以供将来使用。
我尝试将保留值作为 IntPtrs,我尝试打开不安全代码并使用 fixed 关键字(并将它们更改为整数)。我已经尝试在结构的末尾实际布置适当数量的连续 IntPtrs。似乎没有任何效果。
在其中一些情况下,我会收到一条错误消息(一条无信息的消息,表示某个线程的某个地址存在错误)。但是,大多数情况下,应用程序会在没有错误消息的情况下死掉。我确定那是因为我在这里搞乱了非托管内存。
仅供参考,实际的 Pinvoke 有一个类似的签名
[DllImport("MyDll.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall)]
internal static extern void UseStructs([In,Out] ref ParentStruct parent);
那么在 C# 中声明这些结构以便我可以使用它们的正确方法是什么?
typedef struct
{
ChildStruct1 childOne;
ChildStruct2 childTwo;
ChildStruct2 childTwoB;
ChildStruct3 childThree;
#if defined K_64_BIT
/// Reserved for future implementation
void* Reserved[15];
#elif defined K_32_BIT
/// Reserved for future implementation
void* Reserved[14];
#endif
} ParentStruct;
typedef struct
{
bool Valid;
float x;
float y;
/// Reserved for future implementation.
void* Reserved[16];
} ChildStruct3;
typedef struct
{
bool Found;
XYPairFloat xyPair;
/// Reserved for future implementation.
void* Reserved[16];
} ChildStruct2;
typedef struct
{
unsigned char* imageData;
RectInt rectInt;
#if defined QUICK_LINK_64_BIT
/// Reserved for future implementation
void* Reserved[14];
#elif defined QUICK_LINK_32_BIT
/// Reserved for future implementation
void* Reserved[12];
#endif
} ChildStruct1;
typedef struct
{
int x;
int y;
int width;
int height;
} RectInt;
typedef struct
{
float x;
float y;
} XYPairFloat;
编辑:我想我已经更接近了,因为我现在收到一条至少是人类可读的错误消息。但它仍然不起作用。我在 Reserved 成员上使用了 fixed 关键字,并在成员上适当地设置了属性的 SizeConst 部分。我所做的其他一切都只是基本的 pinvoke 工作。但是,我收到了错误:
此字段的类型定义具有布局信息,但托管/非托管类型组合无效或不可编组。
关于 ChildStruct1 childOne 成员,这是第一个成员,所以我冒险猜测它也适用于其他成员。想法?
编辑 2:根据 Mark Heath 的要求,这是我用于 ChildStruct1 的实际定义:
[StructLayout(LayoutKind.Sequential)]
internal unsafe struct ChildStruct1
{
[MarshalAs(UnmanagedType.LPStr)]
public string imageData;
public RectInt rectInt;
[MarshalAs(UnmanagedType.LPArray, SizeConst=12)]
public fixed int Reserved[12];
}
编辑3:我做了更多的挖掘。如果我注释掉 Reserved 成员,我得到的那个错误就会消失。显然它不起作用。但我猜,那个特定的错误是由我定义该成员的方式引起的。