com初学心得小记

原创 2006年06月05日 00:09:00

DLL是一群写lib写到郁闷的人发明的。
Com是一群写Dll写到郁闷的人发明的。
.net assembly是一群写com写到郁闷的人发明的....
                     ----Akumas
 
     某年某月某日,偶为了完成某同学未竟的事业,毅然向传说中浮云一般的Com发起挑战,虽然明知这是不可完成的任务,但是为了祖国的崛起,为了为中国的IT事业添砖加瓦,为了那美克星的爱与和平,俺还是决定自我牺牲一把。
    突击了两周之后,终于有点不成样的半成品出来。经过我的实践证明,Com不愧是浮云级别的东西,而我也深刻的体会到,浮云的真实含义=编写繁琐+语法晦涩+资料难寻+设计不成熟。从现在的眼光来看,com有很多东西的设计已经落伍了,但是由于目前com在windows平台内的支持可谓是最广泛的,所以研究研究还是有点价值。以下是我在突击过程中遇到的小问题和解决,供日后回忆以及各位参考。
    编写语言:c++
    编译环境:vs2003
 
1、IDL和c++
    原则上,com的接口应该是先编写IDL,由编译器生成头文件,然后由源文件去include这个头文件,不过实际上vc7默认的com project都是采用idl与头文件混合编写的方式。这种方式虽然用起来简便易懂,但是毕竟是在.h里,语法要求与纯IDL文件还不完全一样,有些语法不完全支持,所以参数设置的时候要特别小心,否则会出现IDL语法正确,但是编译报错的情况。比如如下方法声明:
    HRESULT PutArray([in] SAFEARRAY(BSTR) inputArray);
    虽然作为IDL语法是完全正确的,但是当idl混合到.h里的时候,这种语法就会编译报错,仅能使用
    HRESULT PutArray([in] SAFEARRAY* inputArray);
 
2、接口中的自定义参数
    由于Com设计时考虑了跨语言性,所以Com使用了一些通用的类型定义,以使编译后的com控件能够被各种语言所正确调用。而相对的,一些c++中常用的类型将不允许在com的接口定义中出现,如string(使用BSTR)、bool(使用VARIANT_BOOL)等。更多一层,如果用户希望在接口中使用自己的类作为自定义参数,那首先必须在控件库中定义该类的接口(实际上com中的类也肯定是先定义了接口的),然后使用该接口指定为参数的类型。
    比如我们定义一个类CTranInfoCtrl继承了接口ITranInfoCtrl,则某方法如果需要使用CTranInfoCtrl作为参数,则需要如下定义:
    HRESULT PutInfo([in]ITranInfoCtrl* tranInfo);
 
3、SAFEARRAY
    自定义类型的数组对我来说,是玩com过程中最痛苦的一环,几乎所有找到的资料都语焉不详(强调:特别是baidu里找的资料基本没有参考价值...),为了让同学们不再重复我走过的弯路,特别在此说明如何实现自定义类型数组,并且将其正确导入c#中。
    第一步,定义一个方法,以指定类型的安全数组为参数,类型暂定为BSTR。根据网上的资料,我们应该如此定义:
    HRESULT PutArray([in] SAFEARRAY(BSTR) inputArray);
    可惜,编译器报错,原因见前,我们修改定义如下:
    HRESULT PutArray([in] SAFEARRAY* inputArray);
    这次,编译ok了。但是这里我们仅声明了一个安全数组,但是控件并不知道该数组的类型,当然也就没达到我们的要求。
    第二步,指定参数类型:
    HRESULT PutArray([in, satype(BSTR)] SAFEARRAY* inputArray);
    这里我们使用satype这个属性来指定safearray的参数类型。此外,虽然safearray可以自己描述数组大小,但是我们也可以使用size_is属性来标记数组大小(可以使用size_is(输入参数)来指定动态数组大小)。
    第二步完成,我们此时将能成功编译一个Dll,将Dll导入c#之后,我们会发现一个问题,在导入类中,PutArray这个方法的参数不是我们期待的string[] inputArray,而是变成了System.Array inputArray。
    这个问题是由于c#导入程序的默认参数在捣鬼,它在默认导入时使用了(/sysarray参数)。为了正确的导入safearray,比如手动的重新进行导入,在sdk目录下寻找到tlbimp.exe,我们将需要导入的com dll复制过来(假定名为array.dll),进入命令行,输入
    tlbimp array.dll /out:array_imp.dll
    就可生成我们需要的dll,将这个array_imp.dll引入到project,我们用对象查看器就能发现,现在的PutArray的参数已经变成了string[] inputArray
 
