使用LPWSTR和Structs进行显式布局的结构

时间:2013-05-09 00:08:44

标签: c# .net struct pinvoke

对于一个pinvoke调用,我需要创建一个等效的结构,如下所示:

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

因为它在结构中有一个联合,我必须使它布局.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;
    } 

2 个答案:

答案 0 :(得分:2)

64位可能是8个字节。

为联合创建一个显式结构,并将其添加为Mynet40struct的成员,该成员保留LayoutKind.Sequential。

答案 1 :(得分:2)

这里有一些值得考虑的问题。

首先,您假设了一个打包布局。也许本机结构真的很紧凑,但这很不寻常。结构对齐是正常的。除非本机声明包含#pragma pack指令,否则您的结构将被对齐。

其次,指针对于32位和64位目标是不同的大小,因此您对explicit的使用只能用于一个目标。处理它的方法是仅为联合使用显式布局。这是处理工会的最佳方式。

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

然后在你的struct中使用这个union。

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

如果你的结构真的是打包的,那么使用Pack属性的StructLayout参数来指定它。