有没有确切的指导跨平台(x86和x64)PInvoke和Windows数据类型? [英] Is there a definitive guide to cross platform (x86 and x64) PInvoke and windows data types?

查看:116
本文介绍了有没有确切的指导跨平台(x86和x64)PInvoke和Windows数据类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在验证一些代码为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,定义如下:


$ b b


LPVOID



指向任何类型的指针。



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

  typedef void * LPVOID; 


OK ...所以我想这是 IntPtr UIntPtr 。此文章有一个表格,并建议LPVOID应映射到IntPtr或UIntPtr。 OK。



接下来,HANDLE。


>



对象的句柄。



这种类型在WinNT.h中声明如下: p>

typedef PVOID HANDLE;


OK,HANDLE是一个PVOID。 >

PVOID



指向任何类型的指针。 p>

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



typedef void * PVOID;


Hmmmm,听起来像 IntPtr



接下来,DWORD


DWORD



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



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

  typedef unsigned long DWORD; 


OK,unsigned long 0 to 4294967295,this is a uint ,但这里它建议Int32或UInt32。 Int32将不能存储任何超过2,147,483,648的值。所以表是非常可疑的。



最后,我们有SIZE_T,它被定义为ULONG_PTR,可以是32或64位有符号长的,取决于平台)。此文章(和 follow up < a>)认为您应该使用IntPtr,因为它将处理变量大小。


SIZE_T



指针可以指向的最大字节数。



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

  typedefULONG_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 b

一个32位有符号整数。范围是-2147483648到2147483647
十进制。



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

  typedef long LONG; 

INT64



一个64位有符号整数。范围是-9223372036854775808到
9223372036854775807十进制。



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

  typedef signed __int64 INT64; 


因此,虽然我可以查找每个窗口数据的定义类型,然后在大小,符号方面找到相应的.NET数据类型,以及它是否对x86和x64都起作用,这是不理想的。



是否有确定的引用

解决方案

当映射原生数据类型到原始数据类型时,



有符号和无符号类型的选择仅在解释管理值时才有用。



在大多数情况下,你只是将值从一个API方法传递到另一个;在这些情况下,无论类型是签名还是无符号,只要它的大小合适。



因此,一般规则是任何指针 - 大小的值变为 IntPtr DWORD QWORD code> U?Int32 和 U?Int64


I am verifying some code for x64 compatability. Previously I've used PInvoke.net, but I've found a few suspect declarations in terms of x64. So now, I:

  1. Look up the API reference such as MapViewOfFile
  2. Look up the windows data type definition
  3. Find the corresponding .NET type.

It's step 3 where I'd like a definitive reference

As an example:

LPVOID WINAPI MapViewOfFile(
  __in  HANDLE hFileMappingObject,
  __in  DWORD dwDesiredAccess,
  __in  DWORD dwFileOffsetHigh,
  __in  DWORD dwFileOffsetLow,
  __in  SIZE_T dwNumberOfBytesToMap
);

Return value is LPVOID, which is defined as:

LPVOID

A pointer to any type.

This type is declared in WinDef.h as follows:

typedef void *LPVOID;

OK... so I guess that's IntPtr or UIntPtr. This article has a table and suggests LPVOID should map to IntPtr or UIntPtr. OK.

Next, HANDLE.

HANDLE

A handle to an object.

This type is declared in WinNT.h as follows:

typedef PVOID HANDLE;

OK, HANDLE is a PVOID.

PVOID

A pointer to any type.

This type is declared in WinNT.h as follows:

typedef void *PVOID;

Hmmmm, sounds like IntPtr

Next, DWORD

DWORD

A 32-bit unsigned integer. The range is 0 through 4294967295 decimal.

This type is declared in WinDef.h as follows:

typedef unsigned long DWORD;

OK, unsigned long 0 to 4294967295, so that's a uint and yet here it suggests Int32 or UInt32. Int32 won't be able to store any value over 2,147,483,648. So that table is very suspect.

Finally, we have SIZE_T, which is defined as a ULONG_PTR which can be 32 or 64 bit signed long depending on the platform (definitions below). This article (and follow up) conclude you should use IntPtr, since it will handle the variable sizes.

SIZE_T

The maximum number of bytes to which a pointer can point. Use for a count that must span the full range of a pointer.

This type is declared in BaseTsd.h as follows:

typedef ULONG_PTR SIZE_T;

ULONG_PTR

An unsigned LONG_PTR.

This type is declared in BaseTsd.h as follows:

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

LONG

A 32-bit signed integer. The range is –2147483648 through 2147483647 decimal.

This type is declared in WinNT.h as follows:

typedef long LONG;

INT64

A 64-bit signed integer. The range is –9223372036854775808 through 9223372036854775807 decimal.

This type is declared in BaseTsd.h as follows:

typedef signed __int64 INT64;

So, while I can look up the definition of every windows data type and then find a corresponding .NET datatype in terms of size, sign, and whether it works on both x86 and x64, it's not ideal.

Is there a definitive reference out there (not pinvoke.net) with a good mapping table that's up to date for x64?

解决方案

When mapping native datatypes to managed types, all that matters is size and consistency.

The choice of signed vs. unsigned types only matters when interpreting the managed value.
They're both marshaled as raw bits.

In most cases, you will just be passing values from one API method to another; in these cases, it doesn't matter whether the type is signed or unsigned, as long as it's the right size.

Therefore, the general rule is that any pointer-sized value becomes IntPtr, and DWORD and QWORD become U?Int32 and U?Int64, respectively.

这篇关于有没有确切的指导跨平台(x86和x64)PInvoke和Windows数据类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