IDL中的dual关键字。

招RD和QA 2006-11-13 02:33:18
最近用了一点ATL,有点问题请教一下。

在生成的IDL文件中,我添加了4个方法,仅仅为了测试。

[
object,
uuid(A8124E10-EBE5-48FE-B1F0-123C0D310C66),
dual,
helpstring("IMath Interface"),
pointer_default(unique)
]
interface IMath : IDispatch
{
[id(1), helpstring("method Add")] HRESULT Add( [in] VARIANT vOp1, [in] VARIANT vOp2, [out, retval] VARIANT *pvResult );
[id(2), helpstring("method Sub")] HRESULT Sub( [in] VARIANT vOp1, [in] VARIANT vOp2, [out, retval] VARIANT *pvResult );
[id(3), helpstring("method Mul")] HRESULT Mul( [in] VARIANT vOp1, [in] VARIANT vOp2, [out, retval] VARIANT *pvResult );
[id(4), helpstring("method Div")] HRESULT Div( [in] VARIANT vOpt1, [in] VARIANT vOpt2, [out, retval] VARIANT *pvResult );
};

我对双接口的理解其实很简单,就是一个接口(vtable)中同时包含IDispatch和自动化对象本身的属性方法。

我想知道在IDL文件中"Dual"这个keyword有什么作用?无论加不加这个关键字,IMath都应该是个双接口啊。因为下面的测试程序始终都能运行通过。

CComPtr< IUnknown > spUnknown;
HRESULT hr = spUnknown.CoCreateInstance( L"Math" );

CComQIPtr< IDispatch > spDisp( spUnknown );
...
spDisp->Invoke(...)
...
CComQIPtr< IMath > spMath( spUnknown );
spMath->Add(...)
...全文
410 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
UDX协议 2006-11-15
  • 打赏
  • 举报
回复
你应该用vb来测试,而不能用c来测试,c是测不出来的,lz.
toxyboy 2006-11-15
  • 打赏
  • 举报
回复
..你实现了idispatch,则可以用来派发,idl只是接口定义语言,实际上它并不能代表真正的实现,它影响你的tlb或者.c的生成。。用dual表示是实现了自定义和派发接口双接口,看楼主的代码,你用自定义接口的调用方法试试看,因该是错的。
招RD和QA 2006-11-13
  • 打赏
  • 举报
回复
关于数据类型,我想,使用invoke时,自动化接口只能使用自动化类型,本来就是这样啊?和是不是dual有什么关系?
招RD和QA 2006-11-13
  • 打赏
  • 举报
回复
晕。有没有人看我写的测试程序?

CComPtr< IUnknown > spUnknown;
HRESULT hr = spUnknown.CoCreateInstance( L"Math" );

CComQIPtr< IDispatch > spDisp( spUnknown );
...
spDisp->Invoke(...)
...
CComQIPtr< IMath > spMath( spUnknown );
spMath->Add(...)

无论写不写dual,都可以测试通过的。

而且我对比了一下IDL文件生成的header文件,发现有没有dual,生成的header文件是一样的。

我只想知道dual关键字在我这个IDL中,起了什么作用。看起来根本没用。因为是不是双接口本身,不是靠dual就可以解决的,而是要看IDL文件中的定义。
wind235 2006-11-13
  • 打赏
  • 举报
回复
不用Dual? 你用web调用试试,就晓得了!
iGray 2006-11-13
  • 打赏
  • 举报
回复
dual表示一个接口是双接口,既可通过IDispatch调用,也可直接通过vtable调用。

双接口是实现了IDispatch的接口,又同时可以不通过IDispatch来调用的接口。
要实现IDispatch,那么数据类型必须是automation兼容的。

楼主,你上面举例的代码是个“夹生”,这样写IDL本来就应该是个dual.
如果你不写只是生成的关于接口的信息中没有明确地说明这是一个双接口。其实他是一个,但给出的类型信息上没有标明它是一个双接口罢了。

看看《COM原理与应用》P346页至P359页吧,有助于你理解。IDispatch接口与双接口的区别。

要知道。用于事件通知的出接口,通常是IDispatch接口,而不是双接口。这样在有灵活性。

