com组件接口
int
main(
int
argc,
char
*argv[] )
{
cout <<
"Initializing COM"
<< endl;
if
( FAILED( CoInitialize( NULL )))
{
cout <<
"Unable to initialize COM"
<< endl;
return
-1;
}
ISampleMath* pSampleMath;
HRESULT
hr;
// This time use CoCreateInstance
hr = CoCreateInstance( CLSID_SampleMath,
NULL,
CLSCTX_LOCAL_SERVER,
IID_ISampleMath,
(
void
**) &pSampleMath );
if
( FAILED( hr ))
{
cout <<
"Failed to create server instance. HR = "
<< hr << endl;
CoUninitialize();
return
-1;
}
// Access the IMath interface
long
lResult;
pSampleMath->Add( 134, 353, &lResult );
cout <<
"134 + 353 = "
<< lResult << endl;
// Release all of our interfaces
if
( pSampleMath )
CoUninitialize();
return
0;
}
COM组件可以是一个Dll(进程内组件),也可以是一个EXE(进程外组件)。进程内组件就是组件和客户程序在同一进程内,进程外组件即组件和客户程序分别有自己的进程空间。
一个COM组件可以包含多个COM对象,一个COM对象又可以有多个接口。
第2章 COM对象和接口
2.1 CLSID和IID
对于COM对象来说,接口是它与外界进行交互的唯一途径。
每个COM对象,可以用CLSID来标识,COM对象的每个接口可以用IID来标识。CLSID和IID都是128位的标识符GUID,是一个随机数,可以由两方面特性来保证:空间(如网络适配器地址)和时间。
GUID可以通过COM库的API函数生成:
HRESULT CoCreateGuid( GUID * pguid );
2.1.2 COM对象和C++对象的不同
COM对象的数据成员封装以组建模块为最终边界,对于对象用户是完全透明的、不可见的,用户必须通过接口方法来访问数据成员;C++对象的封装特性只是语义上的,用户可以直接看到数据成员。
2.2 COM接口结构
接口是包含了一组函数的数据结构。客户程序利用这些函数获得组件对象的服务。接口成员函数中的字符串变量必须使用Unicode字符指针。
客户程序用一个指向接口数据结构的指针来调用接口成员函数,接口指针又指向pVtable(指向vtable的指针),pVtable指向一组函数,称为接口函数表(虚函数表vtable),表中每一项为4个字节长的函数指针,每个函数指针再指向函数的具体实现。
2.2.2 接口描述语言IDL
2.3 IUnknown接口
COM定义的每个接口都必须从IUnknown接口继承过来,因为IUnknown接口提供了两个重要特性:生存期控制和接口查询。
QueryInterface用于查询COM对象的其他接口指针,AddRef和Release用于对引用计数进行操作。
在COM对象级实现引用计数,精细度比较合适。
2.3.1 使用引用计数规则
(1)函数的参数中使用接口指针变量。
输入参数:在被调用函数中,不必调用AddRef和Release函数。
输出函数:在被调用函数返回之前,对输出参数调用AddRef,增加引用计数。
输入-输出参数:在参数被修改之前,对原来传进来的接口指针调用Release,引用计数减1,在参数被修改之后,对新的接口指针变量指针调用AddRef,若在函数执行过程中,参数没有被修改,则不必调用AddRef和Release函数。
(2)局部接口指针变量。
COM的实现
3.1 进程内组件(DLL)的实现,可以参考DLL技术,主要参数为:
1)LoadLibrary:装载DLL模块
2)GetProcAddress:取引出函数的地址
3)FreeLibrary:释放DLL模块
COM采用LPC(本地过程调用)和RPC(远程过程调用)的方法进行进程之间的通信,LPC用于在同一机器上的不同进程之间进行通信,而RPC用于在不同机器上的进程之间进行通信。
3.2 组件程序的两个用于注册的入口函数为DllRegisterServer和DllUnregisterServer,注册组件使用命令:RegSvr32 *.dll;反注册组件使用命令:RegSvr32 /u *.dll,进程内组件注册使用此命令。进程外组件注册必须支持两个命令行参数/RegServer 和/UnregServer。
3.3 类厂
COM库通过类厂创建COM对象,对应每一个COM类,都有一个类厂专门用于该COM类的对象创建工作。类厂本身也是一个COM对象,它支持接口IClassFactory。
CreateInstance创建对应的COM对象,LockServer控制组件的生存周期。
类厂由函数DllGetClassObject创建。
DllGetClassObject返回类厂对象的接口指针,再通过CreateInstance创建对应的COM对象。
3.3.2 COM库与类厂的交互
创建对象函数:
1)若创建远程对象或希望一次获取对象的多个接口指针,选用CoCreateInstanceEx。
2)若希望获取类厂对象或要调用类厂的某些成员函数,选用CoGetClassObject,通常IID=IID_IclassFactory,进程内组件直接调用DLL的CoGetClassObject,若CoGetClassObject创建的类厂对象位于进程外组件,函数启动组件进程,然后等待,直到组件进程把它支持的COM类对象的类厂注册到COM中,返回类厂信息。
3)其他情况下,选用CoCreateInstance创建对象,CoCreateInstance封装类厂创建对象的过程,返回COM对象的接口指针,不能创建远程机器上的对象。
3.4 COM库
COM库初始化函数:CoInitialize
COM库终止函数:CoUninitialize
3.4.2 COM库的内存管理
COM提供的内存管理器标准,是一个COM接口IMalloc。当组件内存的分配和释放不在同一模块,需要用到内存管理器,COM库封装了三个API函数,用于内存分配和释放
CoTaskMemAlloc
CoTaskMemFree
CoTaskMemRealloc
3.4.3 组件程序的装载和卸载
1)进程内组件的装载、卸载
2)进程外组件的装载、卸载
组件程序满足两个条件才可以被卸载:组件中对象数为0;类厂的锁计数器为0。此时,DllCanUnloadNow返回TRUE。
在判断返回类型HRESULT时,需用宏SUCCEEDED和FAILED。
com组件接口的更多相关文章
- 组件接口(API)设计指南-文件夹
组件接口(API)设计指南-文件夹 组件接口(API)设计指南[1]-要考虑的问题 组件接口(API)设计指南[2]-类接口(class interface) 组件接口(API)设计指南[3]-托付( ...
- django rest framework 解析器组件 接口设计,视图组件 (1)
一.解析器组件 -解析器组件是用来解析用户请求数据的(application/json), content-type 将客户端发来的json数据进行解析 -必须适应APIView -request.d ...
- 组件接口(API)设计指南[4]-通知(Notifications)
*返回文件夹阅读其它章节: http://blog.csdn.net/cuibo1123/article/details/39894477 通知(Notifications) 通知是托付协议的还有一半 ...
- 组件接口(API)设计指南[2]-类接口(class interface)
*返回文件夹阅读其它章节: http://blog.csdn.net/cuibo1123/article/details/39894477 类接口(class interface) 你能够參考MGTi ...
- django rest framework 解析器组件 接口设计,视图组件 (2)
1. 使用视图组件进行接口优化 1.1 使用视图组件的mixin进行接口逻辑优化 - 导入mixin from rest_framework.mixinx import ( ListModelMix, ...
- 组件接口(API)设计指南[5]-最后的思考
*阅读其它章节: http://blog.csdn.net/cuibo1123/article/details/39894477 最后的思考 我通过困难的学习以及多年的失误.写了这片篇关于创建组件和a ...
- php jsonp实例 mip无限滚动组件接口注意事项
在改造mip的过程中,很多同学遇到这样一个问题.mip无限滚动问题 异步请求数据接口(仅支持 JSONP 请求) 异步请求接口需要规范 callback 为 'callback' 那么什么是JSONP ...
- PeopleCode事件和方法只用于online界面不能用于组件接口(component interface)
在使用CI过程中,哪些方法是不能使用的.以下为PeopleBook解释的内容. 一.搜索框代码不执行:SearchInit, SearchSave, and RowSelect events 意味着使 ...
- COM组件 IDispatch 及双接口的调用
转自:http://blog.csdn.net/cnhk1225/article/details/50555647 一.前言 前段时间,由于工作比较忙,没有能及时地写作.其间收到了很多网友的来信询问和 ...
随机推荐
- GitHub上不错的Android开源项目(三)
收集相关系列资料,自己用作参考,练习和实践.小伙伴们,总有一天,你也能写出 Niubility 的 Android App :-) GitHub上不错的Android开源项目(一):http://ww ...
- ASP.Net UpdatePanel控件(转)
Asp.net UpdatePanel 允许用户构建一个丰富的,以客户端为中心的应用程序,引用UpdatePanel控件,能够实现页面的部分刷新,一个包含scriptManage和 UpdateP ...
- MSDN资料
http://www.microsoft.com/china/msdn/events/webcasts/shared/webcast/Series.aspx http://www.microsoft. ...
- 泰信---->20131025~20131101(周计划安排)
学习java相关知识计划安排: [前期复习阶段] (一)熟悉java相关语言基础. (二)搭建一个纯web项目工程,实现增加,删除,修改,查询以及分页...功能. (三)熟悉jboss的使用和相关配置 ...
- php笔记[2]
strlen()函数获得字符窜的长度 读取文件:fgets(),fgetss()和fgetcsv() 读取整个文件:readfile(),fpassthru()和file() 读取一个字符:fgetc ...
- Java编程思想学习笔记_2(继承和多态)
静态初始化: 静态初始化只在必要的时刻进行.(即当程序需要加载类进入内存的时候,执行静态初始化.静态变量和静态代码块的初始化顺序,按照在代码中声明的顺序老执行.例如:如果要执行某个public类,那么 ...
- swift语言学习之UITableView分割线左边到头的解决
此方法兼容ios 7.8.9 // 在tableView创建地方设置 if tableView!.respondsToSelector("setSeparatorInset:") ...
- bignum 大数模板
今天无意间看到一个很好的大数模板,能算加.减.乘.除等基本运算,但操作减法的时候只能大数减小数,也不支持负数,如果是两个负数的话去掉符号相加之后再取反就可以了,一正一负比较绝对值大小,然后相减.我借用 ...
- centos用户权限设置
了解常见的账号配置文件 学会管理用户账号.组账号 学会设置目录或文件的权限 学会设置目录或文件的归属 用户账号文件/etc/passwd :保存用户名称.宿主目录.登录shall等基本信息 每一行 ...
- D3.js 坐标轴
坐标轴,是可视化图表中经常出现的一种图形,由一些列线段和刻度组成.坐标轴在 SVG 中是没有现成的图形元素的,需要用其他的元素组合构成. D3 提供了坐标轴的组件,如此在 SVG 画布中绘制坐标轴变得 ...