上一次说到,COM为了跨语言,有一套完整的规则,只要COM组件按照规则编写,而不同的语言也按照对应的规则调用,那么就可以实现不同语言间相互调用。但是根据那套规则,只能识别接口,并调用没有参数和返回类型的接口,毕竟不同语言里面的基本数据类型不同,可能在VC++中char * 就表示字符串,而在Java或者c#中string是一个对象,二者的内存结构不同,不能简单的进行内存数据类型的强制转化。为了实现数据的正常交互,COM中又定义了一组公共的数据类型。

HRESULT类型:

在COM中接口的返回值强制定义为该类型,用于表示当前执行的状态是完成或者是出错,这个类型一般在VC中使用,别的语言在调用时根据接口的这个值来确定接下来该如何进行。
HRESULT类型的定义如下:

typedef _Return_type_success_(return >= 0) long HRESULT;

其实它就是一个32位的整数,微软将这个整数分成几个部分,各个部分都有详细的含义,这个值的详细解释在对应的winerror.h中。

//
// Note: There is a slightly modified layout for HRESULT values below,
//        after the heading "COM Error Codes".
//
// Search for "**** Available SYSTEM error codes ****" to find where to
// insert new error codes
//
//  Values are 32 bit values laid out as follows:
//
//   3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
//   1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
//  +-+-+-+-+-+---------------------+-------------------------------+
//  |S|R|C|N|r|    Facility         |               Code            |
//  +-+-+-+-+-+---------------------+-------------------------------+
//
//  where
//
//      S - Severity - indicates success/fail
//
//          0 - Success
//          1 - Fail (COERROR)
//
//      R - reserved portion of the facility code, corresponds to NT's
//              second severity bit.
//
//      C - reserved portion of the facility code, corresponds to NT's
//              C field.
//
//      N - reserved portion of the facility code. Used to indicate a
//              mapped NT status value.
//
//      r - reserved portion of the facility code. Reserved for internal
//              use. Used to indicate HRESULT values that are not status
//              values, but are instead message ids for display strings.
//
//      Facility - is the facility code
//
//      Code - is the facility's status code
//
//
// Define the facility codes
//

根据上面的注释可以看到,以及我自己查阅相关资料,它里面总共有7个部分,各个部分代表的含义如下:
S - 严重性 - 表示成功或失败0 - 成功,1 - 失败
R - 设施代码的保留部分,对应于NT的第二严重性位。1 - 严重故障
C - 第三方。 此位指定值是第三方定义还是Microsoft定义的。0 - Microsoft-定义,1 - 第三方定义
N - 保留部分设施代码。 用于指示映射的NT状态值。
X - 保留部分设施代码。 保留供内部使用。 用于指示不是状态值的HRESULT值,而是用于显示字符串的消息标识。
Facility - 表示引发错误的系统服务. 示例Facility代码如下所示:
2 - 调度(COM调度)
3 - 存储 (OLE存储)
4 - ITF (COM/OLE 接口管理)
7 - (原始 Win32 错误代码)
8 - Windows
9 - SSPI
10 - 控制
11 - CERT (客户端或服务器认证)
...
Code - 设施的状态代码
其实这些没有必要知道的很详细,只需要知道里面常用的几个即可:
S_OK:成功
S_FALSE:失败
E_NOINTERFACE:没有接口,一般是由QueryInterface或者CoCreateInterface函数返回,当我们传入的ID不对它找不到对应的接口时返回该值
E_OUTOFMEMORY:当内存不足时返回该值。
一般在COM的调用者看来,有的时候只要最高位不为0就表示成功,这个时候可能会继续使用,所以在我们自己编写组件的时候要根据具体情况选择返回值,不要错误了就返回S_FALSE,其实我们看它的定义可以知道它是等于1的,最高位为0,仍然是成功的。如果返回S_FALSE可能会造成意想不到的错误,而且还难以调试。

BSTR

COM中规定了一种通用的字符串类型BSTR,查看BSTR的定义如下:

typedef /* [wire_marshal] */ OLECHAR *BSTR;
typedef WCHAR OLECHAR;

