我如何将IntPtr转换为UIntPtr
本文关键字:转换 UIntPtr IntPtr | 更新日期: 2023-09-27 18:16:49
我试着像这样投射它:
UIntPtr x = (UIntPtr)intPtr;
…但是编译器对它不太满意,并返回了一个编译错误。
我需要进行转换,因为RegOpenKeyEx的p/Invoke签名需要UIntPtr:
[DllImport("advapi32.dll", CharSet = CharSet.Auto)]
public static extern int RegOpenKeyEx(
UIntPtr hKey,
string subKey,
int ulOptions,
int samDesired,
out UIntPtr hkResult);
为了得到一个句柄,我使用safehandle . dangerouhandle()返回一个IntPtr:
/// <summary>
/// Get a pointer to a registry key.
/// </summary>
/// <param name="registryKey">Registry key to obtain the pointer of.</param>
/// <returns>Pointer to the given registry key.</returns>
IntPtr _getRegistryKeyHandle(RegistryKey registryKey)
{
//Get the type of the RegistryKey
Type registryKeyType = typeof(RegistryKey);
//Get the FieldInfo of the 'hkey' member of RegistryKey
System.Reflection.FieldInfo fieldInfo =
registryKeyType.GetField("hkey", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
//Get the handle held by hkey
SafeHandle handle = (SafeHandle)fieldInfo.GetValue(registryKey);
//Get the unsafe handle
IntPtr dangerousHandle = handle.DangerousGetHandle();
return dangerousHandle;
}
看了msdn后,我注意到UIntPtr
和IntPtr
都有void*
指针转换。
IntPtr a = ....;
UIntPtr b = (UIntPtr)a.ToPointer();
此时需要的是不安全代码。避免这种情况的唯一方法是使用unchecked
关键字并通过使用非指针类型(这里也使用)进行转换。
两个指针之间没有转换的原因可能是UIntPtr
和IntPtr
一样没有固定的大小,因为它们是特定于平台的(参见)。
我发现BitConverter
是最可靠的,因为它在使用VB时也可以工作。. NET不允许从有符号值到无符号值的溢出:
new UIntPtr(BitConverter.ToUInt64(BitConverter.GetBytes(handleIntPtr.ToInt64), 0))
为什么不直接在32位指针上执行unchecked((IntPtr)(int)uintPtr)
,或者在64位指针上执行unchecked((IntPtr)(long)uintPtr)
呢?运行良好(并且比其他解决方案更快)
IntPtr
可以保存和UIntPtr
一样多的值。两者的位数相同
溢出是一个算术概念。算术永远不会在句柄上执行。这个概念在这里不适用。
在整个BCL中IntPtr
是句柄的标准类型。在任何地方使用IntPtr
网站说明:
将IntPtr更改为UIntPtr:当调用IntPtr的句柄时,您将遇到溢出。如果你希望在32位和64位平台上正常工作,UIntPtr是正确的选择。
很可能,他的代码以溢出的方式在类型之间进行转换。这只是他的迷信。他改变了一些东西。其中一个成功了。他现在认为这是IntPtr
的变化,但它是别的东西。
同样,这个选择与过程的比特性无关。
一个更简单的解决方案,不需要不安全的代码,就是简单地先将指针转换为long类型,然后再转换为UIntPtr类型。
IntPtr ptr = …;
UIntPtr Uptr = (UIntPtr)(long)ptr;