>Edit :
我有一个ATL简单对象MyATLObject,只有一个方法:
STDMETHODIMP CMyATLObject::EVAL( DOUBLE* x, long AddressOfFunc )
{
*x = toto<FCTPTR>(*((FCTPTR) AddressOfFunc)) ;
return S_OK;
}
其中 toto 是一个模板函数,由下式定义
#pragma once
template<typename F>
double toto( F f )
{
return f(0.0) ;
}
以及 FCTPTR 被定义为
双打型 (__stdcall * FCTPTR)(双);
我的 ATL 方法使用双 x 来存储 toto 的结果,并使用长 AddressOfOfFunc 这是 VBA 函数的地址。
此按地址将 VBA 函数传递给 ATL 方法。 这是相当可怕的。否则,它如何能够将相同的操作(将VBA函数传递给ATL方法),例如通过在ATL端定义接口?
谢谢。
//
我的问题的第一个版本:
我实际上正在执行以下操作:创建一个 ATL/COM 项目,向其添加一个名为 MyATLObject 的"简单 ATL 对象":
1) 在 idl 文件中:
interface IMyATLObject : IDispatch{
[id(1), helpstring("method EVAL")] HRESULT EVAL(DOUBLE* x, long AddressOfFunc) ;
};
MyATLObject.h 文件中的 2 个
:一
#include "MyStupidEvaluator.h"
和
typedef double (__stdcall * FCTPTR)( double );
课外,课堂内
public:
STDMETHOD(EVAL)(DOUBLE* x, long AddressOfFunc) ;
最后在 MyATLObject.cpp 文件中:
STDMETHODIMP CMyATLObject::EVAL( DOUBLE* x, long AddressOfFunc )
{
*x = toto<FCTPTR>(*((FCTPTR) AddressOfFunc)) ;
return S_OK;
}
MyStupidEvaluator.h 包含:
#pragma once
template<typename F>
double toto( F f )
{
return f(0.0) ;
}
这只是一个模板函数,它返回任何函数对象的零值,即允许 () 运算符的 typename(或类)。
现在,这给了我,编译后,一个dll。
这就是 c++ 部分的全部内容。现在,我在 VBA 和 VBA 中引用了这个 dll:
a) 我定义一个函数
Public Function F(ByVal x As Double) As Double
F = x * x - 2 * x + 1
End Function
b) 和子
Public Sub Draft1()
Dim ENGINE As MyTestProjectLib.MyATLObject
Set ENGINE = New MyTestProjectLib.MyATLObject
Dim x As Double
x = 0#
Call ENGINE.EVAL(x, AddressOf F)
Sheets("Test1").Range("Value_at_0").Offset(0, 0).Value = x
End Sub
c) 执行此子将在工作表"Test1"的 V"alue_at_0"(此处只是一个单元格)中给我函数 F 的 0.0 值。
我总是这样工作:toto 模板函数在这里微不足道(评估为 0.0),但总的来说,它可能是一个数值积分例程,或者需要 c++ 才能快速的寻根例程;我正在通过他们的地址传递 VBA 函数,这要归功于 AddressOf VBA 关键字:这给了我一个长的时间,我传递给我的 ATL 方法 EVAL,我在函数指针 (FCTPTR) p 中转换了这个长,我将我的例程"toto"应用于 *p,这给了我一个双精度,我把它传回我的 ATL 方法。
这很酷,一切正常,但是...我觉得这很糟糕!!而且真的很不优雅。这就是为什么我想做以下事情:
在ATL端设计"以某种方式"一个接口,一个
interface IMyFunction : IDispatch
这将由 VBA 类 VBAClass1 在 VBA 中实现(通过 VBA 的实现),并将该 VBA 类的实例传递给我以前的 VBA 方法的新版本,以便在 0.0 处执行评估。
我的问题是:我根本不是ATL方面的专家,也不是界面创建方面的专家:我已经成功地在界面创建中做了真正愚蠢/琐碎的事情,好吧,但我真的不知道如何设计界面做我想做的事情,那就是:
ATL 中的一个接口(根据定义,它只有方法,通过 ATL 构造!),它将具有"某些东西"扮演类成员的角色,成员跟踪 VBA 函数仍需通过 ATL 方法传递给他。
伙计们,任何帮助将不胜感激。
这是我第一次来这里,所以如果消息不是完美/最佳形式,请提前道歉。
提前谢谢你。
拉夫
您应该重新考虑有关参数和回调地址AddressOfFunc
所有内容。当您设计 COM 接口并希望提供回调时,您需要将可调用的 COM 接口指针作为参数传递(相关讨论),以便 COM 类将回调其方法 - 这将要求您的 VBA 类实现此接口(相关问题)。如果您不想在 VBA 端实现接口,另一种选择是设计具有事件(连接点)的 ATL COM 类,以便 COM 类将触发事件,并且调用方将在那里处理它并执行回调活动。
函数的普通地址在这里不起作用,当你不得不投射东西以使它们甚至编译时,你应该怀疑它。
UPD。这提供了有关如何回调 VB 代码的示例:从 C++/ATL 类实现 VBScript(VB6、VBA)回调的三种方法