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

Is there a definitive guide to cross platform (x86 and x64) PInvoke and windows data types?

本文关键字:数据类型 windows 跨平台 x86 是否 x64 PInvoke      更新时间:2023-10-16

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

  1. 查找API引用,如MapViewOfFile
  2. 查找windows数据类型定义
  3. 查找相应的.NET类型

这是第3步,我想要一个明确的参考

例如:

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;

好的。。。所以我想这是IntPtrUIntPtr。本文有一个表,建议LPVOID应该映射到IntPtr或UIntPtr。好的。

接下来,HANDLE。

手柄

对象的句柄。

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

typedef PVOID HANDLE;

好吧,HANDLE是PVOID。

PVOID

指向任何类型的指针。

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

typedef void*PVOID;

嗯,听起来像IntPtr

接下来,DWORD

DWORD

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

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

typedef unsigned long DWORD;

好的,无符号长0到4294967295,所以这是一个uint,但这里它建议Int32或UInt32。Int32将无法存储超过2147483648的任何值。所以那张桌子很可疑。

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

尺寸_T

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

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

typedef ULONG_PTR SIZE_T;

ULONG_PTR

一个无符号的LONG_PTR。

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

#if defined(_WIN64)
 typedef unsigned __int64 ULONG_PTR;
#else
 typedef unsigned long ULONG_PTR;
#endif

LONG

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

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

typedef long LONG;

INT64

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

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

typedef signed __int64 INT64;

因此,虽然我可以查找每种windows数据类型的定义,然后根据大小、符号以及它是否在x86和x64上都有效找到相应的.NET数据类型,但这并不理想。

有没有一个明确的参考(不是pinvoke.net),有一个针对x64的最新映射表?

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

只有在解释托管值时,有符号类型与无符号类型的选择才重要
它们都是作为原始位进行编组的。

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

因此,一般规则是,任何指针大小的值都变为IntPtr,并且DWORDQWORD分别变为U?Int32U?Int64