COM组件开发笔记--字符串数组的传递
2013-12-09 15:33
204 查看
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了。
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了。
相关文章推荐
- COM组件开发笔记--字符串数组的传递
- COM组件开发笔记--字符串数组的传递
- COM组件,字符串数组的传递
- Android-NDK开发之第三个例子--传递字符串数组和中文乱码问题
- php开发笔记(七)用数组函数实现生成随机字符串
- iphone开发笔记——与c#中split一样的将字符串按特定字符分割成数组
- Android-NDK开发之第三个例子--传递字符串数组和中文乱码问题
- iOS开发-- 如何把字符串数组从 Swift 传递给 C
- SQLServer-存储过程中使用字符串和分隔符实现传递数组参数
- IOS开发中 字符串和数组NSString NSArray操作
- 把javascript,vbscript中得数组传递给COM组件(or Activex)
- 1119数组 二维数组 字符串处理函数 值传递和变量存储类型知识点
- 我的开发笔记---UILabel根据字符串来自适应大小
- <C#入门经典>学习笔记之结构、数组及字符串
- js前台传递json字符串数组到后台有后台转换成list集合或其他格式的问题解决
- c笔记09---字符数组及字符串,预处理,宏,条件编译
- PHP学习笔记2 - 文件、数组、字符串
- iPhone开发笔记——获取字符串宽度和高度
- Unity将字符数组转换为字符串向Android传递消息
- 学习笔记4-C语言数组和字符串