C# 是否有跨平台(x86和x64)PInvoke和windows数据类型的明确指南?
我正在验证x64兼容性的一些代码。以前我使用过PInvoke.net,但我发现了一些关于x64的可疑声明。现在,我: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
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++之间共享内存,它使我的代码变得简单多了。