IDL中提供的[source]属性,是为了让实现类宣扬它支持哪几个对外接口注册。
2008-02-02 08:21
323 查看
IDL中提供的[source]属性,是为了让实现类宣扬它支持哪几个对外接口注册。
主要表达的意思的是--组件内部在某种条件下将调用该接口,向外界传递信息。如果你对此信息感兴趣,就要自己实现这个接口,并向该组件注册并连接。这样当组件调用该接口时,会向你及时传递你感兴趣的信息。
例如:
coclass Math
{
[default] interface IMath;
[source, default] dispinterface _IMathEvents; <==== 对外宣扬 Math组件支持_IMathEvents对外接口的注册。
};
com包括引入接口和引出接口,来描述组件可以支持的两种不同类型的接口。
. 一个引入接口是指由组件实现的接口,这里的IMath接口就是一个引入接口。因为它是有组件来实现的。
.一个引出接口是指在组件的类型库中描述的接口,这里的_IMathEvents接口就是一个引入接口。它实际上是由Math组件的客户机来实现的。
下面展示_IMathEvents接口是如何实现,并与组件Math组件注册并链接的。
========================_IMathEvents接口的实现==========================
class CMathEvents :
public CComObjectRoot,
public _IMathEvents
{
public:
CMathEvents()
{
}
BEGIN_COM_MAP(CMathEvents)
COM_INTERFACE_ENTRY(IDispatch)
COM_INTERFACE_ENTRY(_IMathEvents)
END_COM_MAP()
// IMathEvents
public:
STDMETHODIMP GetTypeInfoCount(UINT*)
{
return E_NOTIMPL;
}
STDMETHODIMP GetTypeInfo( UINT iTInfo,
LCID lcid,
ITypeInfo **ppTInfo)
{
return E_NOTIMPL;
}
STDMETHODIMP GetIDsOfNames( REFIID riid,
LPOLESTR *rgszNames,
UINT cNames,
LCID lcid,
DISPID *rgDispId)
{
return E_NOTIMPL;
}
STDMETHODIMP Invoke( DISPID dispIdMember,
REFIID riid,
LCID lcid,
WORD wFlags,
DISPPARAMS *pDispParams,
VARIANT *pVarResult,
EXCEPINFO *pExcepInfo,
UINT *puArgErr)
{
switch( dispIdMember )
{
case 0x1:
// Make sure the is just one argument
if ( pDispParams->cArgs != 1 )
return DISP_E_BADPARAMCOUNT;
// We don't support named arguments
if ( pDispParams->cNamedArgs )
return DISP_E_NONAMEDARGS;
// Coerce the argument into a long
HRESULT hr;
VARIANTARG var;
VariantInit( &var );
hr = VariantChangeTypeEx( &var,
&(pDispParams->rgvarg[0]),
lcid, 0, VT_I4 );
if FAILED( hr )
return DISP_E_BADVARTYPE;
ComputationComplete( var.lVal );
break;
default:
DisplayMessage( "Error" );
break;
}
return S_OK;
}
STDMETHODIMP ComputationComplete(long lResult)
{
char szMsg[128];
sprintf( szMsg, "The result is %d", lResult );
DisplayMessage( szMsg );
return S_OK;
}
};
=========================与Math组件注册并链接============================
CComPtr<IMath> ptrMath;
HRESULT hr;
hr = CoCreateInstance( CLSID_Math, <==== 创建宣扬支持_IMathEvents对外接口的组件
NULL,
CLSCTX_SERVER,
IID_IMath,
(void**) &ptrMath );
if ( FAILED( hr ))
{
HandleError( "Failed to create server instance", hr );
return -1;
}
CComObject<CMathEvents>* ptrMathEvents;
CComObject<CMathEvents>::CreateInstance( &ptrMathEvents ); <======= 创建实现_IMathEvents的组件实例
CComPtr<IUnknown> ptrEventsUnk = ptrMathEvents;
//
IMathEvents *pMathEvents;
hr = ptrMathEvents->QueryInterface(IID_IMathEvents, (void **)&pMathEvents); <=======获得_IMathEvents接口指针
// Set up the connection
DWORD dwCookie;
hr = AtlAdvise( ptrMath,
pMathEvents,
DIID__IMathEvents,
&dwCookie ); <======将_IMathEvents接口指针pMathEvents在ptrMath组件实例中注册并链接
if (FAILED( hr ))
{
HandleError( "Unable to setup the connection for IMathEvents", hr );
return -1;
}
// Access the IMath interface
long lResult;
ptrMath->Add( 300, 10, &lResult ); <========调用ptrMath组件方法。组件方法执行过程中会适时通过传入的_IMathEvents接口指针pMathEvents向调用者返回信息--回调。
ptrMath->Subtract( 300, 10, &lResult );
ptrMath->Multiply( 300, 10, &lResult );
ptrMath->Divide( 300, 10, &lResult );
// Shut down the event connection
AtlUnadvise( ptrMath,
DIID__IMathEvents,
dwCookie ); <======中断_IMathEvents接口指针与ptrMath组件实例的链接
.....
其中AtlAdvise和AtlUnadvise的实现过程是这样的:
CComPtr<IUnknown>
spSource = /* Set to the source of the events */ ;
CComPtr<_ISpeakerEvents>
spSink = /* Sink to receive the events */ ;
DWORD dwCookie ;
CComPtr<IConnectionPointContainer> spcpc;
HRESULT hr = spSource.QueryInterface (&spcpc);
CComPtr<IConnectionPoint> spcp ;
hr = spcpc->FindConnectionPoint(__uuidof(_ISpeakerEvents),
&spcp); <======根据_ISpeakerEvents来查找ConnectionPoint。只有组件宣扬的对外接口,才可以查找成功。
hr = spcp->Advise (spSink, &dwCookie) ; // Establish connection
// Time goes by, callbacks occur...
hr = spcp->Unadvise (dwCookie) ; // Break connection
hr = AtlAdvise( ptrMath, // 对外宣扬 支持_IMathEvents接口
pMathEvents, // _IMathEvents类型接口指针
DIID__IMathEvents,
&dwCookie );
结论:对于AtlAdvise,只有组件宣扬的对外接口,才可以注册成功。
主要表达的意思的是--组件内部在某种条件下将调用该接口,向外界传递信息。如果你对此信息感兴趣,就要自己实现这个接口,并向该组件注册并连接。这样当组件调用该接口时,会向你及时传递你感兴趣的信息。
例如:
coclass Math
{
[default] interface IMath;
[source, default] dispinterface _IMathEvents; <==== 对外宣扬 Math组件支持_IMathEvents对外接口的注册。
};
com包括引入接口和引出接口,来描述组件可以支持的两种不同类型的接口。
. 一个引入接口是指由组件实现的接口,这里的IMath接口就是一个引入接口。因为它是有组件来实现的。
.一个引出接口是指在组件的类型库中描述的接口,这里的_IMathEvents接口就是一个引入接口。它实际上是由Math组件的客户机来实现的。
下面展示_IMathEvents接口是如何实现,并与组件Math组件注册并链接的。
========================_IMathEvents接口的实现==========================
class CMathEvents :
public CComObjectRoot,
public _IMathEvents
{
public:
CMathEvents()
{
}
BEGIN_COM_MAP(CMathEvents)
COM_INTERFACE_ENTRY(IDispatch)
COM_INTERFACE_ENTRY(_IMathEvents)
END_COM_MAP()
// IMathEvents
public:
STDMETHODIMP GetTypeInfoCount(UINT*)
{
return E_NOTIMPL;
}
STDMETHODIMP GetTypeInfo( UINT iTInfo,
LCID lcid,
ITypeInfo **ppTInfo)
{
return E_NOTIMPL;
}
STDMETHODIMP GetIDsOfNames( REFIID riid,
LPOLESTR *rgszNames,
UINT cNames,
LCID lcid,
DISPID *rgDispId)
{
return E_NOTIMPL;
}
STDMETHODIMP Invoke( DISPID dispIdMember,
REFIID riid,
LCID lcid,
WORD wFlags,
DISPPARAMS *pDispParams,
VARIANT *pVarResult,
EXCEPINFO *pExcepInfo,
UINT *puArgErr)
{
switch( dispIdMember )
{
case 0x1:
// Make sure the is just one argument
if ( pDispParams->cArgs != 1 )
return DISP_E_BADPARAMCOUNT;
// We don't support named arguments
if ( pDispParams->cNamedArgs )
return DISP_E_NONAMEDARGS;
// Coerce the argument into a long
HRESULT hr;
VARIANTARG var;
VariantInit( &var );
hr = VariantChangeTypeEx( &var,
&(pDispParams->rgvarg[0]),
lcid, 0, VT_I4 );
if FAILED( hr )
return DISP_E_BADVARTYPE;
ComputationComplete( var.lVal );
break;
default:
DisplayMessage( "Error" );
break;
}
return S_OK;
}
STDMETHODIMP ComputationComplete(long lResult)
{
char szMsg[128];
sprintf( szMsg, "The result is %d", lResult );
DisplayMessage( szMsg );
return S_OK;
}
};
=========================与Math组件注册并链接============================
CComPtr<IMath> ptrMath;
HRESULT hr;
hr = CoCreateInstance( CLSID_Math, <==== 创建宣扬支持_IMathEvents对外接口的组件
NULL,
CLSCTX_SERVER,
IID_IMath,
(void**) &ptrMath );
if ( FAILED( hr ))
{
HandleError( "Failed to create server instance", hr );
return -1;
}
CComObject<CMathEvents>* ptrMathEvents;
CComObject<CMathEvents>::CreateInstance( &ptrMathEvents ); <======= 创建实现_IMathEvents的组件实例
CComPtr<IUnknown> ptrEventsUnk = ptrMathEvents;
//
IMathEvents *pMathEvents;
hr = ptrMathEvents->QueryInterface(IID_IMathEvents, (void **)&pMathEvents); <=======获得_IMathEvents接口指针
// Set up the connection
DWORD dwCookie;
hr = AtlAdvise( ptrMath,
pMathEvents,
DIID__IMathEvents,
&dwCookie ); <======将_IMathEvents接口指针pMathEvents在ptrMath组件实例中注册并链接
if (FAILED( hr ))
{
HandleError( "Unable to setup the connection for IMathEvents", hr );
return -1;
}
// Access the IMath interface
long lResult;
ptrMath->Add( 300, 10, &lResult ); <========调用ptrMath组件方法。组件方法执行过程中会适时通过传入的_IMathEvents接口指针pMathEvents向调用者返回信息--回调。
ptrMath->Subtract( 300, 10, &lResult );
ptrMath->Multiply( 300, 10, &lResult );
ptrMath->Divide( 300, 10, &lResult );
// Shut down the event connection
AtlUnadvise( ptrMath,
DIID__IMathEvents,
dwCookie ); <======中断_IMathEvents接口指针与ptrMath组件实例的链接
.....
其中AtlAdvise和AtlUnadvise的实现过程是这样的:
CComPtr<IUnknown>
spSource = /* Set to the source of the events */ ;
CComPtr<_ISpeakerEvents>
spSink = /* Sink to receive the events */ ;
DWORD dwCookie ;
CComPtr<IConnectionPointContainer> spcpc;
HRESULT hr = spSource.QueryInterface (&spcpc);
CComPtr<IConnectionPoint> spcp ;
hr = spcpc->FindConnectionPoint(__uuidof(_ISpeakerEvents),
&spcp); <======根据_ISpeakerEvents来查找ConnectionPoint。只有组件宣扬的对外接口,才可以查找成功。
hr = spcp->Advise (spSink, &dwCookie) ; // Establish connection
// Time goes by, callbacks occur...
hr = spcp->Unadvise (dwCookie) ; // Break connection
hr = AtlAdvise( ptrMath, // 对外宣扬 支持_IMathEvents接口
pMathEvents, // _IMathEvents类型接口指针
DIID__IMathEvents,
&dwCookie );
结论:对于AtlAdvise,只有组件宣扬的对外接口,才可以注册成功。
相关文章推荐
- golang自定义路由控制实现(二)-流式注册接口以及支持RESTFUL
- NHibernate+WCF项目实战(三)使用WCF对外提供Webservices接口并进行单元测试
- 稳扎稳打Silverlight(54) - 4.0通信之对UDP协议的支持: 通过 UdpAnySourceMulticastClient 实现 ASM(Any Source Multicast),即“任意源多播”
- 稳扎稳打Silverlight(54) - 4.0通信之对UDP协议的支持: 通过 UdpAnySourceMulticastClient 实现 ASM(Any Source Multicast),即“任意源多播”
- 稳扎稳打Silverlight(54) - 4.0通信之对UDP协议的支持: 通过 UdpAnySourceMulticastClient 实现 ASM(Any Source Multicast),即“任意源多播”
- 稳扎稳打Silverlight(54) - 4.0通信之对UDP协议的支持: 通过 UdpAnySourceMulticastClient 实现 ASM(Any Source Multicast),即“任意源多播”
- 稳扎稳打Silverlight(54) - 4.0通信之对UDP协议的支持: 通过 UdpAnySourceMulticastClient 实现 ASM(Any Source Multicast),即“任意源多播”
- 稳扎稳打Silverlight(54) - 4.0通信之对UDP协议的支持: 通过 UdpAnySourceMulticastClient 实现 ASM(Any Source Multicast),即“任意源多播”
- 稳扎稳打Silverlight(54) - 4.0通信之对UDP协议的支持: 通过 UdpAnySourceMulticastClient 实现 ASM(Any Source Multicast),即“任意源多播”
- ATL 支持ActiveX控件开发的所实现的接口
- BOOST模板库实现的功能与lua在语言层级提供的支持之比较
- tomcat启动提示server.xml的context节点中不支持source属性警告的解决方法
- graph.js整合node和edge资源,对外提供访问接口
- IE9对HTML5中一部分属性不提供支持的原因
- 稳扎稳打Silverlight(55) - 4.0通信之对UDP协议的支持: 通过 UdpSingleSourceMulticastClient 实现 SSM(Source Specific Multicast),即“源特定多播”
- 稳扎稳打Silverlight(55) - 4.0通信之对UDP协议的支持: 通过 UdpSingleSourceMulticastClient 实现 SSM(Source Specific Multicast),即“源特定多播”
- 稳扎稳打Silverlight(55) - 4.0通信之对UDP协议的支持: 通过 UdpSingleSourceMulticastClient 实现 SSM(Source Specific Multicast),即“源特定多播”
- 稳扎稳打Silverlight(55) - 4.0通信之对UDP协议的支持: 通过 UdpSingleSourceMulticastClient 实现 SSM(Source Specific Multicast),即“源特定多播”
- 稳扎稳打Silverlight(55) - 4.0通信之对UDP协议的支持: 通过 UdpSingleSourceMulticastClient 实现 SSM(Source Specific Multicast),即“源特定多播”
- 稳扎稳打Silverlight(55) - 4.0通信之对UDP协议的支持: 通过 UdpSingleSourceMulticastClient 实现 SSM(Source Specific Multicast),即“源特定多播”