说到底,区别就是虚函数表的区别。IDispatch接口的vtable中7个函数地址(外加一个类型信息),是4*8个byte大小。
如果是双接口vtable里,除了原本的8个项外,还有其它的函数地址入口项。




guti_milan 2006-11-13
  • 打赏
  • 举报
回复
好像是这样的如果 自定义的接口是继承自IDispatch的话
系统会默认追加 dual 如果是继承IUnknow的话 可有可无!
Myie的IDL:
[
object,
uuid(25E81C73-A6C1-46B2-A83B-C05565643062),
helpstring("IMyIENSHandle Interface"),
pointer_default(unique)
]
interface IMyIENSHandle : IUnknown
{
};

我自己写的IDL
[
object,
uuid(176A9B31-2AD8-40E3-A9E6-3BD4B1AF9FAE),
dual,
helpstring("IRSSBrowserNSHandle Interface"),
pointer_default(unique)
]
interface IRSSBrowserNSHandle : IUnknown
{
};
都可以正常运行!
horris 2006-11-13
  • 打赏
  • 举报
回复
我上面说的有点错误,应该是:
dual实际上就是指示,接口中用到的所有参数的数据类型都必须是Automation兼容的,就是krh2001(边城浪子)所说的意思,还有一层意思,就是这个接口的前几个方法是IDispatch的方法,后几个是接口本身自定义的方法。
楼主如果把dual去掉,然后在接口中把参数类型改成非Automation兼容的,比如一个自定义类型,组件将能编译成功,但是你的测试程序就会失败。
另外,楼主的测试程序用的是迟绑定,如果组件去掉dual,测试客户端用直接自定义接口绑定,也是能运行的。但是此时的接口表并不是自定义接口的,前面还有IDispatch的方法。实际上这时你还可以调用IDispatch的方法呢!
如果你加上dual,则在直接自定义接口绑定时,绑定的接口表是IDispatch后面的方法,也即你的自定义的接口方法。这时客户端是无法调用IDispatch的方法的。
由此看来只要你的接口继承自IDispatch,那么dual可以不加,但是加上更好,因为在直接自定义接口绑定时,返回的接口表比较少。
horris 2006-11-13
  • 打赏
  • 举报
回复
如果你加上dual,则在直接自定义接口绑定时,绑定的接口表是IDispatch后面的方法,也即你的自定义的接口方法。
所以dual不是可有可无的,是必须加的。
horris 2006-11-13
  • 打赏
  • 举报
回复
dual实际上就是指示,接口中用到的所有参数的数据类型都必须是Automation兼容的,就是krh2001(边城浪子)所说的意思,还有一层意思,就是这个接口的前几个方法是IDispatch的方法,后几个是接口本身自定义的方法。
楼主如果把dual去掉,然后在接口中把参数类型改成非Automation兼容的,比如一个自定义类型,组件将能编译成功,但是你的测试程序就会失败。
另外,楼主的测试程序用的是迟绑定,如果组件去掉dual,那么用直接自定义接口绑定,将失败。因为此时的接口表是不对的,测试客户端认为接口的第一个方法是Add,而实际上调用的是IDispatch的第一个方法。
招RD和QA 2006-11-13
  • 打赏
  • 举报
回复
MSDN上如果说,

When the dual C++ attribute precedes an interface, it causes the interface to be placed inside the library block in the generated .idl file.

但我没理解,谁能解释一下。
招RD和QA 2006-11-13
  • 打赏
  • 举报
回复
晕,请问楼上的,
那dual和是否是双接口没有什么关系嘛?随便什么接口都可以是dual??

[
object,
uuid(A8124E10-EBE5-48FE-B1F0-123C0D310C66),
dual,
helpstring("IMath Interface"),
pointer_default(unique)
]
interface IMath : IUnknown
{
};
jerry 2006-11-13
  • 打赏
  • 举报
回复
dual 接口方法只能使用 标准数据类型. 只能返回 HRESULT 类型.

非dual接口没这个限制. 就这个区别

3,248

社区成员

发帖
与我相关
我的任务
社区描述
ATL,Active Template Library活动(动态)模板库,是一种微软程序库,支持利用C++语言编写ASP代码以及其它ActiveX程序。
社区管理员
  • ATL/ActiveX/COM社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