Methods ATL/COM对象的链接方法 在C++中,我们可以通过设计返回这个方法的方法来轻松地在类中建立方法链。这在ATL/COM设置中可能吗?假设我有一个简单的ATL类MyOBj。我想知道在这种情况下链接是否可行,如果可能,支持链接的方法的idl签名是什么?简单的例子将不胜感激!(事实上,我的方法是从VBA for excel调用的,我希望在该VBA上下文中进行链接,因为我们已经为标准VBA方法进行了链接。)

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

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 * 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)