您的位置:首页 > 其它

COM组件开发笔记--字符串数组的传递

2013-03-18 17:14 615 查看
COM编程的好处就是可以跨语言,我们公司是用C#做开发的,所以用C++去开发COM组件就可以弥补图形渲染性能上的不足。但COM组件也有它的缺点,就是COM接口本身的调用开销比较大,所以我总结了,使用COM组件最好是通过最少次数的接口调用来达到目的。所以数组的传递就至关重要了。打个最简单的比方,调10000次SetX(
double x )花的时间肯定要比一次性把x数组传进去SetX( double[] x )多的多。

普通的值类型数组比如int[],short[]什么的,这个都好说,COM里都有对应的类型(VTS_PI4 VTS_PI2),而且就算是在C#里也可以用Marshal来分配非托管数组然后传递到COM里去进行操作。但字符串数组不同,它每一项长度都不一样,这给传递带来了一些困难。所以今天主要就说说字符串数组的传递。

在COM里数组传递要用到一个叫做SAFEARRAY的东东包装一下。但是如果直接用SAFEARRAY进行传递,那么到C#里面的参数类型是IntPtr,还是一个指针,这样就给数据的获取带来不便。后来发现数组传递之前还要用VARIANT这个数据结构把SAFEARRAY再次包装一下,这样数据传到C#里后参数类型是Object,只需要用String[]强转一下就OK了,十分方便。其实我这段描述百度百科里好像也说的挺明白的,可以参考一下:http://baike.baidu.com/view/1907445.htm

我们可以这样理解,SAFEARRAY就是存放数据的数组,而VARIANT就是一个壳子,就好比C#里装箱的概念一样,把变量变成Object后传递起来会方便一些。说的够多了,下面直接用代码举例了。

首先,如果数组是传入参数的话,调度声明中需要用VTS_VARIANT,函数原型声明中类型是VARIANT*;如果是返回值的话调度声明要用VT_VARIANT,函数原型声明类型是VARIANT(注意不是VARIANT*,和传入参数有点不同,否则到C#里参数类型不是Object而是IntPtr);然后主要说下数组的构造和包装。

VARIANT AryWarp;

VariantInit( &AryWarp );

AryWarp.vt = VT_ARRAY | VT_BSTR;
// 指定壳子是用来包装数组的,并且是字符串数组,注意COM里面字符串就是BSTR,其实就是宽字符串

SAFEARRAY* psa;

SAFEARRAYBOUND bounds = { 10, 0 };

psa = SafeArrayCreate( VT_BSTR, 1, &bounds ); // 这里就是初始化一个长度为10的字符串数组

然后声明一个字符串数组 BSTR* bstrArray; 并且用SafeArrayAccessData将psa与bstrArray进行绑定(不知道绑定这个词合适不合适,反正给我的感觉就是绑定),然后要做的就是对bstrArray[
i ]赋值了,赋值完毕后记得用SafeArrayUnaccessData解除绑定。

最后一步就是包壳子了,
AryWarp.parray = psa; 然后就可以把AryWarp return了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: