0

pinvoke 呼び出しの場合、次のように相当する構造体を作成する必要があります。

typedef struct _Somenativestruct {
 PCWSTR filename;
 DWORD count;
 DWORD anothercount;
 AnEnumWithByteSize info;
 union {
     Structwithoneintfield Progress;
     Anotherstructwithoneintfield Result;
 };
} Somenativestruct , *PSomenativestruct ;

構造体に 1 つの共用体があるため、layout.explicit にする必要がありますが、問題は PCWSTR であるファイル名に対して行うオフセットです。32 ビットのポインターなので、オフセットを 4 にできますか? では、以下は正しいでしょうか?

[StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode)]
    public struct Mynet40struct
    {
        [FieldOffset(0)]
        private [MarshalAs(UnmanagedType.LPWStr)] string filename;
        [FieldOffset(4)]
        private int count;
        [FieldOffset(8)]
        private int anothercount;
        [FieldOffset(12)]
        AnEnumWithByteSize info;
        [FieldOffset(13)]
        StructWithOneIntField progress;
        [FieldOffset(13)]
        AnotherStructWithOneIntField result;
    } 
4

2 に答える 2

2

64 ビットでは 8 バイトの場合があります。

ユニオン専用の明示的な構造体を作成し、それを LayoutKind.Sequential のままの Mynet40struct のメンバーとして追加します。

于 2013-05-09T02:10:48.060 に答える
2

ここには、検討する価値のある問題がいくつかあります。

まず、パックされたレイアウトを想定しています。おそらく、ネイティブ構造体は実際にはパックされていますが、それは珍しいことです。構造体が整列されるのは正常です。ネイティブ宣言に#pragma packディレクティブが含まれていない限り、構造体は整列されます。

次に、ポインターは 32 ビットと 64 ビットのターゲットではサイズが異なるため、明示的な使用は 1 つのターゲットに対してのみ機能します。これに対処する方法は、ユニオンのみに明示的なレイアウトを使用することです。これがユニオンを処理する最良の方法です。

[StructLayout(LayoutKind.Explicit)]
public struct Mynet40union
{
    [FieldOffset(0)]
    StructWithOneIntField progress;
    [FieldOffset(0)]
    AnotherStructWithOneIntField result;
}

そして、この共用体を構造体で使用します。

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct Mynet40struct
{
    string filename;
    int count;
    int anothercount;
    AnEnumWithByteSize info;
    Mynet40union progressOrResult;
} 

構造体が実際にパックされている場合は、属性のPackパラメーターを使用してそれを指定します。StructLayout

于 2013-05-10T11:22:30.393 に答える