将实现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方法的主要内容,如果未能解决你的问题,请参考以下文章
如何通过 InvokeHelper 将 variant* 传递给 C#?