BSTR数据类型

2023-12-09 13:19
文章标签 数据类型 bstr

本文主要是介绍BSTR数据类型,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

多数支持COM的语言都没法处理单以NULL结尾的字符数组(不管是否是UNICODE)。Visual Basic, Java, VBScript, 还有 Jscript都希望字符串是固定字节长度的。BSTR数据类型是一个UNICODE,固定字节长度,且以NULL结尾的字符串,所有的COM兼容语言都 可以使用。虽然所有的COM兼容的语言都能使用BSTR,但它们都以自己的方式操作。VB程序员用下面的代码创建BSTR:

' VB developer made a BSTR.
'
Dim name as String
name = "Fred Flintstone"

作为C++程序员,我们使用一组COM包创建,操作BSTR数据。每个BSTR方法名都有"Sys-"前缀,用以表示是操作BSTR的(system string)。比较有趣的是BSTR是个OLECHAR*的typedef,所以它是一个OLECHAR字符数组。

// Behold the BSTR (<wtypes.h>).
typedef OLECHAR*          BSTR;

操作BSTR的方法才是真正有区别的地方。下面我们就看一下常用的BSTR方法,了解什么时候去使用它。

在C++中创建BSTR

当你要在C++中创建BSTR的时候,你需要使用SysAllocString()。这个方法会计算字符串的长度并设置足够的缓存。例如,我们传入一个UNICODE的字符串,用bstrName变量来保持返回值:

// SysAllocString() creates a BSTR.
BSTR bstrName;
bstrName = SysAllocString(L"Fred Flintstone");

当然,多数情况下你不想使用硬代码的字符串来初始化BSTR,而使用变量。应此,你可以使用OLECHAR*变量来创建BSTR(使用OLESTR宏来确保使用正确的类型):

// Create a BSTR using an array of OLECHAR types (could be char or wchar_t).
OLECHAR* pOLEStr;     
pOLEStr = OLESTR("Fred Flinstone");
BSTR bstrName;
bstrName = SysAllocString(pOLEStr);

操作BSTR

一旦你创建了一个BSTR,你很有可能在程序中会重设它的值。使用SysReAllocString()来修改一个现有的BSTR,它会释放之前的空间,重新计算字符串的长度和设置缓存:

// Change existing bstrName to 'Mr. Slate'
SysReAllocString(&bstrName, L"Mr. Slate");

SysStringLen()方法给你计算现存BSTR缓存的长度:

// Mr. Slate == 9
int length = SysStringLen(bstrName);

重要的是,任何一个使用SysAllocString()创建BSTR必须使用SysFreeString()来清除。任何一个你从接口方法获得的BSTR也需要使用SysFreeString()来清除。

// All done with the string.
SysFreeString(bstrName);

注意:忘记使用SysFreeString()来清除BSTR会导致内存泄漏。这个的重要性就和在C++中用NEW来获得内存而忘记用DELETE删除是一样的。

额外的BSTR方法

SysAllocString(), SysStringLen(), 和 SysFreeString()方法是学习操作BSTR的好开始,BSTR的API还定义了一些其他的方法。这里列举 了<oleauto.h>中定义的所有的方法,在线帮助里有更完善的注解:

SysAllocString()
创建一个新的BSTR 。

SysReAllocString()
重新设置一个已存在的BSTR 。

SysStringLen()
返回BSTR 的长度。

SysFreeString()
销毁已存在的BSTR 。

SysReAllocStringLen()
Used to create a BSTR based on some length of characters.

SysStringByteLen()
返回BSTR的字节长度。(Win32)

SysAllocStringByteLen()
使用二进制数据来创建BSTR。你只能在不存在ANSI 到Unicode 或是Unicode 到ANSI转换的情况下使用。(Win32)


Unicode 到 ANSI转换

即使我们都能接纳BSTR(最大化的做到语言独立性),我们还有一个未解决的问题。WIN32 API的字符串参数通常都是ANSI类型。如:我们广泛使用的MessageBox()看起来是这样:

