用标准C编写COM(五)COM in plain C,Part5
原文:http://www.codeproject.com/Articles/14183/COM-in-plain-C-Part-5
添加连接对象(源、接收器)
下载例程-246Kb
内容
简介 在COM对象中封装回调函数 IConnectionPointContainer和IConnectionPoint对象 C应用程序例程 添加脚本语言支持 另一个C应用程序例程 VBScript例程 *多类型回调对象 多个回调对象简介
通常,对于一个我们调用的DLL函数来说“回调”我们自己的一个函数是比较方便的,这样我们可以在特定的时刻做些其他工作,或者接受些发生的事情的通知。例如,标准C库函数qsort,它的第四个参数是一个指向我们提供的比较两个内容项函数的指针。这样,当我们调用qsort时,它让我们来决定内容项排序的规则,而qsort本身做的实际工作是重新排序这些项。
我们不能提供随意函数给qsort。写qsort的家伙严格指定了我们的“比较”回调函数的参数、返回值,当然也严格指定了回调函数的目的。此外,qsort决定什么时候真正调用我们的回调函数(因为是qsort它调用我们的函数)。设计qsort的家伙要求我们的比较回调函数必须定义成这样:
coclass IExampleEvts2 { [default] interface IExampleEvts2VTbl; [source, default] interface IFeedback2VTbl; [source] interface ICompareVtbl; }
但注意只有一个source interface可以标记为default,同时脚本引擎只使用一个缺省对象。(也就是说脚本不能提供给上面的ICompare回调函数给我们)。
此外,我们必须给我们的IConnectionPointContainer的EnumConnectionPoints函数提供真正的代码。这个函数应该返回另一个可以枚举我们支持的每个不同类型的IConnectonPoint对象。(它返回的对象是一个像我们在我们的Collections章节中使用的标准枚举器对象)
因为回调对象通常用在交互脚本中(脚本引擎不能支持每一个单独coclass对象的多类型的回调对象),我会进一步深入研究多类型回调对象。
在我们对象例程中,我们允许应用程序(或者脚本引擎)只给我提供一个IFeedback2对象(我们把它存储在MyRealIExampleEvts2的feedback成员中)。但理论上,应用程序可以给我们提供它希望的多个IFeedback2回调对象。在我们IConnectionPoint的Advise中,我们直接拒绝接受从一个应用程序、引擎那里请求的多个IFeedback2。如果你要允许应用程序、引擎提供多个IFeedback2,那么不能用feedback成员,你不妨另外定义一个结构,结构可以连接成一个列表,结构有一个存储IFeedback2指针的成员。你在Advise中GlobalAlloc每个结构成员,把他们链接到列表头存储在MyRealIExampleEvts2 成员中的列表中。
你还需要修改DoSomething,循环整个列表,调用每个IFeedback2的Invoke。
不过,由于使用回调对象主要是脚本,而大部分只使用一个回调对象,我们跳过开发这种情况的例子。