C# 是否有跨平台(x86和x64)PInvoke和windows数据类型的明确指南?

C# 是否有跨平台(x86和x64)PInvoke和windows数据类型的明确指南?,c#,c++,winapi,64-bit,pinvoke,C#,C++,Winapi,64 Bit,Pinvoke,我正在验证x64兼容性的一些代码。以前我使用过PInvoke.net,但我发现了一些关于x64的可疑声明。现在,我: 查找API参考,例如 查一下定义 查找相应的.NET类型 这是第三步,我想要一个明确的参考 例如: LPVOID WINAPI MapViewOfFile( __in HANDLE hFileMappingObject, __in DWORD dwDesiredAccess, __in DWORD dwFileOffsetHigh, __in DWORD

我正在验证x64兼容性的一些代码。以前我使用过PInvoke.net,但我发现了一些关于x64的可疑声明。现在,我:

  • 查找API参考,例如
  • 查一下定义
  • 查找相应的.NET类型
  • 这是第三步,我想要一个明确的参考

    例如:

    LPVOID WINAPI MapViewOfFile(
      __in  HANDLE hFileMappingObject,
      __in  DWORD dwDesiredAccess,
      __in  DWORD dwFileOffsetHigh,
      __in  DWORD dwFileOffsetLow,
      __in  SIZE_T dwNumberOfBytesToMap
    );
    
    返回值为LPVOID,定义为:

    LPVOID

    指向任何类型的指针

    该类型在WinDef.h中声明如下:

    typedef void *LPVOID;
    
    typedef unsigned long DWORD;
    
    typedef ULONG_PTR SIZE_T;
    
    #if defined(_WIN64)
     typedef unsigned __int64 ULONG_PTR;
    #else
     typedef unsigned long ULONG_PTR;
    #endif
    
    typedef long LONG;
    
    typedef signed __int64 INT64;
    
    好的。。。所以我猜这是
    IntPtr
    UIntPtr
    。这有一个表,建议LPVOID映射到IntPtr或UIntPtr。嗯

    下一步,处理

    手柄

    对象的句柄

    该类型在WinNT.h中声明如下:

    typedef void *LPVOID;
    
    typedef unsigned long DWORD;
    
    typedef ULONG_PTR SIZE_T;
    
    #if defined(_WIN64)
     typedef unsigned __int64 ULONG_PTR;
    #else
     typedef unsigned long ULONG_PTR;
    #endif
    
    typedef long LONG;
    
    typedef signed __int64 INT64;
    
    typedef PVOID手柄

    好的,句柄是一个PVOID

    PVOID

    指向任何类型的指针

    该类型在WinNT.h中声明如下:

    typedef void *LPVOID;
    
    typedef unsigned long DWORD;
    
    typedef ULONG_PTR SIZE_T;
    
    #if defined(_WIN64)
     typedef unsigned __int64 ULONG_PTR;
    #else
     typedef unsigned long ULONG_PTR;
    #endif
    
    typedef long LONG;
    
    typedef signed __int64 INT64;
    
    typedef void*PVOID

    嗯,听起来像是
    IntPtr

    接下来,德沃德

    DWORD

    32位无符号整数。范围为0到4294967295十进制

    该类型在WinDef.h中声明如下:

    typedef void *LPVOID;
    
    typedef unsigned long DWORD;
    
    typedef ULONG_PTR SIZE_T;
    
    #if defined(_WIN64)
     typedef unsigned __int64 ULONG_PTR;
    #else
     typedef unsigned long ULONG_PTR;
    #endif
    
    typedef long LONG;
    
    typedef signed __int64 INT64;
    
    好的,无符号长0到4294967295,这是一个
    uint
    ,但它表示Int32或UInt32。Int32无法存储超过2147483648的任何值。所以那张桌子很可疑

    最后,我们还有SIZE_T,它被定义为一个ULONG_PTR,根据平台的不同,它可以是32位或64位有符号长(定义如下)。这(和)得出结论,您应该使用IntPtr,因为它将处理可变大小

    大小\u T

    指针可以指向的最大字节数。用作 必须跨越指针整个范围的计数

    此类型在BaseTsd.h中声明如下:

    typedef void *LPVOID;
    
    typedef unsigned long DWORD;
    
    typedef ULONG_PTR SIZE_T;
    
    #if defined(_WIN64)
     typedef unsigned __int64 ULONG_PTR;
    #else
     typedef unsigned long ULONG_PTR;
    #endif
    
    typedef long LONG;
    
    typedef signed __int64 INT64;
    
    ULONG_PTR

    未签名的长PTR

    此类型在BaseTsd.h中声明如下:

    typedef void *LPVOID;
    
    typedef unsigned long DWORD;
    
    typedef ULONG_PTR SIZE_T;
    
    #if defined(_WIN64)
     typedef unsigned __int64 ULONG_PTR;
    #else
     typedef unsigned long ULONG_PTR;
    #endif
    
    typedef long LONG;
    
    typedef signed __int64 INT64;
    
    LONG

    32位有符号整数。范围为–2147483648到2147483647 十进制

    该类型在WinNT.h中声明如下:

    typedef void *LPVOID;
    
    typedef unsigned long DWORD;
    
    typedef ULONG_PTR SIZE_T;
    
    #if defined(_WIN64)
     typedef unsigned __int64 ULONG_PTR;
    #else
     typedef unsigned long ULONG_PTR;
    #endif
    
    typedef long LONG;
    
    typedef signed __int64 INT64;
    
    INT64

    64位有符号整数。范围为–9223372036854775808到 9223372036854775807十进制

    此类型在BaseTsd.h中声明如下:

    typedef void *LPVOID;
    
    typedef unsigned long DWORD;
    
    typedef ULONG_PTR SIZE_T;
    
    #if defined(_WIN64)
     typedef unsigned __int64 ULONG_PTR;
    #else
     typedef unsigned long ULONG_PTR;
    #endif
    
    typedef long LONG;
    
    typedef signed __int64 INT64;
    
    因此,虽然我可以查找每个windows数据类型的定义,然后根据大小、符号以及它是否在x86和x64上都有效找到相应的.NET数据类型,但这并不理想


    是否有一个明确的引用(而不是pinvoke.net)和一个适用于x64的最新映射表?

    将本机数据类型映射到托管类型时,重要的是大小和一致性

    只有在解释托管值时,有符号与无符号类型的选择才起作用。
    它们都被当作未加工的碎片整理

    在大多数情况下,您只需将值从一个API方法传递到另一个API方法;在这些情况下,类型是有符号的还是无符号的并不重要,只要大小合适


    因此,一般的规则是,任何指针大小的值分别变成
    IntPtr
    DWORD
    QWORD
    变成
    U?Int32
    U?Int64

    假设我调用一些组合函数GetSystemMemory(\uu out DWORD totalMemory),它返回0xFFFFFFFF。如果我获取该值并将其传递给另一个Win32函数,则Int32或UInt32不会有任何区别,因为原始位仍然是0xFFFFFF。但是,如果我试图在CLR中解释该值,它将作为UInt32而不是Int32来解释。因此,我想说DWORD应该始终作为UInt32进行编组-值可以在两种上下文中进行编组和解释,并且具有相同的含义?我想避免“一般规则”,科学地去做…@StevenP:这取决于原生类型的意思。听起来它应该在
    Int32
    中,值为
    -1
    。谢谢你的回答。也许0xFFFFFF是一个令人困惑的例子。我的意思是0xFFFFFF作为4GB的有效值。因此,如果函数返回4GB,并且我使用Int32,那么它在managed land中没有意义,但在win32中会有意义。那么,如果UInt32能够封送值并表示其含义,为什么我要将其封送为Int32而不是UInt32呢?在本例中为4GB。@StevenP:如果该值应为4GB,请使用
    UInt32
    。如果它应该是
    -1
    ,请使用
    Int32
    。这取决于本机函数的语义。此外,如果32位机器上是32位的,而64位机器上是64位的(如ptrdiff_t),则必须使用IntPtr。我知道您已经使用了IntPtr作为示例,但仅供参考。自.NET 4.0以来,您可以使用ClassThank Shaun-我确实在.NET 4.0中看到了MemoryMappedFile实现,但在本例中,我没有控制客户环境的乐趣,不幸的是,4没有在卡上。不用担心,我用它来在.NET和本地C++之间共享内存,它使我的代码变得简单多了。