Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Following Igor Tandetnik first answer, I've tried chaining methods for ATL/COM as follows, in simple ATL/COM object called "Complex", modelling complex numbers : </p> <p>in the IDL file :</p> <pre><code>[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 ) ; </code></pre> <p>in the Complex.h file :</p> <pre><code>class ATL_NO_VTABLE CComplex : public CComObjectRootEx&lt;CComSingleThreadModel&gt;, public CComCoClass&lt;CComplex, &amp;CLSID_Complex&gt;, public IDispatchImpl&lt;IComplex, &amp;IID_IComplex, &amp;LIBID_ATLSimpleChainingTestLib, /*wMajor =*/ 1, /*wMinor =*/ 0&gt; { public: CComplex() ; CComplex( double x, double y ) ; CComplex &amp; setRealPart( double x ); CComplex &amp; 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) </code></pre> <p>In the Complex.cpp file :</p> <p>// Complex.cpp : Implementation of CComplex</p> <pre><code>#include "stdafx.h" #include "Complex.h" #include &lt;cmath&gt; #include "MYVARIANT.h" // CComplex CComplex::CComplex( void ) { } CComplex::CComplex( double x, double y ) { _RealPart = x ; _ImagPart = y ; } CComplex &amp; CComplex::setRealPart( double x ) { _RealPart = x ; return *this ; } void CComplex::setRealPart2( double x ) { _RealPart = x ; } CComplex &amp; CComplex::setImagPart( double y ) { _ImagPart = y ; return *this ; } void CComplex::setImagPart2( double y ) { _ImagPart = y ; } double CComplex::getRealPart( void ) { return _RealPart ; } double CComplex::getImagPart( void ) { return _ImagPart ; } double CComplex::getModule( void ) { return std::sqrt( _RealPart*_RealPart + _ImagPart*_ImagPart ) ; } STDMETHODIMP CComplex::SET( /*[in]*/ VARIANT * var_inx, /*[in]*/ VARIANT * var_iny ) { MyVARIANT myvarx( var_inx ) ; MyVARIANT myvary( var_iny ) ; if ( myvarx.GETNBLINES()*myvarx.GETNBCOLS()*myvary.GETNBLINES()*myvary.GETNBCOLS() != 1L ) return E_INVALIDARG ; ATL::CComVariant myccomvarx ; ATL::CComVariant myccomvary ; myvarx.GET(0, 0, myccomvarx ) ; myvary.GET(0, 0, myccomvary ) ; if ( ( myccomvarx.vt != VT_R8 ) || ( myccomvary.vt != VT_R8 ) ) return E_INVALIDARG ; setRealPart2( myccomvarx.dblVal ) ; setImagPart2( myccomvary.dblVal ) ; return S_OK ; } STDMETHODIMP CComplex::SETREALPART( /*[in]*/ VARIANT * var_inx, /*[out, retval]*/ IComplex** ret ) //STDMETHODIMP CComplex::SETREALPART( /*[in]*/ VARIANT * var_inx ) { MyVARIANT myvarx( var_inx ) ; if ( myvarx.GETNBLINES()*myvarx.GETNBCOLS() != 1L ) return E_INVALIDARG ; ATL::CComVariant myccomvarx ; myvarx.GET(0, 0, myccomvarx ) ; if ( myccomvarx.vt != VT_R8 ) return E_INVALIDARG ; setRealPart2( myccomvarx.dblVal ) ; return S_OK ; } STDMETHODIMP CComplex::SETIMAGPART( /*[in]*/ VARIANT * var_iny, /*[out, retval]*/ IComplex** ret ) //STDMETHODIMP CComplex::SETIMAGPART( /*[in]*/ VARIANT * var_iny ) { MyVARIANT myvary( var_iny ) ; if ( myvary.GETNBLINES()*myvary.GETNBCOLS() != 1L ) return E_INVALIDARG ; ATL::CComVariant myccomvary ; myvary.GET(0, 0, myccomvary ) ; if ( myccomvary.vt != VT_R8 ) return E_INVALIDARG ; setImagPart2( myccomvary.dblVal ) ; return S_OK ; } STDMETHODIMP CComplex::MODULE( /*[out, retval]*/ VARIANT * var_out ) { double mod = getModule() ; MyVARIANT module( &amp;mod, 1, 1) ; module.ATTACH( var_out ) ; return S_OK ; } // </code></pre> <p>MyVARIANT is a VARIANT wrapper class, that works perfectly and that as been fully backtested. In</p> <pre><code>ATL::CComVariant myccomvarx ; myvarx.GET(0, 0, myccomvarx ) ; </code></pre> <p>GET fills the ATL::CComVariant myccomvarx with the coeff (0,0) of the MyVARIANT myvarx.</p> <p>One can easily guess what</p> <pre><code>GETNBLINES() </code></pre> <p>and</p> <pre><code>GETNBCOLS() </code></pre> <p>methods are doing. In</p> <pre><code>MyVARIANT module( &amp;mod, 1, 1) ; module.ATTACH( var_out ) ; </code></pre> <p>the method ATTACH "fills" the VARIANT var_out with the MyVARIANT "module" constructed by the constructor</p> <pre><code>MyVARIANT( double *, long, 1) </code></pre> <p>which assciates (in this case) a MyVARIANT to a pointer to double. Let me say again that MyVARIANT has been fully backtested, and that it fully works.</p> <p>Now, on the VBA for Excel side, I created the six following functions :</p> <pre><code>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 </code></pre> <p>I called each of these six functions F (that, F is equal to calcmodule11, or calcmodule12, or... etc) in a excel cell, writing</p> <pre><code>=F(B3,B4) </code></pre> <p>in it, where B3 and B4 are two excel cells containing each the double 1. Here are the results obtained for each function :</p> <p>calcmodule11 #VALUE! calcmodule12 1.414213562 calcmodule21 1.414213562 calcmodule22 #VALUE! calcmodule31 #VALUE! calcmodule32 #VALUE!</p> <p>1.414213562 is indeed the right value expected.</p> <p>Questions :</p> <p>1) Why do I have a #VALUE! for the call to calcmodule11 ?</p> <p>2) As calcmodule12 gives the right value and calcmodule11 not, I would expected the same behaviour for the pair (calcmodule21, calcmodule22), but it is the contrary : calcmodule21 gives the right value, and calcmodule22 not. Why ?</p> <p>2) As Igor Tandetnik explained it its first answer to my question, I put method chaining in place in functions calcmodule31 and calcmodule32. And it doesn't work, where it work in the calcmodule21 and calcmodule22 case, at least for calcmodule21. Why ?</p> <p>Igor Tandetnik, as I put in place exactly what you advised to me (correct me if I'm wrong), why doesn't it work ?...</p> <p>Thx a lot.</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload