COM学习笔记(二)

一个简单COM的应用开发

实例中为一个动态链接库文件,需要导出一系列函数:

extern “C”  HRESULT __stdcall DllCanUnloadNow(void)
extern “C”  HRESULT __stdcallDllRegisterServer()
extern “C”  HRESULT __stdcallDllUnRegisterServer()
extern “C”  HRESULT __stdcallDllGetObject(const CLSID &,const IID &,void **)

COM服务端开发

流程如下:

1)   分配一个对象签名标识符CLSID,提供组件模块与CLSID之间的映射

2)   对于每个接口CLSID,均需实现一个类工厂(继承自IClassFactory接口),用于组件的内存分配及接口指针的路由(CreateInstance)

3)   在类工厂中暴露实现的接口以便于COM服务器在装载dll后能及时定位到对应的接口

4)   当没有对象引用或调对象无锁时,调用类工厂卸载该COM模块。(LockServer)

5)   开发具体业务接口(继承自IUnknown接口),在开发过程中只能使用上述内存分配函数

6)   进行注册表的注册,将接口参数写入注册表

7)   COM为一个dll,需要提供处理导出函数

8)   调用命令regsvr32来注册dll形式的COM

Windows中CLSID保存在注册表中(Win7中32/64位COM注册表分开保存至不同的路径),如:

CLSID

{54BF6567-1007-11D1-B0AA-444553540000}= Dictionary Component,在该键值下面又有其它一些项:

服务项

子键名称

含义

同一进程

InprocServer32

COM组件dll形式的路径名

本地机器的不同进程

LocalServer32

COM组件exe形式的路径名

同一进程对象句柄

InprocHandler32

将服务端的对象在客户端中重建但又不完全本地化,主要用于性能优化

COM 客户端开发:

COM客户端开发比较简单,包含COM服务端的接口,通过调用系统提供的API来获取接口指针,并通过QueryInterface函数来实现接口之间的跳转。步骤如下:

1.   初始化COM库,启动模式

2.   调用CoCreateInstance,QueryInterface获取接口指针

3.   调用接口方法

4.   卸载COM库

COM的调用流程

实例调用流程如下:

1.   客户端CoCreateInstance创建指定CLSID组件

2.   系统通过查找注册表找到指定COM dll,并调用LoadLibrary装载至内存,调用导出函数DllGetObject获取接口指针

3.   DllGetObject方法创建类厂并返回至CoGetClassObject,继续返回至CoCreateInstance函数

4.   CoCreateInstance函数得到类厂后,调用类厂对象创建函数

5.   类厂创建COM对象,向CoCreateInstance返回对象指针

6.   客户端获取对象指针,访问接口方法

CoCreateInstance方法源码如下(来自COM标准文档):

HRESULT CoCreateInstance(REFCLSID clsid, IUnknown * pUnkOuter,
	DWORD grfContext, REFIID iid, void * ppvObj)
	{
	IClassFactory * pCF;
	HRESULT         hr;

	hr=CoGetClassObject(clsid, grfContext, NULL, IID_IClassFactory, (void *)pCF);

	if (FAILED(hr))
		return hr;

	hr=pCF->CreateInstance(pUnkOuter, iid, (void *)ppv);
	pCF->Release();

	/*
	 * If CreateInstance fails, ppv will be set to NULL. Otherwise
	 * ppv has the interface pointer and hr contains NOERROR.
	 */
	return hr;
	}
COM调试工具

由于实例为dll,这里采用的工具为DumpBin来查看dll导出符号是否成功(VS2010命令行启动dumpbin /EXPORTS  dll路径名)

通过设置命令行(vs2010)进行断点调试:

项目->DictComp 属性页 -> 调试 -> 命令:Regsvr32;命令参数: /u $(TargetPath)

具体源码见  这里

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值