您好、欢迎来到现金彩票网!
当前位置:2019欢乐棋牌 > 争用条件 >

C + +-在 Win32 API 边界使用 STL 字符串

发布时间:2019-06-28 06:35 来源:未知 编辑:admin

  所以,基本上,输入的字符串作为传递一个常数 (即,只读) wchar_t 的字符指针,该字符串指向的假设是以 NUL 结尾,在经典的纯 C 的风格。这是在 Win32 API 边界传递的输入的字符串参数的典型模式。

  另一边,输出字符串在 Win32 API 边界通常表示使用两三件的信息:指向缓冲区的指针目的地,由调用方,并表示调用方提供的缓冲区的总大小的尺寸参数分配。一个例子是 GetWindowText 功能 (bit.ly/1bAMkpA):

  在这种情况下,与目标字符串缓冲区 (输出字符串参数) 相关的信息存储在最后两个参数:消息和拷贝。前者是一个指向目标字符串缓冲区 (使用导出 LPTSTR Win32 typedef,这将转换成 TCHAR *,表示或 wchar_t * 在 Unicode 中生成)。后者,拷贝,代表中 wchar_ts; 目标字符串缓冲区的总大小 注意此值包括终止 NUL 字符 (别忘了那些 C 样式字符串是以 NUL 结尾的字符数组)。

  当然,特别是使用 c + + 而不纯 C 是非常富有成效的选项为发展用户模式 Windows 代码和 Windows 应用程序。事实上,在一般情况下,使用 c + + 提出了语义级别的代码和提高程序员的工作效率,没有对应用程序性能的负面影响。尤其是,使用方便的 c + + 字符串类是更好 (更容易、 更有成效,更容易导致 bug) 比处理原始的 C 像以 NUL 结尾的字符数组。

  所以现在的问题就变成:什么样的 c + + 字符串类可以用于与 Win32 API 层,以本机方式公开一个纯 C 接口进行交互?

  标准的 STL 字符串然而,有更好地在弥补 Windows 应用程序的自定义设计的 c + + 类接口使用标准字符串类的情况。例如,您可能想要抽象出来,尽快在 c + + 代码中,Win32 API 层宁愿而不是 Windows 特定类像 CString 在公共接口的自定义设计 c + + 类 STL 字符串类的使用。所以,让我们考虑一下存储在 STL 字符串类的文本的大小写。在这一点上,您需要将这些 STL 字符串传递跨越 Win32 API 边界 (这也可以使一个纯 C 的接口,如本文开头所述)。使用 ATL,WTL 和 MFC,框架将实现胶水代码之间的 Win32 C 接口层和 CString,隐藏引擎盖下,但这种便利与 STL 字符串不可用。

  请注意,虽然 ATL/MFC CString 提供隐式转换为字符的原始 const 指针 (const TCHAR *,相当于现代的 Unicode 常量 wchar_t * 生成),STL 字符串不提供这样的隐式转换。相反,您必须使 STL 字符串 c_str 方法的显式调用。那里是隐式转换往往不是一件好事,因此 STL 字符串类的设计者选择了一种显式调用 c_str 方法的现代 c + + 中的共同理解。(你会发现相关的讨论上,缺乏现代 STL 智能指针在博客中的隐式转换bit.ly/1d9AGT4.)

  把事情变得有点多复杂与输出字符串。通常的模式组成的第一次调用 Win32 API 输出字符串中获取目标缓冲区的大小。这可能包括或不包括终止 NUL; 特殊的文档 Win32 API 必须为此目的阅读。

  然后,由调用方动态分配适当大小的缓冲区。该缓冲区的大小是在上一步中确定的大小。

  以及最后,对 Win32 API 作出另一个调用,实际的字符串内容读入的调用方分配的缓冲区。

  然后,可以使用该长度分配一个字符串缓冲区。这里的选项可以使用 std::vector wchar_t 若要管理字符串缓冲区中,例如:

  请注意,这是比使用原料简单得叫新 wchar_t [bufferLength],因为这将需要正确释放缓冲区调用删除 [] (和到忘了做那会引起内存泄漏)。使用 std::vector 是只是更简单,即使使用向量有一个较小的开销相对于原始的新 [] 呼叫。事实上,在这种情况下 std::vector 的析构函数将自动删除已分配的缓冲区。

  这也有助于建立异常安全的 c + + 代码:如果在代码中某个地方引发一个异常,std::vector 析构函数会自动调用。相反,与新的 [],其指针存储在原始拥有指针,动态分配的缓冲区会被泄露。

  然后,一旦分配适当大小的缓冲区,并准备好使用,可以调用 GetWindowText API,则将指针传递给该字符串缓冲区。要获取一个指针,指向原始缓冲区由 std::vector,std::vector::data 方法的开始 (bit.ly/1I3ytEA) 可以使用,就像这样:

  并且,最后,控件的文本可以深从临时缓冲区拷贝到一个 std::wstring 实例:

  在前面的代码片段中,我使用 wstring,构造函数重载以恒定的原始 wchar_t 指针,指向一个 NUL 结尾的输入字符串。这只是正常工作,因为被调用的 Win32 API 将在由调用方提供的目标字符串缓冲区中插入一个 NUL 结束符。

  作为一种轻微的优化,如果 (wchar_ts) 中的字符串的长度已知的 wstring 的构造函数重载以指针和一个字符串字符计数参数可供使用。在这种情况下,在调用站点,提供了字符串长度和 wstring 构造函数不需要 (通常与 o (n) 操作,类似于在 Visual c + + 实现中调用 wcslen) 把它找出来。

  事实上,std::wstring 具有一个大小调整方法,可以用来生成一个适当大小的字符串。请注意,在这种情况下,您不关心实际的初始内容的调整大小后的字符串,因为它将被调用 Win32 API 所覆盖。图 1包含示例代码段演示如何读取字符串在使用 std::wstring 的地方。

  获取写访问内部字符串缓冲区第一,考虑 GetWindowText 电话:

  C + + 程序员可能会使用 std::wstring::data 方法来访问内部字符串内容,通过指针传递给 GetWindowText 调用。但 wstring::data 返回常量的指针,不允许内部字符串缓冲区被修改的内容。GetWindowText 预计写访问 wstring 的内容,因为该调用不会编译。所以,替代方法是使用 & 文本 [0] 语法以获得要作为输出传递的内部字符串缓冲区的开始的地址 (也就是说,可修改) 到所需的 Win32 API 的字符串。

  与以往的方法相比,这种技术是更有效是有没有临时的 std::vector,第一次分配,然后深复制到 std::wstring,并最后,丢弃的缓冲区。事实上,在这种情况下,代码只是运行在一个 std::wstring 实例的地方。

  在结束之前这篇文章,它值得讨论如何处理潜在的争用条件,可能会出现一些 Api。例如,假设您有从 Windows 注册表中读取一些字符串值的代码。遵循的模式表明在上一节,c + + 程序员将首先调用 RegQuery­ValueEx 函数来获取字符串值的长度。然后在此基础上,将分配的字符串缓冲区,,最后 RegQueryValueEx 也会叫第二次来读入缓冲区在上一步中创建的实际字符串值。

  在这种情况下可能出现争用条件是修改这两个 RegQueryValueEx 调用之间的字符串值的另一个进程。第一次调用所返回的字符串的长度可能是毫无意义的价值,无关写在注册表中的其他进程的新字符串值。所以,RegQueryValueEx 第二次调用会读错的大小分配的缓冲区中的新字符串。

  使用 while 循环在图 2确保因为验证返回,每次一个新的缓冲区分配适当的 bufferLength 值,直至 API 调用成功 (返回写入) 或因其他原因而提供不够大小的缓冲区失败,在适当长度的缓冲区中读取的字符串。

  请注意,代码段在图 2是只是骨架代码示例; 其他 Win32 Api 可以使用不同的错误代码 ERROR_INSUFFICIENT_BUFFER 代码的调用方,例如,提供的缓冲区不足有关。

  虽然在 Win32 API 边界使用 CString — — 像 ATL/WTL 以及 MFC 框架的帮助 — — 隐藏的力学与 Win32 纯 C 接口层,当使用 STL 字符串 c + + 程序员的互操作必须注意某些细节。在这篇文章中,我讨论了一些编码模式的 Win32 纯 C 接口函数与 STL wstring 类的互操作。在输入的情况下,调用 wstring 的 c_str 方法是没事就去在 Win32 C 接口边界,简单恒定 (只读) 以 NUL 结尾的字符串的字符指针的形式传递输入的字符串。对于输出字符串,必须由调用方分配临时字符串缓冲区。这可以实现使用 std::vector STL 类或略少开销,STL std::unique_ptr 智能指针模板类。另一个选项是使用 wstring::resize 方法,作为为 Win32 API 函数的目标缓冲区分配一些房间内的字符串实例。在这种情况下,就必须指定足够的空间来允许被调用的 Win32 API,涂在其 NUL 结束符,然后调整到印章,下车离开只有 wstring NUL 结束符。最后,覆盖潜在的争用条件,并提出了一种编码模式来解决此争用条件的示例。

http://altofigaro.com/zhengyongtiaojian/45.html
锟斤拷锟斤拷锟斤拷QQ微锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷微锟斤拷
关于我们|联系我们|版权声明|网站地图|
Copyright © 2002-2019 现金彩票 版权所有