編集 :
メソッドが 1 つしかない 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 メソッドは、toto の結果を格納するために double x を消費し、VBA 関数の AddressOf である long AddressOfFunc を消費します。
この VBA 関数をアドレスによって ATL メソッドに渡します。それはかなりひどいです。たとえば、ATL側でインターフェイスを定義するなど、そうでなければ、VBA関数をATLメソッドに渡す同じことをどのように行うことができますか?
どうもありがとうございました。
/////////////////////////////////////////////// /////////////////////////////////////////////// /////////////////////////////////////////////// ///////////////////////////////
私の質問の最初のバージョン:
私は実際に次のことを行っています: ATL/COM プロジェクトを作成し、それに MyATLObject という「単純な ATL オブジェクト」を追加します:
1) idl ファイル内:
interface IMyATLObject : IDispatch{
[id(1), helpstring("method EVAL")] HRESULT EVAL(DOUBLE* x, long AddressOfFunc) ;
};
2 MyATLObject.h ファイル内:
を
#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) ;
}
これは、() 演算子を受け入れる型名 (またはクラス) である関数オブジェクトのゼロの値を返す単なるテンプレート関数です。
これで、コンパイル後に 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++ が必要なルート検索ルーチンである可能性があります。AddressOf VBA キーワードのおかげで、私は常に VBA 関数をそのアドレスを介して渡しています。これにより、ATL メソッド EVAL に渡す long が得られ、この long を関数ポインタ (FCTPTR) p に変換し、ルーチンを適用します" toto" を *p に変換すると、ATL メソッドに返される double が返されます。
それはクールです、すべてが機能しますが...私はこれがひどいと思います!!! そして本当にエレガントではありません。それが私が次のことをしたい理由です:
ATL側のインターフェースを「何とか」設計し、
interface IMyFunction : IDispatch
これは、VBA クラス VBAClass1 によって VBA に (VBA の実装を通じて) 実装され、その VBA クラスのインスタンスを以前の VBA メソッドの新しいバージョンに渡して、0.0 で評価を実行します。
私の問題は次のとおりです。私はATLの専門家でも、インターフェイスの作成の専門家でもありません。インターフェイスの作成で本当にばかげた/些細なことをすることに成功しました。私がやりたいこと、つまり:
ATL のインターフェイス (定義上、ATL 構造によってメソッドのみを持ちます!) クラスのメンバーの役割を果たす「何か」を持ち、ATL を介して渡される VBA 関数を追跡するメンバー方法。
皆さん、どんな助けも大歓迎です。
ここに来るのは初めてなので、メッセージが完璧/最適な形式でない場合は、事前に申し訳ありません.
前もって感謝します。
ラフ