从上面的定义上不难看出BSTR其实就是一个WCHAR ,也就是一个指向宽字符的指针。COM中使用的是UNICODE字符串,在编写COM程序的时候经常涉及到CString、WCHAR、char等的相互转化,其实本质上就是多字节字符与宽字节字符之间的转化。我们平时在进行char 与WCHAR之间转化的函数像WideCharToMultiByte和MultiByteToWideChar,以及W2A和A2W等。
COM为了方便使用,另外也提供了一组转化函数_com_util::ConvertBSTRToString以及_com_util::ConvertStringToBSTR用在在char
与BSTR之间进行转化。需要注意的是,这组函数返回的字符串是在堆上分配出来的,使用完后需要自己释放。
在BSTR类型中,定义了两个函数SysAllocString(),和SysFreeString()用来分配和释放一个BSTR的内存空间。
在这总结一下他们之间的相互转化:
char*----->BSTR: _com_util::ConvertStringToBSTR
WCHAR---->BSTR:可以直接用 = 进行赋值,也可以使用SysAllocString
BSTR---->WCHAR
:一般是直接使用等号即可,但是在WCHAR使用完之前不能释放,所以一般都是赋值给一个CString
BSTR---->char
:_com_util::ConvertBSTRToString
Convert函数是定义在头文件atlutil.h中并且需要引用comsupp.lib文件
另外COM封装了一个_bstr_t的类,使用这个类就更加方便了,它封装了与char*之间的相互转化,可以直接使用赋值符号进行相互转化,同时也不用考虑回收内存的问题,它自己会进行内存回收。

VARIANT 万能类型

现代编程语言一般有强类型的语言和弱类型的语言,强类型的像C/C++、Java这样的,必须在使用前定义变量类型,而弱类型像Python这样的可以直接定义变量而不用管它的类型,甚至可以写出像:

i = 0
i = "hello world"

这样的代码,而且不同语言中可能同一种类型的变量在内存布局上也可能不一样。解决不同语言之间变量类型的冲突,COM定义了一种万能类型——VARIANT。

typedef struct tagVARIANT VARIANT;
typedef struct tagVARIANT VARIANTARG;
struct tagVARIANT
{union {struct __tagVARIANT{VARTYPE vt;WORD wReserved1;WORD wReserved2;WORD wReserved3;union {LONGLONG llVal;LONG lVal;BYTE bVal;SHORT iVal;FLOAT fltVal;DOUBLE dblVal;VARIANT_BOOL boolVal;_VARIANT_BOOL bool;SCODE scode;CY cyVal;DATE date;BSTR bstrVal;IUnknown *punkVal;IDispatch *pdispVal;SAFEARRAY *parray;BYTE *pbVal;SHORT *piVal;LONG *plVal;LONGLONG *pllVal;FLOAT *pfltVal;DOUBLE *pdblVal;VARIANT_BOOL *pboolVal;_VARIANT_BOOL *pbool;SCODE *pscode;CY *pcyVal;DATE *pdate;BSTR *pbstrVal;IUnknown **ppunkVal;IDispatch **ppdispVal;SAFEARRAY **pparray;VARIANT *pvarVal;PVOID byref;CHAR cVal;USHORT uiVal;ULONG ulVal;ULONGLONG ullVal;INT intVal;UINT uintVal;DECIMAL *pdecVal;CHAR *pcVal;USHORT *puiVal;ULONG *pulVal;ULONGLONG *pullVal;INT *pintVal;UINT *puintVal;struct __tagBRECORD{PVOID pvRecord;IRecordInfo *pRecInfo;}    __VARIANT_NAME_4;}    __VARIANT_NAME_3;}    __VARIANT_NAME_2;DECIMAL decVal;}    __VARIANT_NAME_1;
};

从定义上看出,它其实是一个巨大的联合体,将所有C/C++的基本类型都包含进来,甚至包含了像BSTR, 这样的COM中使用的类型。它通过成员vt来表示它当前使用的是哪种类型的变量。vt的类型是一个枚举类型,详细的定义请参见MSDN。为了简化操作,COM中也对它进行了一个封装——_variant_t,该类型可以直接使用任何类型的数据对其进行初始化操作。但是在使用里面的值时还是得判断它的vt成员的值

COM中的其他操作

最后附上一张COM常用函数表以供参考:

转载于:https://www.cnblogs.com/lanuage/p/7775005.html

