首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >什么是Windows句柄?

问什么是Windows句柄?
EN

Stack Overflow用户
提问于 2009-05-24 02:51:48
回答 7查看 152.1K关注 0票数 169

在Windows中讨论资源时,什么是“句柄”?它们是如何工作的?

EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2009-05-24 02:54:26

它是对资源的抽象引用值,通常是内存、打开的文件或管道。

正确地说,在Windows中(通常在计算中)句柄是一种抽象,它对API用户隐藏了真实的内存地址,允许系统对程序透明地重组物理内存。将句柄解析为指针会锁定内存,释放句柄会使指针失效。在这种情况下,可以将其视为指向指针表的索引...您可以将索引用于系统API调用,系统可以随意更改表中的指针。

可选地,当API编写器打算使API的用户与返回的地址所指向的细节隔离时,可以给出实际指针作为句柄;在这种情况下,必须考虑句柄所指向的内容在任何时候都可能改变(从API版本到版本,或者甚至从对返回句柄的API的调用到调用),因此应该将句柄简单地视为仅对API有意义的不透明值。

我要补充的是,在任何现代操作系统中,即使是所谓的“真实指针”也仍然是进程的虚拟内存空间的不透明句柄,这使得O/S能够管理和重新安排内存,而不会使进程中的指针无效。

票数 195
EN

Stack Overflow用户

发布于 2009-05-24 03:09:17

HANDLE是特定于上下文的唯一标识符。通过上下文特定,我的意思是,从一个上下文获得的句柄不一定用于任何其他也在HANDLE上工作的行为上下文中。

例如,GetModuleHandle向当前加载的模块返回唯一标识符。返回的句柄可以在接受模块句柄的其他函数中使用。它不能提供给需要其他类型句柄的函数。例如,您不能将从GetModuleHandle返回的句柄提供给HeapDestroy,并期望它做一些合理的事情。

HANDLE本身只是一个整型。通常,它是指向某个基础类型或内存位置的指针,但不是必须的。例如,GetModuleHandle返回的HANDLE实际上是指向模块的基本虚拟内存地址的指针。但是没有规则规定句柄必须是指针。句柄也可以只是一个简单的整数(它可能被一些Win32应用程序接口用作数组的索引)。

HANDLE是从内部Win32资源提供封装和抽象的故意不透明的表示。这样,Win32 API可能会更改句柄背后的底层类型,而不会以任何方式影响用户代码(至少这是这样的想法)。

考虑我刚刚编写的Win32应用程序接口的这三个不同的内部实现,并假设Widget是一个struct。

代码语言:javascript
复制
Widget * GetWidget (std::string name)
{
    Widget *w;

    w = findWidget(name);

    return w;
}
代码语言:javascript
复制
void * GetWidget (std::string name)
{
    Widget *w;

    w = findWidget(name);

    return reinterpret_cast<void *>(w);
}
代码语言:javascript
复制
typedef void * HANDLE;

HANDLE GetWidget (std::string name)
{
    Widget *w;

    w = findWidget(name);

    return reinterpret_cast<HANDLE>(w);
}

第一个示例公开了关于struct Widget的内部细节:它允许用户代码知道GetWidget返回一个指向API的指针。这有几个后果:

  • 用户代码必须有权访问定义Widget结构的头文件
  • 用户代码可能会修改返回的Widget结构

的内部部分

这两种后果可能都是不可取的。

第二个示例通过仅返回void *,对用户代码隐藏了此内部细节。用户代码不需要访问定义Widget结构的头文件。

第三个示例与第二个示例完全相同,但我们只是将void *称为HANDLE。也许这会阻碍用户代码尝试找出void *所指向的确切内容。

为什么要经历这样的麻烦呢?考虑这个相同API的更新版本的第四个示例:

代码语言:javascript
复制
typedef void * HANDLE;

HANDLE GetWidget (std::string name)
{
    NewImprovedWidget *w;

    w = findImprovedWidget(name);

    return reinterpret_cast<HANDLE>(w);
}

请注意,该函数的接口与上面的第三个示例相同。这意味着用户代码可以继续使用这个新版本的应用程序接口,而无需任何更改,即使“幕后”实现已改为使用NewImprovedWidget结构。

这些示例中的句柄实际上只是void *的一个新的、可能更友好的名称,这正是Win32应用编程接口中的HANDLE (请查看at MSDN。它在用户代码和Windows库的内部表示之间提供了一堵不透明的墙,从而增加了使用Win32应用编程接口的代码在不同版本之间的可移植性。

票数 110
EN

Stack Overflow用户

发布于 2009-05-24 02:58:53

Win32编程中的句柄是表示由Windows内核管理的资源的标记。句柄可以是窗口、文件等。

句柄只是一种使用Win32 API标识要使用的颗粒资源的方法。

例如,如果您想创建一个窗口,并将其显示在屏幕上,您可以执行以下操作:

代码语言:javascript
复制
// Create the window
HWND hwnd = CreateWindow(...); 
if (!hwnd)
   return; // hwnd not created

// Show the window.
ShowWindow(hwnd, SW_SHOW);

在上面的例子中,HWND意味着“一个窗口的句柄”。

如果您习惯于面向对象的语言,您可以将句柄视为没有方法的类的实例,该类的状态只能由其他函数修改。在这种情况下,ShowWindow函数修改窗口句柄的状态。

有关详细信息,请参阅Handles and Data Types。

票数 41
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/902967

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档