2

私が使用しようとしているアンマネージ DLL があります。これは、それらの最後に予約されたメンバーを持ついくつかのネストされた構造体を利用します。それらを C# に変換する際に問題が発生しています。

コードを本質的なものに落とし込もうとしました。ParentStruct には、3 つの異なる子構造体の 4 つのインスタンスのメンバーがあります。これら 3 つの異なる子構造体はすべて、将来の使用のためにメモリを予約するための void* 配列を持っています。

予約済みの値を IntPtrs として実行しようとしましたが、安全でないコードを有効にして、fixed キーワードを使用してみました (そしてそれらを int に変更しました)。構造体の最後に適切な数の連続する 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

Essential P/InvokeIntPtrに従って、最後の値を配列に変更してみることができます

だから変更:

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

に:

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