cplusplus

一知半解与自定义COM接口(转载)

上一篇 / 下一篇  2011-07-08 22:12:42 / 个人分类:COM编程

这篇随笔很早就写好了,但一直没有想好是不是放上来。

除虫记之十三:一知半解与自定义COM接口

好几年前就已经使用COM了,大大小小、各种各样的COM组件也写了很多,COMRPC的理论也看了不少书,自以为对COM相当熟悉了,但本文遇到的这个问题,让我汗颜不已。发现自己其实对COM是一知半解,有些技术可以说是狗屁不懂:(


问题是这样的,2周前,一个同事问我,他写了一个不支持双接口的进程外组件,用CoCreateInstance创建这个接口怎么也创建不成功,问我怎么回事?我说这很简单呀,看返回值就知道了。答案是返回值是0x80004002,不支持此接口。怎么了?哪儿出了问题?

同事说,我们工程中创建组件的方式是先创建IUnknown接口,然后再查询的。换成这种方式,第一步创建IUnknown成功,但第二步查询接口失败了。ft,咋回事,还没遇到过这种情况。

这个组件里面还定义了一个出接口,是不是这个原因?让他把相关代码注释掉试试,结果还是不行。

干脆再重新写一个最简单的,哈,tnnd,用ATL写了一个最简单的采用Custom模式的exe组件,在客户端用CoCreateInstance就是创建不成功,一直的报告都是不支持此接口

不支持此接口?不可能的呀。用VB的对象浏览器查看这个组件,里面明明白白的写这个接口及接口函数。但当时忘了写段VB代码看是否能创建成功了。

没有什么结论,当时急于下班,这个问题就放下了。

这个周末,想起这个问题,又打开工程,写了几个测试程序。发现,进程内组件没有这个问题,支持自动化接口的也没有这个问题,不过还是没有解决问题。

中间曾经想起过一个现象,VC6的早期版本,没有打补丁的,ATL有一个Bug,就是自动生成的CLSID,和自动生成的rgs文件里面的对应CLSID,会有一个字符不一样,这次会不会也是这样原因?严格的比较了多次,发现不是这个原因,现在用的VC都打了SP5了。

很是郁闷,女儿要玩游戏,非要用我的电脑,于是把电脑让给她,自己躺下休息一会儿,随手拿过潘爱民的那本《COM原理与应用》,翻翻看有没有什么帮助。

在第三次的躺下,第三次的翻看那本书的时候,看到了一句令我汗颜不已甚至于要跳河的话:windowsCOM库还不能够处理自定义接口的列集过程!就是说MIDL给我们提供了接口的代理以及存根源代码、COM库提供了缺省的代理对象和存根的管理器以及RPC通道,但就是不给我们实现这种简单参数类型的标准列集的存根程序!这windows也够可以的,100步,都走了99步了,咋就差这一步?

我一直以为系统提供了标准列集的代理存根dll,兄弟们,知道我是怎么个一知半解了吧。哪天看到我要跳河,一定要劝劝我呀:)

这下精神为之振奋,用命令行编译了一下midl生成的mk文件!注册这个代理存根dll!测试!可以了!
tnnd,还有这种事情,我这水平真的是太差了!

那为什么实现了IDispatch接口的组件就不用自己实现代理存根程序了呢?究其原因,我认为是IDispatch的参数类型是固定了的,系统对此实现了参数的列集和散集。系统实现的这个代理存根就是oleaut32.dll,它的CLSID{00020424-0000-0000-C000-000000000046}

自定义接口实现标准列集也是很简单的,如果你够仔细,你会发现MIDLidl编译后会产生几个文件:dlldata.cXXXX_p.cXXXXps.defXXXXps.mk,我们用这些文件就可以很容易的实现自定义接口的列集代理和存根。
介绍三种方法:
1
、命令行:nmake /f XXXXps.mk,执行后,会产生XXXXps.dll,用Regsvr32 XXXXps.dll注册一下这个代理存根dll就可以了。
2
、在VC工程设置的Custom Build页面的Commands里面追加下面内容,然后Rebuild All就可以了。
 nmake "$(InputName)ps.mk"
 echo nmake "$(InputName)ps.mk"
 regsvr32 "$(InputName)ps.dll"  /s
3
、创建一个新的dll工程,把midl产生的这几个文件添加到工程中,编译,注册,就可以了。

要注意的一点是,如果组件发布,要同步发布对应的代理存根dll

还有,进程外组件支持IDispatch接口也没有什么不好的,暂时我想。

教训:
做技术不能象我这样一知半解的。


TAG: COM编程

 

评分:0

我来说两句

Open Toolbar