在 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)
在 Complex.cpp 文件中:
// Complex.cpp : CComplex 的实现
#include "stdafx.h"
#include "Complex.h"
#include <cmath>
#include "MYVARIANT.h"
// CComplex
CComplex::CComplex( void )
{
}
CComplex::CComplex( double x, double y )
{
_RealPart = x ;
_ImagPart = y ;
}
CComplex & CComplex::setRealPart( double x )
{
_RealPart = x ;
return *this ;
}
void CComplex::setRealPart2( double x )
{
_RealPart = x ;
}
CComplex & 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( &mod, 1, 1) ;
module.ATTACH( var_out ) ;
return S_OK ;
}
//
MyVARIANT 是一个 VARIANT 包装类,可以完美运行并且经过全面回测。在
ATL::CComVariant myccomvarx ;
myvarx.GET(0, 0, myccomvarx ) ;
GET 用 MyVARIANT myvarx 的系数 (0,0) 填充 ATL::CComVariant myccomvarx。
很容易猜到是什么
GETNBLINES()
和
GETNBCOLS()
方法正在做。在
MyVARIANT module( &mod, 1, 1) ;
module.ATTACH( var_out ) ;
方法 ATTACH 用构造函数构造的 MyVARIANT“模块”“填充”VARIANT var_out
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 #VALUE!calcmodule31 #值!calcmodule32 #值!
1.414213562 确实是预期的正确值。
问题 :
1)为什么我有一个#VALUE!调用 calcmodule11 ?
2)由于 calcmodule12 给出了正确的值而 calcmodule11 没有,我希望这对(calcmodule21,calcmodule22)有相同的行为,但事实恰恰相反:calcmodule21 给出了正确的值,而 calcmodule22 没有。为什么 ?
2) 正如 Igor Tandetnik 解释它对我的问题的第一个答案,我将方法链接放在函数 calcmodule31 和 calcmodule32 中。而且它不起作用,它在 calcmodule21 和 calcmodule22 的情况下工作,至少对于 calcmodule21。为什么 ?
Igor Tandetnik,正如我完全按照您对我的建议(如果我错了,请纠正我),为什么它不起作用?...
多谢。