在COM中使用数组参数--概述

原创 2003年07月15日 16:15:00

COM中使用数组参数-概述

关键字:DCOM、数组、自定义类型、MarshalSafeArrayICollection

 <?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

本文讲述在COM的接口中使用数组作为参数的三种方法。它们分别是:数组指针、SafeArrayICollection。文章分析了各种方法的优缺点。本文的目的不是描述COM的基本原理和开发方法。为了能够更好的理解本文中的内容,读者需要具备基本的COM编程知识。

1      相关的基本概念

COM中,如果对接口中方法的调用是跨套间的,就必须对所进行的调用进行序列化。序列化哪康氖鞘沟饔媚芄辉谡返奶准渲蟹⑸1疚牟淮蛩阆晗该枋鎏准浜托蛄谢睦砺郏龆砸婕暗降囊恍└拍罱兴得鳌?lt;/SPAN>

1.1     套间(Apartment)

在一个进程中可以包含多个套间,每个套间可以包含一个或多个线程[1]。包含单个线程的套间叫做单线程套间;包含多个线程的套间叫做多线程套间。在一个进程中最多可以包含一个多线程套间,但可以拥有0或多个单线程套间。每个使用COM的线程,无论是客户程序还是COM程序都要通过调用CoInitializeCoInitializeEx函数进入套间,同时确定所在套间的类型。在进入套间之前不能使用COM功能,否则会导致错误结果。

1.2     序列化(Marshal)

COM架构中调用者和被调用者如果在不同的套间,就不可以直接调用,而必须通过代理(Proxy)和占位(Stub)程序调用。代理程序和调用者在同一个套间中,而占位程序和被调用者在同一个套间中。代理程序模仿COM组件的行为,接受调用,而占位程序模仿调用者的行为发出调用。这样就可以保证调用是在同一个套间中进行了。代理和占位程序之间通过特定的网络通讯协议传递被调用的方法、参数和返回值。把调用转换成网络协议的过程叫做序列化(Marshal)。由于涉及到指针或数组类型的传递地址型的参数,序列化过程非常复杂,幸好我们有简单的方法可以生成效率还算不错的代理和占位程序。

对于指针类型,具体的指针地址是不重要的,关键是指针指向的内存中的数据。所以在传递指针类型的参数时,必须传递所指向的数据。对于数组类型数据也有类似的情况。如果存在双重或多重指针,情况就会变得更加复杂。

例如long*类型的参数。在序列化的时候代理程序把参数所指向的长整型值传递给占位程序,占位程序要为参数申请内存,然后把长整型的值存放到申请到的内存中,使用这个新的内存地址作为参数调用目标函数。在函数返回的时候,内存中的数据变化被占位程序传递回代理程序。代理程序把数据复制回调用者的内存,然后返回。如果指针所指向的数据不是单个的值,而是一块不定大小的内存,序列化时就要确定所要传递数据的长度。另外,在多重指针的情况下,要传递的就不是一块数据,而可能是多块数据段了。

在后面的讨论中,我们会详细地说明如何生成正确的代理和占位程序。

1.3     代理(Proxy)和存根(Stub)

COM通过代理和存根实现序列化功能。每个可能跨套间调用的接口都必须有相应的代理和存根程序。代理和存根程序是在同一个动态连接库中的。每个COM接口的设计者负责实现自己的代理和存根程序。一般情况下,代理和存根程序的代码可以通过一个叫做MIDL的工具自动生成的,我们要做的只是把它编译出来。

代理和存根的工作方式如下图:

<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" />CSDN_Dev_Image_2003-7-151603580.wmz

代理的作用是在客户套间中“伪装”成COM对象,供客户程序调用。而存根的作用则是在COM对象所在的套间中“伪装”成客户程序,发出调用请求。代理和存根之间通过网络协议[2]交换调用请求和返回结果。

 

2      概述

COM中使用数组可以使用三种方法:数组指针、SafeArrayICollection。数组指针和我们熟悉的C/C++程序中传递数组的方法是相同的、SafeArrayVB中标准的存放数组的方法,也是Automation中的标准方法、ICollection方法是通过一个独立的COM对象传递数据。这三种方法各有优缺点,应该按照具体的需求决定使用哪种方法。

2.1     数组指针

数组指针是标准的C/C++中的数组参数传递方式。数组指针实际上就是数组元素序列化存放时的首地址。数组指针的操作非常简单,所以也是效率最高的传递方式。但是,这种方式不能够在VB中使用。数组指针可以传递一维数组,也可以传递多维数组。如果COM的客户端是VC++程序的话,这是最好的传递方式。

数组指针作为跨套间的调用参数时,需要进行marshal。所以,应该编译和注册proxy/stub

2.2     SafeArray

SafeArray是标准的VB数组存放方式。和数组指针类似,SafeArray可以传递一维数组,也可以传递多维数组。由于SafeArray具有比数组指针更复杂的结构,所以,编程比使用数组指针复杂[3],程序运行效率也相对较低。

使用SafeArray方式传递的数组,可以从VB程序中调用,也可以从VC++程序中调用。而且,由于SafeArrayAutomation的标准数据,所以可以通过缺省的基于TLBproxy/stub进行跨套间的调用,而不必编译和注册自己的proxy/stub