4、接口类的实例化
    通常一个com project中,对一个类我们会定义一个接口(Interface),比如我们想设计一个类Cobject,则会定义一个接口Iobject,由Cobject继承Iobject,而Com编译器实际上最后会自动生成一个完全实现类CobjectClass。而Cobject由于从Iobject继承了虚基类IDispatch和IUnknown,而且没有实现虚函数,所以Cobject这个类是无法实例化的。如果我们既想在代码中直接实例化Cobject的一个对象,又不想重新实现Cobject的虚函数,那我们可以使用com为我们提供的懒人接口CComObject。CComObject利用模版自动实现虚函数,并生成新的类实例,对我们来说非常方便,假设我们已经定义一个类CTranInfoCtrl,尚未实现虚寒树,但是又想使用它的对象,则使用方法如下:
    CTranInfoCtrl* infoCtrl = new CComObject<CTranInfoCtrl>;
    使用虽然简单,不过需要牢记,com对象生成后,不能直接调用delete进行删除,而是在实例化后调用AddRef()增加引用计数,使用完后用Release()减去计数并进行资源释放。如果不照此做的话,可能会导致不可预期的结果。
   
版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

COM/ATL项目开发小记

最近在忙COM的项目,中途遇到一些问题和自己的一些想法,先记录下来,以便以后再遇到可以查阅,先胡乱写一通,将来东西多了,再整理成篇吧。   1.关于ATL Merge ProxyStub的问题,具...

Com原理与应用的心得

最近在读潘老师写的COM

付费并发服务器开发(vip.kankan.com)的心得体会

即将从迅雷离职了,虽然有点舍不得,但是既然做了决定,就会坚持。 一年多的时间,我很感谢迅雷给我的机会,让我刚来就能负责迅雷看看付费频道的后台开发,接着又把看看无线的整个后台交给我维护,敢于用人,因人...

学习心得《软件工程(C编码实践篇)》MOOC课程http://mooc.study.163.com/course/USTC-1000002006 ”

王训谱+ 原创作品转载请注明出处 + 《软件工程(C编码实践篇)》MOOC课程http://mooc.study.163.com/course/USTC-1000002006 ”

软件工程学习理解与心得《软件工程(C编码实践篇)》MOOC课程http://mooc.study.163.com/course/USTC-1000002006

软件工程理解与学习心得 软件工程是研究和应用如何以系统性的、规范化的、可定量的过程化方法去开发和维护软件的一门科学,代码的设计不单单是为了使程序可运行,可实现需要的功能,在代码的规范,设计的规范,模块...

《COM本质论》COM是一个更好的C++心得分享

昨天看了《COM本质论》的第一章”COM是一个更好的C++”,觉得很有必要做一些笔记,于是整理成这篇文章,我相信你值得拥有。 这篇文章主要讲的内容是:一个实现了快速查找功能的类FastString,...

初学android插件化开发小记

插件开发可以提高一款软件的可扩展性,我个人认为他就是一种化整为零的思想。就跟电脑的主板上留了不同的接口一样,只要插上相应的硬件就可以实现具体的功能。 Android插件开发要具备以下的基本功share...

Dubbo初学小记

user-guide:http://dubbo.io/User+Guide-zh.htm 简单记录下过程和需要注意的地方: 我的环境和工具:jdk1.7 win10 Eclipse Mar tomca...

matlab数学建模算法小记

  • 2013-04-20 11:55
  • 4.00MB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

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