Methods ATL/COM对象的链接方法 在C++中,我们可以通过设计返回这个方法的方法来轻松地在类中建立方法链。这在ATL/COM设置中可能吗?假设我有一个简单的ATL类MyOBj。我想知道在这种情况下链接是否可行,如果可能,支持链接的方法的idl签名是什么?简单的例子将不胜感激!(事实上,我的方法是从VBA for excel调用的,我希望在该VBA上下文中进行链接,因为我们已经为标准VBA方法进行了链接。)
Thx很多 R 编辑: 在.idl文件中,我有以下内容:Methods ATL/COM对象的链接方法 在C++中,我们可以通过设计返回这个方法的方法来轻松地在类中建立方法链。这在ATL/COM设置中可能吗?假设我有一个简单的ATL类MyOBj。我想知道在这种情况下链接是否可行,如果可能,支持链接的方法的idl签名是什么?简单的例子将不胜感激!(事实上,我的方法是从VBA for excel调用的,我希望在该VBA上下文中进行链接,因为我们已经为标准VBA方法进行了链接。),methods,com,atl,chaining,idl,Methods,Com,Atl,Chaining,Idl,Thx很多 R 编辑: 在.idl文件中,我有以下内容: interface IRateModel : IDispatch{ [id(1), helpstring("SETRATEMODEL")] HRESULT SETRATEMODEL( [in] VARIANT * var_in ) ; [id(2), helpstring("GETRATETERMSTRUCTURE")] HRESULT GETRATETERMSTRUCTURE( [in, out] VARIANT * v
interface IRateModel : IDispatch{
[id(1), helpstring("SETRATEMODEL")] HRESULT SETRATEMODEL( [in] VARIANT * var_in ) ;
[id(2), helpstring("GETRATETERMSTRUCTURE")] HRESULT GETRATETERMSTRUCTURE( [in, out] VARIANT * var_in ) ;
};
interface IVolatilityModel : IDispatch{
[id(1), helpstring("SETVOLATILITYMODEL")] HRESULT SETVOLATILITYMODEL( [in] VARIANT * var_in ) ;
[id(2), helpstring("GETVOLATILITY")] HRESULT GETVOLATILITY( [in, out] VARIANT * var_in ) ;
};
interface IMyOption : IDispatch{
[id(1), helpstring("SETMATURITY")] HRESULT SETMATURITY( [in] VARIANT * TheMaturity, [out,retval] IMyOption ** ret ) ;
[id(2), helpstring("SETSTRIKE")] HRESULT SETSTRIKE( [in] VARIANT * TheStrike, [out,retval] IMyOption ** ret ) ;
[id(3), helpstring("SETPAYOFF")] HRESULT SETPAYOFF( [in] VARIANT * ThePayoff, [out,retval] IMyOption ** ret ) ;
[id(4), helpstring("ATTACHRATEMODEL")] HRESULT ATTACHRATEMODEL( [in] IRateModel ** TheRateModel, [out,retval] IMyOption ** ret ) ;
[id(5), helpstring("ATTACHVOLATILITYPROCESS")] HRESULT ATTACHVOLATILITYPROCESS( [in] IVolatilityModel ** TheVolatilityModel, [out,retval] IMyOption ** ret ) ;
[id(6), helpstring("PRICEIT")] HRESULT PRICEIT( [in, out] DOUBLE * price ) ;
};
SETRATEMODEL的实现是:
STDMETHODIMP CRateModel::SETRATEMODEL( /*[in]*/ VARIANT * var_in )
{
// something
// ...
return S_OK ;
}
自从我添加了其他接口后,这个实现没有改变。在添加它们之前,在调试时,变量是VT_R8(来自vba变量,这一个来自excel的double)。现在在调试时,变量是VT_分派
PS:我是ATL/COM的新手。类似这样的:
interface IMyInterface {
HRESULT DoSomething([in] long someParam, [out, retval] IMyInterface** ret);
HRESULT DoSomethingElse([out, retval] IMyInterface** ret);
};
脚本客户端应该能够执行
myObj.DoSomething(42).DoSomethingElse()
根据Igor Tandetnik的第一个答案,我尝试了ATL/COM的链接方法,如下所示,在名为“Complex”的简单ATL/COM对象中,对复数进行建模:
在IDL文件中:
[id(1), helpstring("SET")] HRESULT SET( [in/*,out*/] VARIANT * var_inx, [in/*,out*/] VARIANT * var_iny ) ;
[id(2), helpstring("SETREALPART")] HRESULT SETREALPART( [in] VARIANT * var_inx, [out, retval] IComplex** ret ) ;
[id(3), helpstring("SETIMAGPART")] HRESULT SETIMAGPART( [in] VARIANT * var_iny, [out, retval] IComplex** ret ) ;
[id(4), helpstring("MODULE")] HRESULT MODULE( [out, retval] VARIANT * var_out ) ;
在Complex.h文件中:
class ATL_NO_VTABLE CComplex :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CComplex, &CLSID_Complex>,
public IDispatchImpl<IComplex, &IID_IComplex, &LIBID_ATLSimpleChainingTestLib, /*wMajor =*/ 1, /*wMinor =*/ 0>
{
public:
CComplex() ;
CComplex( double x, double y ) ;
CComplex & setRealPart( double x );
CComplex & setImagPart( double y );
void setRealPart2( double x );
void setImagPart2( double y );
double getRealPart( void ) ;
double getImagPart( void ) ;
double getModule( void ) ;
private:
double _RealPart ;
double _ImagPart ;
public:
DECLARE_REGISTRY_RESOURCEID(IDR_COMPLEX)
BEGIN_COM_MAP(CComplex)
COM_INTERFACE_ENTRY(IComplex)
COM_INTERFACE_ENTRY(IDispatch)
END_COM_MAP()
DECLARE_PROTECT_FINAL_CONSTRUCT()
HRESULT FinalConstruct()
{
return S_OK;
}
void FinalRelease()
{
}
public:
STDMETHOD( SET )( /*[in]*/ VARIANT * var_inx, /*[in]*/ VARIANT * var_iny ) ;
STDMETHOD( SETREALPART )( /*[in]*/ VARIANT * var_inx, /*[out, retval]*/ IComplex** ret ) ;
STDMETHOD( SETIMAGPART )( /*[in]*/ VARIANT * var_iny, /*[out, retval]*/ IComplex** ret ) ;
//STDMETHOD( SETREALPART )( /*[in]*/ VARIANT * var_inx ) ;
//STDMETHOD( SETIMAGPART )( /*[in]*/ VARIANT * var_iny ) ;
STDMETHOD( MODULE )( /*[out, retval]*/ VARIANT * var_out ) ;
};
OBJECT_ENTRY_AUTO(__uuidof(Complex), CComplex)
GET用MyVARIANT myvarx的coeff(0,0)填充ATL::CComVariant myccomvarx
人们很容易猜到是什么
GETNBLINES()
及
方法正在发挥作用。在
MyVARIANT module( &mod, 1, 1) ;
module.ATTACH( var_out ) ;
ATTACH方法用构造函数构造的MyVARIANT“module”来“填充”变量var_
MyVARIANT( double *, long, 1)
将MyVARIANT与指向double的指针关联(在本例中)。让我再说一遍,MyVARIANT已经过全面的回溯测试,并且完全有效
现在,在VBA for Excel端,我创建了以下六个函数:
Function calcmodule11(ByRef x As Variant, ByRef y As Variant) As Variant
Dim z As ATLSimpleChainingTestLib.Complex
Set z = New ATLSimpleChainingTestLib.Complex
Call z.SET(x, y)
calcmodule11 = z.module()
End Function
Function calcmodule12(ByRef x As Variant, ByRef y As Variant) As Variant
Dim z As ATLSimpleChainingTestLib.Complex
Set z = New ATLSimpleChainingTestLib.Complex
Dim xx As Variant
xx = x
Dim yy As Variant
yy = y
Call z.SET(xx, yy)
calcmodule12 = z.module()
End Function
Function calcmodule21(ByRef x As Variant, ByRef y As Variant) As Variant
Dim z As ATLSimpleChainingTestLib.Complex
Set z = New ATLSimpleChainingTestLib.Complex
z.SETREALPART (x)
z.SETIMAGPART (y)
calcmodule21 = z.module()
End Function
Function calcmodule22(ByRef x As Variant, ByRef y As Variant) As Variant
Dim z As ATLSimpleChainingTestLib.Complex
Set z = New ATLSimpleChainingTestLib.Complex
Dim xx As Variant
xx = x
Dim yy As Variant
yy = y
z.SETREALPART (xx)
z.SETIMAGPART (yy)
calcmodule22 = z.module()
End Function
Function calcmodule31(ByRef x As Variant, ByRef y As Variant) As Variant
Dim z As ATLSimpleChainingTestLib.Complex
Set z = New ATLSimpleChainingTestLib.Complex
z.SETREALPART(x).SETIMAGPART (y)
calcmodule31 = z.module()
End Function
Function calcmodule32(ByRef x As Variant, ByRef y As Variant) As Variant
Dim z As ATLSimpleChainingTestLib.Complex
Set z = New ATLSimpleChainingTestLib.Complex
Dim xx As Variant
xx = x
Dim yy As Variant
yy = y
Call z.SETREALPART(x).SETIMAGPART(y)
calcmodule32 = z.module()
End Function
我在excel单元格中调用了这六个函数中的每一个F(即,F等于calcmodule11,或calcmodule12,或…等等),编写
=F(B3,B4)
其中,B3和B4是两个excel单元格,每个单元格包含双1。以下是每个函数的结果:
calcmodule11#值!
calcmodule12 1.414213562
calcmodule21 1.414213562
calcmodule22#值!
calcmodule31#值!
calcmodule32#值
1.414213562确实是正确的预期值
问题:
1) 为什么我有一个#值!打电话给calcmodule11
2) 由于calcmodule12给出了正确的值,而calcmodule11没有给出正确的值,因此我希望该对(calcmodule21、calcmodule22)具有相同的行为,但事实恰恰相反:calcmodule21给出了正确的值,而calcmodule22没有。为什么?
2) 当Igor Tandetnik解释它是我问题的第一个答案时,我在函数calcmodule31和calcmodule32中放置了方法链接。它不起作用,在calcmodule21和calcmodule22案例中,至少在calcmodule21中起作用。为什么?
伊戈尔·坦德尼克(Igor Tandetnik),我完全按照你的建议(如果我错了,请纠正我),为什么它不起作用呢
Thx很多。好的,这个值!是在函数calcmodule11中引起的,因为作为变量传递给它的是“VARIANT/Object/Range”,其value2组件是VARIANT/double,并且我没有在MyVARIANT包装类中处理VARIANT/Object/Range。但是如果y通过x.value2(在vba中)执行该方法,则一切正常。这也解释了为什么这个把戏将xx作为变量,xx=x函数:这样做会以某种方式将x.value2放入xx,但我不知道为什么。。。为了#价值!在涉及方法链接的VBA函数中,原因是相同的,只是变量更复杂:指向com obj实例的指针
因此,我必须重写/完成我的MyVARIANT类,以处理所有将出现的VT_分派情况,如“VARIANT/Object/Range”,但也要处理更复杂的其他VT_分派…,顺便问一下,是否有可能为ATL/COM类1设计方法,以其他ATL/COM类B的实例,或者返回另一个ATL/COM类C的实例?有什么更好的方法?(我仍然处于VBA环境中,参见问题)当然。你一直都在做这件事——比如想想
IClassFactory::CreateInstance
。请注意,在COM中,您不使用类,而是使用接口。您可以使用一个方法,将接口指针作为[in]参数,或将接口指针作为[out]参数返回。我在同一个idl中添加了三个ATL/COM接口,现在是三个接口之一的简单方法,即签名[id(1)、帮助字符串(“SETRATE”)]HRESULT SETRATE([in]VARIANT*var_-in);获取vt的一个变量,该变量等于vt_DISPATCH,而在它之前是vt_R8,因为我在VBA中传递了一个double to。我做错了什么?…你过去常常通过一个双人赛,得到了VT\u R8
。现在您传递一个接口指针,并获得VT\u DISPATCH
。到底是什么让你对这个结果感到惊讶?我想我应该说我是昨天在ATL/COM上开始的,所以我仍然不知道事情到底是如何运作的。(我认为我的问题不足以说明这一点,但不…;-)在我传递一个变量之前,该变量(通过VBA)来自excel单元格中的一个双精度变量,即VT_R8。现在我也这么做了,这个变体“是一个”VT_调度。这是我不明白的,也是让我困惑的。我将编辑我的问题,将idl签名,以便您可以看到我做了什么-糟糕。似乎是VBA的一些怪癖,我必须承认我并不真正熟悉。据我所知,calcmodule11
和calcmodule12
之间的唯一区别在于,参数首先复制到局部变量,然后再传递到方法。我不知道这有什么关系。至于我确实知道的事情:我不得不注意到,您采用/*[out,retval]*/IComplex**ret
的方法实际上没有为[out]
参数分配任何内容。您应该执行类似于*re的操作
MyVARIANT( double *, long, 1)
Function calcmodule11(ByRef x As Variant, ByRef y As Variant) As Variant
Dim z As ATLSimpleChainingTestLib.Complex
Set z = New ATLSimpleChainingTestLib.Complex
Call z.SET(x, y)
calcmodule11 = z.module()
End Function
Function calcmodule12(ByRef x As Variant, ByRef y As Variant) As Variant
Dim z As ATLSimpleChainingTestLib.Complex
Set z = New ATLSimpleChainingTestLib.Complex
Dim xx As Variant
xx = x
Dim yy As Variant
yy = y
Call z.SET(xx, yy)
calcmodule12 = z.module()
End Function
Function calcmodule21(ByRef x As Variant, ByRef y As Variant) As Variant
Dim z As ATLSimpleChainingTestLib.Complex
Set z = New ATLSimpleChainingTestLib.Complex
z.SETREALPART (x)
z.SETIMAGPART (y)
calcmodule21 = z.module()
End Function
Function calcmodule22(ByRef x As Variant, ByRef y As Variant) As Variant
Dim z As ATLSimpleChainingTestLib.Complex
Set z = New ATLSimpleChainingTestLib.Complex
Dim xx As Variant
xx = x
Dim yy As Variant
yy = y
z.SETREALPART (xx)
z.SETIMAGPART (yy)
calcmodule22 = z.module()
End Function
Function calcmodule31(ByRef x As Variant, ByRef y As Variant) As Variant
Dim z As ATLSimpleChainingTestLib.Complex
Set z = New ATLSimpleChainingTestLib.Complex
z.SETREALPART(x).SETIMAGPART (y)
calcmodule31 = z.module()
End Function
Function calcmodule32(ByRef x As Variant, ByRef y As Variant) As Variant
Dim z As ATLSimpleChainingTestLib.Complex
Set z = New ATLSimpleChainingTestLib.Complex
Dim xx As Variant
xx = x
Dim yy As Variant
yy = y
Call z.SETREALPART(x).SETIMAGPART(y)
calcmodule32 = z.module()
End Function
=F(B3,B4)