2

我有一个我正在尝试使用的非托管 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 成员,我得到的那个错误就会消失。显然它不起作用。但我猜,那个特定的错误是由我定义该成员的方式引起的。

4

1 回答 1

2

IntPtr您可以尝试根据Essential P/Invoke将最后一个值更改为数组

所以改变:

[MarshalAs(UnmanagedType.LPArray, SizeConst=12)]
public fixed int Reserved[12];

到:

[MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)]
public IntPtr[] Reserved;
于 2012-11-27T19:39:21.933 回答