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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了将实现ATL接口的VBA类传递给ATL方法相关的知识,希望对你有一定的参考价值。

编辑:

我有一个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"

和a

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方面的接口,a

interface IMyFunction : IDispatch

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

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

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

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

这是我第一次来这里,如果消息不是完美/最佳的形式,那么每次提前都很抱歉。

先感谢您。

拉夫

答案

您应该重新考虑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

以上是关于将实现ATL接口的VBA类传递给ATL方法的主要内容,如果未能解决你的问题,请参考以下文章

ATL/COM 对象的链接方法

如何通过 InvokeHelper 将 variant* 传递给 C#?

使用 ATL 编译 dll,将方法参数作为接口,但将它们作为 coclasses

创建实现特定接口的 ATL COM 对象

如何添加atl工程实现接口实现ipersistfile

WinRT/Metro 风格应用程序中基于 ATL 的 COM 对象