2.3     ICollection

ICollection方式是最复杂,也是使用最广泛的。ICollection并不是一个接口的名称,而是指实现了枚举器和索引属性的IDispatch接口。这种数组传递方式的特点是自己实现数组对象,所以有最大的灵活性,可以实现按需生成数组元素等高级功能。

ICollection所传递的数组对象不再是普通的指针或特定的结构,而是一个独立的COM对象。由于传递的是接口,所以参数具有面向对象的多态性特征,就是说数组元素可以是自己实现的,也可以是其他人实现的,只要是实现了有特定属性的IDispatch接口就可以作为参数。另一方面,由于用作数组的COM对象可以单独设计,所以,可以使用更加合理的实现方式,例如使用列表、hash表或平衡树等方式实现。

有的数组实现,只需要访问少数的几个元素,或者元素个数理论上是无穷的,或者每个数组元素的生成需要耗费大量的资源。这时,应该使用ICollection方式实现数组传递。

3      各种方法的比较

 

数组指针

SafeArray

ICollection

代码量

较少

兼容Automation

不兼容

兼容

兼容

开发工具

VC++

VC++/VB

VC++

可重用性

按需生成元素

不可

不可

模型设计难度

容易

容易

程序运行速度

较慢

根据实际情况分析

分布式应用

RPC

RPC

RPC或对象复制

设计灵活性

尚可

尚可

 


[1] 最新的COM标准中,某些线程可能会跨越套间,这里不讨论这种情况。

[2] 实际上基于在远程过程调用协议(RPC)的一种协议。

[3] 指用VC++编程,如果用VB实现COM,这是唯一的传递方式。

java通过jacob实现对com组件的调用

项目中涉及到与第三方系统对接,我们项目是java的,对方项目提供的接口是c#的,根据网上的一些信息我们可以知道java调用com组件有一套解决方案那就是jni,另外还有一个开源的jar包,对jni的封...
  • u013151822
  • u013151822
  • 2013年12月14日 13:23
  • 3548

COM接口所支持的数据类型 、IDL中简单参数传递

下面的文章对IDL中简单参数传递基本介绍到了, 包括自定义结构、数组、字符串、枚举等。仔细看看吧。 一、COM接口所支持的数据类型 表一:各种语言平台支持的数据类型的比较 ...
  • aasmfox
  • aasmfox
  • 2014年08月16日 19:49
  • 3774

C++ STL list介绍与使用方法

list(链表)链表也即链式表,在数据结构中,我们知道线性表的物理存储结构有两种,顺序表(数组)和链式表(结点)。链表是在堆中为每一个元素分配内存,然后利用指针将所有元素串起来。根据这种物理存储结构,...
  • Cypress1010
  • Cypress1010
  • 2016年12月15日 13:34
  • 1627

关于《在COM中使用数组参数》的提醒

网文《在COM中使用数组参数》被广为转载,下面就是其中一个:http://blog.csdn.net/wcyoot/article/details/6562620 。 该文讲述在COM的接口中使用数...
  • brookindut
  • brookindut
  • 2011年12月03日 16:19
  • 349

在COM中使用数组参数-SafeArray(转自http://dev.csdn.net/article/19/19696.shtm)

在COM中使用数组参数-SafeArray关键字:DCOM、数组、自定义类型、Marshal、SafeArray、ICollection1      使用SafeArraySafeArray是VB中的...
  • sun_star221
  • sun_star221
  • 2011年05月17日 16:05
  • 360

在COM中使用数组参数-SafeArray

在COM中使用数组参数-SafeArray 关键字:DCOM、数组、自定义类型、Marshal、SafeArray、ICollection 1      使用SafeArray SafeAr...
  • sunnylion1982
  • sunnylion1982
  • 2012年12月19日 15:06
  • 802

在COM中使用数组参数-SafeArray

转载于: http://www.7880.com/Info/Article-5208abe0.html 在COM中使用数组参数-SafeArray 关键字:DCOM、数组、自定义类型、Marshal...
  • CCCstudyer
  • CCCstudyer
  • 2013年11月22日 10:50
  • 705

在COM中使用数组参数

关键字:DCOM、数组、自定义类型、Marshal、SafeArray、ICollection  本文讲述在COM的接口中使用数组作为参数的三种方法。它们分别是:数组指针、SafeArray和ICol...
  • wcyoot
  • wcyoot
  • 2011年06月23日 09:40
  • 4866

Variant输入出参数,ocx传递byte数组,safearray使用方法,vc写ocx在vb下调用

  • 2009年05月26日 11:37
  • 2.17MB
  • 下载

COM组件返回二维数组供javascript和客户端使用

COM组件中的主要代码 STDMETHODIMP CHcdpJiraAdapter::GetResult(VARIANT* pvarData) { // TODO:  在此添加实现代码 CCom...
  • qq1134993111
  • qq1134993111
  • 2015年08月03日 22:44
  • 491
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:在COM中使用数组参数--概述
举报原因:
原因补充:

(最多只允许输入30个字)