// This is the MessageBox() method we think we know...
MessageBox (HWND hWnd , LPCSTR lpText, LPCSTR lpCaption, UINT uType);

根据上面的方法原型,它看起来像是我们需要提供2个字符数组常量(LPCSTR =指向常量字符数组的长指针)。然而,现实总是很奇怪,事实上WIN32 API中根本就没有MessageBox()方法。实际上这个方法(所有包含字符串参数的WIN32方法)定义成2个可能的形式:

// Every Win32 function which takes text strings has an ANSI (A) or Unicode(W)
// variation.
#ifdef UNICODE
     #define MessageBox MessageBoxW
#else
     #define MessageBox MessageBoxA
#endif // !UNICODE

在WIN NT下,当你选择使用UNICODE编译你的当前项目时,就会定义UNICODE预处理标志(在Project | Settings菜单中选择)。在这种情况下,API中所有的方法就会自动转变成宽字符版本。例如MessageBox()会转换为下面的形式:

// Under Unicode builds, all strings come through as an array of constant wchar_t.
MessageBoxW( HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType);

在非UNICODE结构下,MessageBox()转变成ANSI字符版本:

// ANSI builds use const char arrays.
MessageBoxA (HWND hWnd , LPCSTR lpText, LPCSTR lpCaption, UINT uType);

我们遇到了进退两难的情况,如果我们选择UNICODE结构,我们的项目就只能在WIN NT下正确运行。如果我们选择非UNICODE结构,程序就可以运行在所有的平台上,虽然在UNICODE平台上(比如WIN NT)会执行ANSI到UNICODE的转换(意味着会降低效率)。

用于转换的方法

WIN32定义了2个很强大的方法,让你将ANSI转换成UNICODE,或是将UNICODE转换成ANSI。这2个方法给你最大的灵活性。但是鉴于他们复杂的参数,稍显难用:

? MultiByteToWideChar(): Converts an ANSI string to a Unicode equivalent.
? WideCharToMultiByte(): Converts a Unicode string to an ANSI equivalent.

还有一个选择,C的运行期库提供了较为简单,方便,且跨平台的转换方法。如果你想将UNICODE(例如BSTR)字符串转换为ANSI字符串,可以调用wcstombs()方法(Wide Character String to Multibyte String):

// wcstombs( char *ANSIString, wchar_t *UNICODEString, size_t count );
char buff[MAX_LENGTH];
BSTR bstr = SysAllocString(L"How did strings get so ugly?");
wcstombs(buff, bstr, MAX_LENGTH);          // P3 = size of target buffer.
cout << buff << endl;                      // Pump to console.
SysFreeString(bstr);

如果你想将ANSI字符串转换为UNICODE,调用mbstowcs()方法(Multi Byte String to Wide Character String):

// Transform an existing char* (ANSI) into a wchar_t* (Unicode)
mbstowcs( wchar_t *UNICODEString , char *ANSIString, size_t count );

当我们从COM转移到ATL后,我们将有一整套用于转换的宏,简化字符的转换操作,忘掉之前的4个方法。同时,ATL中的CComBSTR类将我们从复杂的字符串方法中解救出来。但是现在,我们还有很长的一段路要走,也仍然要使用那些转换的方法

这篇关于BSTR数据类型的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/473853

相关文章

Rust 数据类型详解

《Rust数据类型详解》本文介绍了Rust编程语言中的标量类型和复合类型,标量类型包括整数、浮点数、布尔和字符,而复合类型则包括元组和数组,标量类型用于表示单个值,具有不同的表示和范围,本文介绍的非... 目录一、标量类型(Scalar Types)1. 整数类型(Integer Types)1.1 整数字

C 语言的基本数据类型

C 语言的基本数据类型 注:本文面向 C 语言初学者,如果你是熟手,那就不用看了。 有人问我,char、short、int、long、float、double 等这些关键字到底是什么意思,如果说他们是数据类型的话,那么为啥有这么多数据类型呢? 如果写了一句: int a; 那么执行的时候在内存中会有什么变化呢? 橡皮泥大家都玩过吧,一般你买橡皮泥的时候,店家会赠送一些模板。 上

