映射平台特定的互操作类型

Posted

技术标签:

【中文标题】映射平台特定的互操作类型【英文标题】:Mapping platform specific interoperable types 【发布时间】:2014-11-18 12:56:01 【问题描述】:

Windows Data Types 引用列出了以下类型:

#if defined(_WIN64) 
 typedef __int64 INT_PTR; 
#else 
 typedef int INT_PTR;
#endif

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

由于 .NET(大部分)取消了预处理器指令,因此很难准确地映射这些指令。我可以看到两个选项,我想知道哪个最好:

使用 IntPtr,因为它是特定于平台的

using INT_PTR = System.IntPtr;
using LONG_PTR = System.IntPtr;

使用更大的整数,以防我们在 x64 上运行

using INT_PTR = System.Int64;
using LONG_PTR = System.Int64;

我的直觉是使用IntPtr 而不是Int64,但是我想了解一下什么才是真正的最佳选择。

备注

问题:您要解决什么问题? 答案: 通常将 windows 数据类型映射到 .NET,尽可能紧密地支持未来的 PInvoke 操作。

问题: PInvoke 与此问题有何关联? 答案: 需要 windows 数据类型才能将托管数据正确映射到 PInvoke/d(非托管)签名(未来使用)

示例:

土著宣言:

LRESULT WINAPI SendMessage(
  _In_  HWND hWnd,
  _In_  UINT Msg,
  _In_  WPARAM wParam,
  _In_  LPARAM lParam
);

PInvoke 声明变体:

[DllImport("user32.dll", CallingConvention = CallingConvention.Winapi)]
public static extern IntPtr SendMessage(
    [In] IntPtr hWnd,
    [In] uint Msg,
    [In] UIntPtr wParam,
    [In] IntPtr lParam
);

[DllImport("user32.dll", CallingConvention = CallingConvention.Winapi)]
public static extern long SendMessage(
    [In] IntPtr hWnd,
    [In] uint Msg,
    [In] ulong wParam,
    [In] long lParam
);

在上面的示例中,第一个实例使用 IntPtr 和 UIntPtr(特定于平台)类型,而第二个实例使用 long 和 ulong,“以防万一”在 x64 上运行

【问题讨论】:

您要解决什么问题? PInvoke 与这个问题有什么关系? @AlexFarber - 见备注 Agiin,不清楚。 IntPtr 具有正确的 32 位和 64 位大小。 PInvoke 调用的 Native Dll 的位数相同,因此 IntPtr 的大小与 void* 相同 @AlexFarber 因此说我想 PInvoke 使用 INT_PTR 的东西;使用实现是否特定(我需要根据实现选择正确的 .NET 数据类型,而不是一般使用 IntPtr vs Int32/Int64)? 您不能从 64 位进程中 PInvoke 32 位 Dll,也不能从 32 位进程中 PInvoke 64 位 Dll。所以,如果你 PInvoke 带有参数 INT_PTR 的原生 Dll,将其声明为 IntPtr,两者的大小将是相同的。 【参考方案1】:

INT_PTRLONG_PTR 与指针大小相同。因此,它们在 32 位目标中为 32 位宽,在 64 位目标中为 64 位宽。在 C# 中使用 intlong 是完全错误的,因为它们具有固定的大小。 INT_PTRLONG_PTR 到 C# 的正确翻译是 IntPtr

同样,对于未签名的变体,使用UIntPtr

【讨论】:

问题...如何在 C# 中映射 HALF_PTR(32 位机器上为 16 位,64 位机器上为 32 位)? 这种东西还存在吗?! 根据 Windows 数据类型参考,是的。虽然它对我来说似乎很奇怪 - 甚至可能不会在任何地方使用 没有可匹配的 C# 类型。我从未见过这种类型的用途。

以上是关于映射平台特定的互操作类型的主要内容,如果未能解决你的问题,请参考以下文章

创建了对嵌入的互操作程序集间接引用,无法嵌入互操作类型

C 和 C++ 中类型的互操作性

CTS .cls clr 分别做何解释?

库/框架之间的互操作性

Groovy 元类与 Java 8 的互操作性

[转]Go与C语言的互操作