现在的位置: 首页 > 综合 > 正文

COM学习-COM基础

2013年06月21日 ⁄ 综合 ⁄ 共 2015字 ⁄ 字号 评论关闭

       COM语言无关性:COM是一种跨应用和语言共享二进制代码的方法,编写组件对象所使用的语言与编写客户程序使用的语言可以不同,只要它们都能够生成符合COM规范的可执行二进制代码即可。COM明确指出二进制模块必须被编译成与指定的结构匹配。这个标准也确切规定了在内存中如何组织COM对象。COM定义的二进制标准还必须独立于任何编程语言(如C++中的命名修饰)。一旦满足了这些条件,就可以轻松地从任何编程语言中存取这些模块。由编译器负责所产生的二进制代码与标准兼容。这样使后来的人就能更容易地使用这些二进制代码。

 

COM接口指的是逻辑上一组函数的集合。一个COM组件对象可以包含多个COM接口,但必须至少实现一个COM接口,这个COM组件对象才有存在的必要性。客户与COM对象打交道实际上是利用接口所提供的服务。

 

COM对象可以代替传统的API函数接口,API函数存在一些问题,如当API函数较多时,使用会非常不方便,需要对函数进行组织。API函数需要标准化,按照统一的调用方式进行处理。

 

任何COM接口都必须从IUnknown继承过来,是因为IUnknown提供了两个重要的特性:生存期控制和接口查询。

IUnknown 有三个方法:

l        AddRef() —— 通知COM对象增加它的引用计数。如果你进行了一次接口指针的拷贝,就必须调用一次这个方法,并且原始的值和拷贝的值两者都要用到。在本文的例子中没有用到AddRef()方法;

l        Release() —— 通知COM对象减少它的引用计数。参见前面的Release()示例代码段;

l        QueryInterface() —— COM对象请求一个接口指针。当coclass实现一个以上的接口时,就要用到这个方法。

 

COM是如何实现的?以及如何调用COM组件是下面要讲述的内容。

 

进程内组件和客户程序运行的是同一个地址空间,效率较高。对于进程内组件采用的是DLL动态链接库的形式,编程方法如下:

extern “C” int _stdcall MyFunction(int n)_stdcall调用习惯

def文件中

EXPORTS

       MyFunction

或者不定义def文件直接声明:

extern “C”  _declspec int _stdcall MyFunction(int n)

在客户程序一般可以用三个函数来调用,LoadLibrary,加载动态库,取出函数地址GetProcAddress,释放DLL程序的函数FreeLibrary

hModual = LoadLibrary(“Diccomp.dll”);

if(hModual == NULL) return;

typedef BOOL(_stdcall *MyFunctionType)(const CLSID& clisid, const IID& iid, void **pv)

MyFunctionType fnCreateObject;

fnCreateObject = (MyFunctionType)GetProcAddress(hModual,”CreateObject”);

fnCreateObject(clisd,iid,ppv);

FreeLibrary(hModual);

 

进程外组件存在两个问题,一个进程如何调用另外一个进程中的函数,参数如何从一个进程传递到另外一个进程,COM采用了本地过程调用LPC和远程过程调用RPC来实现进程之间的通信。

比如说应用程序A调用系统服务f,而f是在另外一个进程中实现的。应用A实际上调用系统模块DLL,称之为存根模块,存根模块中把应用请求通过LPC的方式调用了进程B的服务f,当f完成后,通过LPC的方式把结果信息返回到存根DLL中,最后由存根DLL返回到A。在这个过程中还存在参数列集合散集的过程。

 

客户程序通过COM库来完成对象的创建工作,COM库通过系统注册表所提供的信息进行组件的创建工作。可以通过调用组件程序中的DLlRegisterServerDllUnRegisterServer函数完成组件程序的注册和注销操作。

 

类厂就是COM类的工厂,COM库通过类厂来创建COM对象。对应每一个COM类有一个类厂专门对应于该COM类的对象创建操作。类厂本身也是一个COM对象,支持一个特殊的接口:CreateInstance

类厂又是被谁所调用和创建的呢?是DllGetClassObject函数,不是COM库的函数,是组件程序实现的引出函数。由该函数创建类厂对象,返回类厂对象的指针,由类厂对象的指针来创建COM对象。

CoCreateInstance函数隐藏了类厂的创建过程,主要的过程是调用CoGetClassObject函数负责在注册表中查找COM服务器的位置,此函数找到DLL程序调用DllGetClassObject函数,此函数创建类厂对象,然后类厂对象创建COM对象。

 

抱歉!评论已关闭.