当你有句柄时,int vs IntPtr?

时间:2010-11-30 17:23:07

标签: c# pinvoke

首先是一个背景问题:

一般来说,intIntPtr之间有什么区别?我的猜测是它是一个实际的对象而不是intbyte之类的值。假设是真的:

所以他们不一样。然而,我看到手柄代表两者。

  1. IntPtr:Control.Handle
  2. int(或uint):可以设置PInvoke返回int并且它可以正常工作:

    [DllImport("coredll.dll", SetLastError = true)]
    public static extern int GetForegroundWindow();
    private string GetActiveWindow()
    {
        const int nChars = 256;
        int handle = 0;
        StringBuilder Buff = new StringBuilder(nChars);
    
        handle = CoreDLL.GetForegroundWindow();
    
        if (CoreDLL.GetWindowText(handle, Buff, nChars) > 0)
        {
            return Buff.ToString();
        }
    
        return "";
    }
    
  3. 那么,int vs IntPtr?手柄有问题吗?你能用吗?

1 个答案:

答案 0 :(得分:29)

int长度为32位。 IntPtr与您的架构的指针一样长。因此,指针只能存储在32位系统的int中,而 总是存储在IntPtr中。

请注意,“int as a return value”示例 not 使用int来保存指针,但只是为了保存数值。这并不意味着int自动具有正确的大小:该P / Invoke签名的作者应该转到GetForegroundWindow的文档并看到它返回HWND

然后,从平台SDK中的windef.h(或this MSDN page),我们可以看到HWNDHANDLEPVOIDGetForegroundWindow ......一个指针!

因此,据我所知,该签名是错误的,因为IntPtr的返回值的大小取决于架构。因此,它也应该是int

<强>更新

虽然可以从上面推断,但我认为值得明确指出:

  • 在32位应用程序中错误地使用IntPtr而不是int将永远不会导致问题,即使它们在64位Windows上运行;由于此时大多数应用程序都是32位,因此可以让您经常摆脱这些错误。
  • 在64位应用程序中错误地使用IntPtr代替int 无法保证会导致问题,因为实际上很可能会遇到遇到的值在int的32位中。这进一步降低了错误将表现为应用程序错误的可能性。

因此,对于实际显示的错误,必须同时满足三个条件:

  1. IntPtr应该使用int
  2. 可执行映像为64位。
  3. 某些PInvoke调用返回并存储为{{1}}的值实际上大于32位。