如何以32/64位兼容的方式在C#中定义MAPINAMEID结构?

如何以32/64位兼容的方式在C#中定义MAPINAMEID结构?,c#,interop,pinvoke,C#,Interop,Pinvoke,在C中,MAPINAMEID定义为: typedef struct _MAPINAMEID { LPGUID lpguid; ULONG ulKind; union { LONG lID; LPWSTR lpwstrName; } Kind; } MAPINAMEID, FAR * LPMAPINAMEID; 在C#中,我的定义是: [StructLayout(LayoutKind.Explicit)] priv

在C中,MAPINAMEID定义为:

typedef struct _MAPINAMEID
{
    LPGUID lpguid;
    ULONG ulKind;
    union {
        LONG lID;
        LPWSTR lpwstrName;
    } Kind;

} MAPINAMEID, FAR * LPMAPINAMEID;
在C#中,我的定义是:

    [StructLayout(LayoutKind.Explicit)]
    private struct MAPINAMEID
    {
        [FieldOffset(0)]
        public IntPtr lpguid;
        [FieldOffset(8)]
        public uint ulKind;
        [FieldOffset(16)]
        public int lID;
        [FieldOffset(16)]
        public IntPtr lpwstrName;
    };

显然,它只在64位模式下工作,对于32位,我需要不同的偏移量值。不幸的是,FieldOffset属性不允许使用可计算的值(如IntPtr.Size)。是否有一种与平台无关的方法来指定偏移量(或者以某种方式告诉编译器我希望lID和lpwstrName共享相同的偏移量?

您可以这样声明:

[StructLayout(LayoutKind.Sequential)]
private struct MAPINAMEID
{
    public IntPtr lpguid;
    public uint ulKind;
    public IntPtr lpwstrName; // or lID
};

如果需要,可以使用IntPtr 32位转换在lpwstrName和lId之间切换(LONG和ULONG是32位)。

好吧,这就是我现在正在做的事情。但对我来说,这似乎不是一个优雅的解决方案。在32位的情况下,IntPtr.Size与uint Size相同,但在64位的情况下就不是了(而将字体转换为较短的值……值得怀疑).所以,32和64种情况下的不同代码路径(这是我试图避免的)。如果这是你正在做的,为什么不显示它而不是其他东西呢?我不会回答。唉,p/invoke并不总是优雅的,它通常是关于在圆孔中安装方钉。还有其他不优雅的解决方案(两个结构,等等)。我的意思是,我尝试了这一点以及许多其他选项(如读取字节,然后将其转换为值,分离MAPINAMEID32和MAPINAMEID64等)。但它们都假定32位和64位的特定代码路径。我要求的是某种统一的、独立于平台的方式(或者确认没有这种方式).从你的回答中,我现在看到我没有遗漏任何明显的东西,而且确实没有这种方式。这回答了我的问题。谢谢!