C语言程序设计(数据类型、运算符与表达式)

一、C的数据类型 C语言提供的数据类型: 二、常量和变量 2.1常量和符号常量 在程序运行过程中,其值不能被改变的量称为常量。 常量区分为不同的类型: 程序中用#define(预处理器指令)命令行定义变量将代表常量,用一个标识符代表一个常量,称为符合常量。 2.2变量 变量代表内存中具有特定属性的一个存储单元,用来存放数据,在程序运行期间,这些值是可以 改变的。 变

Redis地理数据类型GEO

通常要计算两个地理位置的距离不是很方便,这里可以直接通过Redis提供的GEO操作来完成地理位置相关的计算 1)添加地理位置 语法:geoadd key longitude latitude member [longitude latitude member] ...字段说明:key:存放地理位置的集合名称longitude:地理坐标的经度latitude:地理坐标的纬度member:表示这

【JavaScript】基本数据类型与引用数据类型区别(及为什么String、Boolean、Number基本数据类型会有属性和方法?)

基本数据类型   JavaScript基本数据类型包括:undefined、null、number、boolean、string。基本数据类型是按值访问的,就是说我们可以操作保存在变量中的实际的值。 1)基本数据类型的值是不可变的 任何方法都无法改变一个基本类型的值,比如一个字符串: var name = "change";name.substr();//hangconsole.log

【MySQL】MySQL常用的数据类型——表的操作

前言: 🌟🌟本期讲解关于MySQL常用数据类型,表的简单使用,希望能帮到屏幕前的你。 🌈上期博客在这里:http://t.csdnimg.cn/wwaqe 🌈感兴趣的小伙伴看一看小编主页:GGBondlctrl-CSDN博客   目录 前言: 📚️1.MySQL常用的数据类型 1.1数值类型 1.2字符串类型 1.3日期类型  📚️2.表的简单操作 2.1创建

c语言(三种语言对比、数据类型及输出、变量存储、内存分配)

数据类型: 变量的输出: c语言不能直接打印数字,字符,只能将他们转化成字符串打印, printf("%d\n", num); %d 是整数占位符,将来由逗号右边的变量的值占据这个位置。(%i和%d是一样的) %f 是浮点数占位符,默认输出小数点后6位,若只想输出小数点后两位:%.2f %c 是字符型数据占位符。

SpinalHDL之数据类型(一)

本文作为SpinalHDL学习笔记第五十四篇,介绍SpinalHDL的Bool数据类型。 SpinalHDL技术交流QQ群: Note: 1.本群是个人技术交流群,不是什么官方答疑群; 2.提问是你的权利,但回答不是别人的义务; 3.可以潜水,不能灌水; 4.请文明交流,做这行的都算高层次人才,希望你有对应的高素质; 5.不强制改名,但希望统一格式:姓名(昵称也行)-公司/学校-

MySQL数据类型和Schema优化(二)

MySQL数据类型和Schema优化 MySQL合适的数据类型日期和时间类型(datetime、timesamp)整数类型实数类型(float\double\decimal)字符串类型(Varchar、Char) Schema设计缓存表和汇总表 MySQL 良好的逻辑设计与物理设计是高性能的基石,应该根据具体业务需求的查询语句来设计schema,这往往需要权衡各种因素。 比如

【R语言数据类型】深入了解 向量、矩阵、数据框、列表

R语言数据类型有向量、矩阵、数据框、列表。下面我们来深入了解下: vector 的划分 R中的vector分为两类,atomic和list,二者的区别在于,前者元素类型必须相同,后者可以不同。前者的代表是向量和矩阵,后者的代表是list和数据框。 创建向量、矩阵、数据框、列表 # atomica <- 1:5b <- letters[1:5]c <- 1:10mat <- matr