如何将IntPtr转换为UIntPtr?

时间:2011-12-06 08:32:34

标签: c#

我试着像这样投射它:

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.DangerousHandle()返回一个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;
    }

5 个答案:

答案 0 :(得分:2)

在看了msdn之后,我注意到UIntPtrIntPtr都有void*指针转换。

IntPtr a = ....;
UIntPtr b = (UIntPtr)a.ToPointer();

此时您需要不安全的代码。避免这种情况的唯一方法是使用unchecked关键字并使用非指针类型进行转换(也使用here)。

两个指针之间没有转换的原因可能是UIntPtr IntPtr之类的{{1}}没有固定大小,因为它们是特定于平台的(see)。

答案 1 :(得分:0)

我发现BitConverter最可靠,因为它在使用VB.NET时也有效,它不允许从签名到无符号值的溢出:

new UIntPtr(BitConverter.ToUInt64(BitConverter.GetBytes(handleIntPtr.ToInt64), 0))

答案 2 :(得分:0)

为什么不对32位指针执行unchecked((IntPtr)(int)uintPtr),或对64位指针执行unchecked((IntPtr)(long)uintPtr)?运行良好(并且比其他解决方案更快)。

答案 3 :(得分:0)

IntPtr可以包含与UIntPtr一样多的值。两者都具有相同的位数。

溢出是算术的概念。 Arithemtic永远不会在句柄上执行。这个概念在这里不适用。

在整个BCL IntPtr中是句柄的标准类型。到处使用IntPtr

该网站说:

  

将IntPtr更改为UIntPtr:当使用IntPtr调用句柄时,您将遇到溢出。如果您希望在32位和64位平台上正常工作,UIntPtr是正确的选择。

他的代码可能是以溢出的方式在类型之间进行转换。这只是他的迷信。他改变了一些事情。其中一个下摆使它工作。他现在认为这是IntPtr改变,但它是另一回事。

此外,这一选择无助于确定流程的位数。

答案 4 :(得分:0)

一种非常简单的解决方案,不需要不安全的代码,只需将指针先转换为long类型,然后再转换为UIntPtr。

IntPtr ptr = …;
UIntPtr Uptr = (UIntPtr)(long)ptr;