C# 映射特定于平台的可互操作类型
参考文件列出了以下类型:C# 映射特定于平台的可互操作类型,c#,c++,.net,interop,pinvoke,C#,C++,.net,Interop,Pinvoke,参考文件列出了以下类型: #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(大部分)取消了预处理器指令,因此要精确地映射这些指令并不容易。我可以看到两种选择,我想知道哪一种最好: 使用IntPt
#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与这个问题有什么关系?
回答:将托管数据正确映射到PInvoke/d(非托管)签名(将来使用)需要windows数据类型 示例:
LRESULT WINAPI SendMessage(
_In_ HWND hWnd,
_In_ UINT Msg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
[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
);
本机声明:
LRESULT WINAPI SendMessage(
_In_ HWND hWnd,
_In_ UINT Msg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
[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
);
平沃克声明变体:
LRESULT WINAPI SendMessage(
_In_ HWND hWnd,
_In_ UINT Msg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
[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上运行的“以防万一”和与指针大小相同的
INT\u PTR
。因此,它们在32位目标中的宽度为32位,在64位目标中的宽度为64位。在C语言中,使用int
或long
都是错误的,因为它们的大小是固定的。INT_PTR
和LONG_PTR
到C的正确翻译为IntPtr
同样,对于未签名的变体,使用
uintpttr
您试图解决什么问题?PInvoke与这个问题有什么关系?@AlexFarber-见Remarksagin,还不清楚IntPtr
具有正确的32位和64位大小。PInvoke调用的本机Dll具有相同的位,因此IntPtr与void*大小相同*@AlexFarber因此说我想PInvoke使用INT_PTR;使用实现是否特定(我需要根据实现选择正确的.NET数据类型,而不是通常使用IntPtr vs Int32/Int64)?不能从64位进程中PInvoke 32位Dll,从32位进程中PInvoke 64位Dll。因此,如果您使用参数INT#PTR来PInvoke原生Dll,将其声明为IntPtr,两者的大小将是相同的。问题…如何在C#中映射半#PTR(32位机器上为16位,64位机器上为32位)?这样的东西是否存在?!根据Windows数据类型参考,是。虽然它对我来说确实很奇怪——甚至可能不会在任何没有C#type可匹配的地方使用。我从来没见过这种类型有什么用。