COM学习(四)——COM中的数据类型相关推荐

  1. 前端系统化学习【JS篇】:(四)Javascript中的数据类型

    前言 细阅此文章大概需要 3分钟\color{red}{3分钟}3分钟左右 本篇中简述\color{red}{简述}简述了: Javascript中常用的数据类型 基本数据类型 引用数据类型 数据类型 ...

  2. 论文浅尝 - CIKM2021 | DT-GCN: 一种双曲空间中的数据类型感知的知识图谱表示学习模型...

    论文作者:申雨鑫,天津大学硕士 发表会议:CIKM 2021 链接:https://dl.acm.org/doi/pdf/10.1145/3459637.3482421 动机 知识图谱表示学习旨在将实 ...

  3. LabView学习笔记(四):动态数据类型

    Labview学习笔记: LabView学习笔记(一):基础介绍 LabView学习笔记(二):滤波器实验 LabView学习笔记(三):基本控件 LabView学习笔记(四):动态数据类型 LabV ...

  4. python字典、列表、元祖使用场景_python学习第七讲,python中的数据类型,列表,元祖,字典,之元祖使用与介绍...

    python学习第七讲,python中的数据类型,列表,元祖,字典,之元祖使用与介绍 一丶元祖 1.元祖简介 元祖跟列表类似.只不过是有区别的. 如下: tuple(元祖英文) 跟列表类似, 元素不能 ...

  5. python学习第八讲,python中的数据类型,列表,元祖,字典,之字典使用与介绍

    目录 python学习第八讲,python中的数据类型,列表,元祖,字典,之字典使用与介绍.md 一丶字典 1.字典的定义 2.字典的使用. 3.字典的常用方法. python学习第八讲,python ...

  6. JVM知识体系学习四:排序规范(happens-before原则)、对象创建过程、对象的内存中存储布局、对象的大小、对象头内容、对象如何定位、对象如何分配

    文章目录 前言 零.排序规范 1.happens-before原则 2.找文档位置 一.一线互联网企业关于对象面试题: (后面回答的就是这几个问题) 二.对象创建过程 三.对象在内存中的存储布局 1. ...

  7. 软硬件学习记录5—— Verilog语言中的数据类型

    Verilog语言中的数据类型 在 Verilog 语言中,主要有三大类数据类型:寄存器数据类型.线网数据类型和参数数据类型. 1.寄存器类型 reg 1.1 概述: 寄存器数据类型的关键字是 reg ...

  8. 3、java中的数据类型和运算符

    数据类型 数据类型是对数据存储在内存中位置的一种抽象表示,java的数据类型总体上分为两大类:基本数据类型和引用数据类型. 1.基本数据类型 基本数据类型是语言本身定义的,数据结构上有说基本数据类型表 ...

  9. [转载] Java内存管理-你真的理解Java中的数据类型吗(十)

    参考链接: Java中的字符串类String 1 做一个积极的人 编码.改bug.提升自己 我有一个乐园,面向编程,春暖花开! 推荐阅读 第一季 0.Java的线程安全.单例模式.JVM内存结构等知识 ...

  10. (转)SpringMVC学习(四)——Spring、MyBatis和SpringMVC的整合

    http://blog.csdn.net/yerenyuan_pku/article/details/72231763 之前我整合了Spring和MyBatis这两个框架,不会的可以看我的文章MyBa ...

最新文章

  1. cocos2dx 3.x(动态改变精灵的背景图片)
  2. nagios配置文档
  3. expect自动化交互脚本(一)
  4. 文巾解题 1418. 点菜展示表
  5. 2019款iPhone XR新配色机模上手:就是这个味儿
  6. GRT上线Bancor提案已通过
  7. 微信JS图片上传与下载功能--微信JS系列文章(三)
  8. 如何编辑已存在的.fig文件
  9. 生活中的逻辑谬误01.诉诸纯洁
  10. 网友上海求职指南2007
  11. python 典型相关分析_Canonical Correlation Analysis 典型相关分析
  12. are in unnamed module of loader ‘app‘)“ }
  13. el-table表格某列添加icon图标
  14. Python爬虫实战:爬取YY上漂亮小姐姐视频
  15. 推荐五个常用的免费图片素材下载网站
  16. gitee配置流水线实现自动打包vue
  17. Pixie: A System for Recommending 3+ Billion Items to 200+ Million Users in Real-Time简介
  18. 云计算除了具有极高的市场效益外,简化企业IT运营、内置安全和易于部署等优势非常明显
  19. (详细)安装nvidia专有驱动并且正确配置,arch linux + lightdm + deepin desktop
  20. JavaScript主要作用是什么?

热门文章

  1. java生成点阵图_Android从SD卡读取图片并显示为点阵图
  2. mac 上mysql怎么卸载不了_mac上mysql怎么卸载不了
  3. javapythonc就业人数比例_P100 统计各年龄段的人数
  4. java方法分为类方法和_— Must we finish copying all these articles this morning? — No, you( )._学小易找答案...
  5. python连接数据库必须要提供用户名和密码_5.9---python连接数据库实现登录注册
  6. “21天好习惯”第一期-21
  7. 腾讯通如何修改服务器,rtx如何设置服务器地址
  8. mysql 导入导出 csv_mysql文件导入导出为csv格式
  9. c语言程序设计删除,C程序设计语言练习1-23 编写一个删除C语言程序中所有的注释语句...
  10. oracle宣传片,会声会影X8震撼的宣传片效果该怎么制作?