`

Delphi COM编程技术二(COM接口和COM组件)

 
阅读更多


一、类厂(Class Factory)

1、类厂的含义:

    类厂是一种组件或者对象,它就是用于创建其他对象的。COM对象不是由程序直接实例的,COM使用类厂来创建对象。每一个COM都有一个相关的类厂,负责创建在服务器中实现的COM对象;类厂把COM从实际构造一个对象的过程中分离出来,COM没有对象构造过程,所以需要使用类厂来解决创建组件时的不灵活性。

2、类厂的创建和COM组件的创建:

    COM对象的创建可以通过CoCreateInstance()函数来完成。在使用时只需将CLSID、IID等作为参数传入即可创建相应的组件并从输出参数ppv得到所请求接口的指针。如果函数是直接创建组件的,那么在函数返回时组件将创建完毕,这样客户将无法对组件的创建过程进行任何干预,灵活性太差。因此,CoCreateInstance()函数内部实现中通过调用CoGetClassObject()函数先创建一个类厂(一种专门用来创建组件的组件)来解决此问题。

1>、CoCreateInstance函数:创建CLSID相应的组件并从输出参数ppv得到所请求接口的指针
    CoCreateInstance内部创建负责创建COM对象类厂的实例,然后使用类厂来创建对象,创建完后COM对象后,类厂被销毁;如果使用CoCreateInstance函数创建了一个借口,你必须使用Release()函数释放掉它。
HRESULT __stdcall CoCreateInstace(
 const CLSID& clsid, // 要创建COM组件的CLSID
 IUnknown* pIUnknownOuter, // 用于聚合组件,如果不使用可以设置为NULL
 DWORD dwClsContext, // 限定了所创建组件的执行上下文
 const IID& iid, // COM组件中要使用的接口的IID
 void** ppv // 返回得到的接口指针
);

参数说明:

CLSID:它可唯一指定客户端需要使用的COM类。COM将使用该ID来查找可产生请求COM对象的服务器。一旦连接到服务器,将会创建该对象。
pIUnknownOuter:它指向“outer unknown”。我们不会使用这个参数,因此可以传送一个NULL。在涉及到“aggregation”(集合)概念时,outer unknown是很重要的。aggregation可让一个接口直接调用另一个COM接口而无需通知客户端。aggregation和containment是接口用来调用其它接口的两个方法。
dwClsContext:定义COM类的Context或者CLSCTX。该参数控制服务器的范围。我们可以通过它来控制服务器是进程内的服务器,还是一个EXE或者是在远程的计算机上。CLSCTX是一个位掩码,因此你可以混合几个值。(CLSCTX_INPROC_SERVER--该服务器将运行在本地的计算机,并且作为一个DLL连接到客户,进程内的服务器是最容易实现的)。
IID:请求的接口的ID。

PPV:指向一个接口的指针

2>、CoGetClassObject函数:创建类厂对象并返回类厂指针
STDAPI CoGetClassObject(
REFCLSID rclsid,
DWORD dwClsContext,
LPVOID pvReserved,
REFIID riid,
LPVOID * ppv
);

    创建类厂的CoGetClassObject()函数将接收一个CLSID作为参数并返回指向类厂对象IClassFactory接口的指针。客户将可以通过此指针来创建所需要的组件并返回某接口的指针(IUnknown接口指针)。通过此指针,客户将可以直接调用新创建的COM对象接口的成员函数,从而获得COM对象的所有服务。

3、IClassFactory接口:用于创建组件的接口

    类厂所支持IClassFactory接口,该接口从IUnknown派生,并具只定义了两个接口成员函数CreateInstance()函数和LockServer()函数。这两个成员函数分别用于创建COM组件对象和控制组件的生存期。

1>、CreateInstance成员函数:负责创建类厂涉及到的COM对象的实例,并返回IUnknown接口指针;
HRESULT __stdcall CreateInstance(IUnknown* pIUnknownOuter, const IID& iid, void** ppv);

    这个用于创建组件对象的CreateInstance()函数并未包含一个用来接受CLSID的参数,显然该函数将只能创建同某个CLSID相应的组件。而对于一个类厂,也没有其他函数用于创建组件,因此只能用CreateInstance()函数创建与某个特定CLSID(CoGetClassObject函数接受到的CLSID)相应的组件。


2>、LockServer成员函数: 控制组件的生存期,保持服务器在内存中,一般不要调用它。

二、创建类厂对象的两种情况

1、进程内的COM服务器(In-Process COM Server)

    如果COM对象是进程内组件,即组件与客户处于同一进程地址空间,通常多以DLL形式存在。CoGetClassObject()将调用DLL模块的DllGetClassObject()函数并把clsid、iid和ppv等参数传递进去以创建类厂,并返回类厂对象的接口指针。
    共性:有一个InprocServer32的子键、所有进程内服务器都输出以下四个标准函数;
1、DllRegisterServer: 2种方式自动调用IDE的Register ActiveX Server菜单

  Windows的命令行应用程序RegSvr32.exe或Boland应用程序TRegSvr
2、DllUnregisterServer: 是DllRegisterServer的逆进程,移走放在注册表中的条目;
3、DllGetClassObject: 负责给COM创建一个类厂,该类厂用语创建一个COM对象; 每个COM服务器将实现它输出的每个COM对象的类厂;
4、DllCanUnloadNow: 返回S_True,CO在内存中移走COM服务器;如果返回S_False


2、进程外COM服务器(Out-Of-Process COM Server)

    如果COM对象是进程外组件(拥有独立的进程地址空间,通常多以EXE形式实现的),则CoGetClassObject()将要首先启动组件进程,并一直等待到组件进程通过CoRegisterClassObject()函数将类厂注册到COM后,才会返回COM中相应的类厂信息。一旦组件进程退出,此注册的类厂对象也就不再有效,需调用CoRevokeClassObject()函数予以通知。

3、各类名称的含义
线程支持(Threading Support): 只适用于进程内服务器;被保存在注册表中。
Single-Thread Apartment(STA):是线程模型, 实际上根本没有线程支持,所有对COM服务器的访问由Windows顺序执行,不必考虑同步存取的问题。
Mutli-Threaded Apartment(MTA): 是线程模型,允许同时有多个线程存取COM对象,必须控制不同线程同步存取的程序代码。
Both Apartment: 可以执行在MTS或STA中;
注册服务器(registering the Server): 所有的COM服务器都需要Windows注册表来工作。
定制构造函数(Custom constructors): delphi中COM对象的基类包括一系列的非虚构造函数。 为了能够使用COM库提供的API函数,首先要用CoInitialize()初始化COM库,不要试图重载一个COM对象的构造函数;
实例化(Instancing): 创建多少个客户需要的实例;可以支持三个实例化方法中的一个;
单实例(Single Instace): 只容许一个COM对象的实例,每个需要COM对象实例的应用程序将产生COM服务器的单独拷贝;
多实例(Multiple Instance): 指COM Server可以创建一个COM对象的多个拷贝;客户请求COM对象的一个实例时,由当前运行的服务器创建COM对象的一个实例;
内部实例(Internal Only):用于不被客户应用程序使用的COM对象;
调度数据(Marshaling Data): 一个可执行的程序不能直接访问另一个可执行程序的地址空间;Windows通过调度(Marshaling)进程在调用应用程序和进程外COM服务器之间移动数据; 自动化兼容 SmallInt、Integer、Single、Double、currency、TDateTime、WideString、Idispatch、Scode、WordBool、Olevariant、IUnknown、ShortInt、Byte; 记录和数组不能自动调度;

三、总结COM组件的创建和使用过程

1、使用CLSIDFromProgID()函数,根据组件的ProgID得到组件的CLSID。

    虽然通过CLSID和ProgID都可以标识一个组件,但ProgID显然要比CLSID更易于理解和使用,因此通常很少直接使用CLSID,而是通过使用CLSIDFromProgID(),根据ProgID得到组件的CLSID。

2、调用CoGetClassObject()函数,把刚得到的CLSID作为参数去创建类厂对象并返回类厂接口指针。

3、再通过类厂接口指针调用类厂对象的CreateInstance()接口成员函数,执行结果将创建与CLSID相应的组件对象并返回IUnknown接口指针。

4、通过IUnknown接口指针的QueryInterface()成员函数取组件的其他接口指针,从而为组件提供的各种服务。
5、最后,通过Release()函数释放接口指针。

(如果使用的进程内组件,在调用CoUninitialize()函数释放COM库资源之前,应首先调用CoFreeUnusedLibraries()将其从内存卸载。由于在CoCreateInstance()函数内部实现了对CoGetClassObject()的调用。)

四、客户端和服务端的交互

1、传统的C/S模式和COM的C/S模式之间的对比

概念

传统的(C++/OOP)

COM

客户端

一个从某个服务器请求服务的程序

一个调用COM方法的程序

服务器

一个为其它程序服务的程序

一个让某个COM客户得到COM对象的程序

接口

没有

通过COM调用的一组函数的一个指示器

一个数据类型

定义了一组一起使用的方法和数据,一个对象的定义,用来实现一个或者多个COM接口,“coclass”也是

对象

一个类的实例化

一个coclass的实例化

Marshalling

没有

在客户和服务器端之间移动数据

2、COM客户端和COM服务端的交互

    在COM中,客户端程序驱动所有的事情,服务器是被动的,只响应客户的请求。这意味着对于客户的个别方法调用,COM服务器以一个同步的方式运作。
 1>、客户端的程序启动服务器
 2>、客户端请求COM对象和接口
 3>、客户端发起所有的方法调用到服务器
4>、客户端释放服务器的接口,允许服务器关闭
  这个区别是重要的。有各种不同的方法可模拟服务器到客户的调用,不过它们都难以实现,并且都相当复杂(这个被称为回叫)。通常没有客户的请求,服务器不做任何的事情。

3、一个典型的COM客户端和COM服务器之间的交互
  客户请求:

    请求访问一个特别的COM接口,特别的COM类和接口(通过GUID)
  服务器响应:

    1>、启动服务器(如果需要)。
      (如果是一个进程内的服务器,DLL将被载入。可执行的服务器将由SCM运行.)。
    2>、创建请求的COM对象。
    3>、创建到COM对象的一个接口。
    4>、增加激活接口的引用计数。
    5>、返回该接口给客户。
  客户请求 :
    调用接口的一个方法。
  服务器响应:

    执行一个COM对象的方法。
  客户请求:
    释放接口。
  服务器响应:
    减少接口引用的数目;如果引用计数为0,将会删除该COM对象;如果没有活动的连接,关闭服务器。某些服务器不会关闭自身。(如果你要了解COM,你必须使用一个以客户为中心的方法。)


分享到:
评论

相关推荐

    DELPHI 5编程实例与技巧

    本书共分三部分、16章,主要介绍Delphi 5集成开发环境,对象Pascal语言、组件、通用编程技术、动态链接库、多线程、多媒体编程、数据库编程、网络编程和Windows API编程等。 目 录 前言 第一部分 Delphi编程基础 ...

    80例上手Delphi7编程(完全版)+源码

     Delphi中的INI文件编程  删除或移动正在使用的文件  如何在Delphi中操作Excel  实现应用程序的文件拖放功能  将EXE文件转换成SWF文件  将SWF文件转换成EXE文件  文件捆绑  统计中英文字个数  06...

    Delphi 5编程实例与技巧

    第二部分 Delphi编程的核心技能 第3章 窗体和组件 53 3.1 窗体和组件 53 3.1.1 窗体 54 3.1.2 组件 56 3.1.3 在窗体中使用组件 57 3.2 文本组件 60 3.3 特殊输入组件 61 3.4 按钮及其分类组件 63 3.5 列表组件 64 ...

    Delphi技术手册

    本书还用一章的篇幅讨论了Delphi中的并发编程,以及多线程应用程序的创建。 本书的主要内容是Delphi语言以字母顺序排列的完整参考。每项参考的内容都包括: 语法,使用标准编码惯例 说明参数列表,如果函数或...

    Delphi6分布式开发

    第二篇讲述了分布式组件的实现,篇中分别讲述了DCOM架构的基元——COM的编程基础,创建DCOM客户端用& 务器应用以及COM十分布式应用的开发;第三篇讲了另一种分布式技术CORBA的原理及实现;第四篇讲多层分布式数据库...

    Delphi5开发人员指南

    第二部分 高级技术 第8章 使用GDI和字体的图像编程 167 8.1 TImage:Delphi的图像显示 167 8.2 存储图像 168 8.3 使用TCanvas的属性 169 8.3.1 画笔 170 8.3.2 使用TCanvas.Pixels属性 175 8.3.3 使用刷子 175 8.3.4...

    Delphi网络通信协议分析与应用实现pdf清晰

    1.3 网络编程接口(Winsock API) 1.4 Winsock常用函数介绍 1.4.1 基本Socket函数 1.4.2 数据库函数 1.4.3 Winsock规范提供的扩展函数 1.5 Delphi Socket网络组件介绍 1.5.1 ClientSocket组件 1.5.2 ...

    报表控件Cell组件、插件

    软件授权:共享软件/免费软件/试用软件/DEMO软件 使用平台:Win9x/Me/NT/2000/XP 电子信箱:miaofeng@cellsoft.cc 软件简介:Cell组件、插件...且提供几个百个编程接口。是软件开发人员开发完美软件的最佳解决方案。

    糖果多源多线程下载ActiveX组件

    使用糖果专业下载组件,可以使你的软件...糖果下载控件以ActiveX(ocx)方式提供编程接口,易于使用. 包含 一个多线程下载软件的VC演示工程,Delphi演示工程(含源码)和NTLM认证的VC演示工程,Delphi演示工程(含源码).

    基于单片机和delphi串行通信的步进电机控制 自动化课程设计报告

    本实验主要是基于STC89C52RC单片机和delphi串行通信的步进电机控制的设计。同时还进行了proteus仿真设计和虚拟串行通信。 本设计的主要思路是通过对DELPHI界面的控制,通过串行通信实现对单片机的控制,由单片机产生...

    KeyGenDelphi (XE2注册机).

    如果你对Web编程很熟,VCL Style就是delphi版的css,想像一下只要换一个style,所有的按钮菜单表格都换了新的颜色和风格,十分酷。XE2中自带了预定义的几种Style,用户可以添加新的并且和其他人分享。 2. 64Bit ...

    《WINDOWS网络编程技术》

    本书专门讨论Windows网络编程技术,覆盖Windows 95/98/NT 4/2000/CE平台,内容包括NetBIOS和Windows重定向器方法、Winsock方法、客户端远程访问服务器方法,本书论述深入浅出、用大量实例详解了微软网络API函数的...

    华表插件5.3.8.exe

    是第一个国产ActiveX商业组件,有300多个编程接口;Cell组件适用于Windows环境下各种开发工具(如VB,VC,Visual Foxpro,Delphi,C+Builder,PowerBuilder,.net)等。实现自定义报表、图表、公式、自定义函数、数据库...

    久其表格OCX控件(共享版)

    久其表格OCX控件V2.1是久其ezReport报表组件的核心组件之一,是基于微软COM/COM+技术开发的报表二次开发组件,可以应用于企业级的报表开发,能够实现多种复杂报表的设计、打印等操作,具有以下几个特点: 1. ...

    D5开发人员指南-02卷

    第二部分 高级技术 第8章 使用GDI和字体的图像编程 167 8.1 TImage:Delphi的图像显示 167 8.2 存储图像 168 8.3 使用TCanvas的属性 169 8.3.1 画笔 170 8.3.2 使用TCanvas.Pixels属性 175 8.3.3 使用刷子 175 8.3.4...

    Visual Graph 交互图形开发平台(组件)

     她提供功能非常强大的ActiveX组件,和其他流行的编程语言共同工作,极大地弥补了这些语言在图形处理方面的不足。 一、在电力、煤炭、化工、钢铁、安全监控软件开发中的应用  Visual Graph是专门处理交互图形的...

    ADO.Net完全攻略(PDF中文版)

    ADO组件的使用需要利用支持COM的高级语言,例如ASP中的VBScript或者Visual Basic,甚至Delphi,微软的竞争对手Borland的一个产品,现在也支持使用ADO来访问数据库。  在新的编程框架.NET Framework中, 微软也提供了...

    是全中文的一个编程语言

    “易语言汉语编程环境”成功通过国家鉴定,易语言获2004年《大连市科学技术进步奖》二等奖。 2004年易语言正式走上讲台“吉林市计算机专业骨干教师培训班”,2004年7月11日至17日,在吉林市教育局的大力支持下,应...

    ofbiz综合技术文档

    二、主要的应用组件 69 1、CommonData 70 2、Content 70 3、Security 70 4、Party 70 5、Product 71 6、Order 71 7、Facility 72 8、Shipment 72 9、Marketing 72 10、WorkEffort 73 11、HumanResources 73 12、...

Global site tag (gtag.js) - Google Analytics