将实现ATL接口的VBA类传递给ATL方法

时间:2012-08-07 12:30:07

标签: vba dll interface atl address-operator

修改:

我有一个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定义为

typedef double(__stdcall * FCTPTR)(double);

我的ATL方法使用双x来存储toto的结果,并使用长的AddressOfFunc作为VBA函数的AddressOf。

通过Address将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) ;
}

这只是一个模板函数,它返回任何函数对象的零值,即允许a()运算符的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“to * p,这给了我一个双倍,我传回我的ATL方法。

这很酷,一切正常,但......我发现这太可怕了!而且真的很不优雅。这就是为什么我想做以下事情:

设计“某种程度上”ATL方面的接口,

interface IMyFunction : IDispatch

将通过VBA类VBAClass1在VBA中实现(通过VBA的实现),并将该VBA类的实例传递给我以前的VBA方法的新版本,以便在0.0处执行评估。

我的问题是:我不是ATL的专家,也不是界面创建的专家:我已经成功地在界面创建中做了真正的愚蠢/琐碎的事情,好吧,但我真的不知道如何设计界面做我想做的事,那就是:

ATL中的一个接口(按照定义只有方法,通过ATL构造!),它将具有扮演类成员角色的“某事”,成员跟踪仍然要传递给他的VBA函数通过ATL方法。

任何帮助都会非常感谢,伙计们。

这是我第一次来这里,如果消息不是完美/最佳形式的话,请提前对不起。

提前谢谢。

拉​​夫

1 个答案:

答案 0 :(得分:0)

您应该重新考虑围绕AddressOfFunc参数和回调地址的所有内容。当你设计COM接口并且你想提供一个回调时,你需要传递一个可调用的COM接口指针作为参数(related discussion),这样COM类就会调用它的方法 - 这需要你的VBA类实现此接口(related question)。如果您不想在VBA端实现接口,另一个选择是使用事件(connection points)设计ATL COM类,以便COM类将触发事件,并且调用者将在那里处理它执行回调活动。

函数的普通地址在这里不起作用,当你不得不编译它们以使它们甚至编译时你应该怀疑它。

<强> UPD 即可。这提供了有关如何回调VB代码的示例:Three ways to implement VBScript (VB6, VBA) callback from C++/ATL class