当你有句柄时 int 与 IntPtr?

发布于 2024-10-05 01:45:08 字数 733 浏览 3 评论 0 原文

首先是一个背景问题:

一般来说,intIntPtr 之间有什么区别?我的猜测是它是一个实际的对象,而不是像 int 或 byte 那样的值。假设这是真的:

所以它们不一样。但我看到句柄同时表示为两者。

  1. IntPtr:Control.Handle
  2. int(或uint):可以将PInvoke设置为返回int并且它工作得很好:

    [DllImport("coredll.dll", SetLastError = true)]
    公共静态 extern int GetForegroundWindow();
    私有字符串 GetActiveWindow()
    {
        常量 int nChars = 256;
        int 句柄 = 0;
        StringBuilder Buff = new StringBuilder(nChars);
    
        句柄= CoreDLL.GetForegroundWindow();
    
        if (CoreDLL.GetWindowText(handle, Buff, nChars) > 0)
        {
            返回 Buff.ToString();
        }
    
        返回 ””;
    }
    

所以,int IntPtr?跟手柄有关系吗?两者都可以用吗?

First a background question:

In general, what is the difference between int and IntPtr? My guess is that it is an actual object rather than a value like an int or byte is. Assuming that is true:

So they are not the same. Yet I see handles represented as both.

  1. IntPtr: Control.Handle
  2. int (or uint): A PInvoke can be setup to return an int and it works just fine:

    [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 "";
    }
    

So, int vs IntPtr? Does it matter for handles? Can you use either?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

你爱我像她 2024-10-12 01:45:08

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

请注意,您的“int 作为返回值”示例并没有使用 int 来保存指针,而只是保存数值。但这并不意味着 int 自动具有正确的大小:该 P/Invoke 签名的作者应该查看 GetForegroundWindow 并查看它返回一个 HWND

然后,从 Platform SDK 中的 windef.h (或 这个 MSDN 页面)我们可以看到 HWND 是一个 HANDLE ,它是一个 PVOID ,它是……一个指针!

因此,据我所知,该签名是错误的,因为 GetForegroundWindow 返回值的大小取决于体系结构。因此,它也应该是一个IntPtr

更新:

虽然可以从上面推断出来,但我认为有必要明确指出:

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

因此,要真正显示错误,必须同时满足三个条件:

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

int is 32 bits long. IntPtr is as long as a pointer for your architecture. Therefore, a pointer can be stored into an int only on 32 bit systems, while it can always be stored in an IntPtr.

Notice that your "int as a return value" example does not use an int to hold a pointer, but just to hold a numeric value. This does not mean that an int is automatically the correct size though: the author of that P/Invoke signature should have gone to the documentation for GetForegroundWindow and see that it returns a HWND.

Then, from windef.h in the Platform SDK (or this MSDN page) we can see that a HWND is a HANDLE which is a PVOID which is... a pointer!

Therefore, as far as I can tell, that signature is wrong, as the size of the return value of GetForegroundWindow depends on the architecture. Thus, it should also be an IntPtr.

Update:

While it can be inferred from the above, I think it's worthwhile to explicitly point out that:

  • Erroneously using int instead of IntPtr in 32-bit applications will never cause a problem, even if they run on 64-bit Windows; since most applications are 32-bit at this point in time, this will let you get away such mistakes very often.
  • Erroneously using int instead of IntPtr in 64-bit applications is not guaranteed to cause problems, since it is quite possible that in practice the values being encountered will fit in the 32 bits of the int. This further lessens the probability that a mistake will manifest as an application error.

Therefore, for an error to actually manifest there are three conditions that have to be satisfied at the same time:

  1. An int is used where an IntPtr should be.
  2. The executable image is 64-bit.
  3. A value returned by some PInvoke call and stored as an int is actually larger than 32 bits.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文