2

何かを試して、いくつかのボイラープレート コードを動的ライブラリ API ラッパーの 1 つに統合したいと考えています。

本質的に、私は次のことをしたいと思います:

typedef bool (*MyFPtrT)(long id, std::string const& name);
typedef boost::function<bool (long id, std::string const& name)> MyFObjT;
...

...
  MyFPtrT pDllFun = NULL;
  long x = 42; string s = "Answer"; // API input, not hardcoded
  MyFObjT f = boost::bind(pDllFun, x, s);
  ...
  return Call(f);
...

template<FT>
bool Call(FT f) {
  ...
  MyFPtrT pDllFun = (MyFunPtr)::GetProcAddress(...);
  f.setFunctionPointerButLeaveBoundParameters(pDllFun); // <- how??
  // Now call the correctly rigged up function object:
  return f();
}

これは可能ですか?(Boost かそれ以外か?) ( C++03 )

4

2 に答える 2

2

bind関数オブジェクトと引数を参照によって受け取る新しいオブジェクトを作成し、参照を再バインドできないため、そのように直接実行できるとは思いません。

ただし、再割り当て可能な関数ポインターを使用して、独自のテンプレート化されたファンクター ラッパーを簡単に作成できます。

template <typename R, typename A, typename B>
struct ReAssFunctor
{
  typedef R(*FP)(A, B);

  ReAssFunctor(const A & a_, const B & b_) a(a_), b(b_) { }

  R operator()() const { return func(a, b); }

  FP function;

private:
  const A & a;
  const B & b;
};

[編集:] 以下のコメントを確認してください。コンストラクターで const 参照によって取得された参照を保持することは、危険なほど乱用される可能性があるため、注意するか、必要に応じて保存abて値を指定してください。[/]

これで、早い段階で引数を使用してファンクターを初期化できます。

ReAssFunctor<R, A, B> raf(a, b);

次に、関数ポインターを割り当てて呼び出します。

raf.function = foo;
raf();

raf.function = goo;
raf();

呼び出し演算子を次のように置き換えることもできます。

  template <typename U>
  U operator()(U (f*)(A, B)) const { return f(a, b); }

次に、関数ポインターを引数としてファンクターを呼び出します。

raf(fp1);  // calls fp1(a,b);
raf(fp2);  // calls fp2(a,b);

その場合、戻り値の型を固定パラメーターとして使用する必要はなくなりますが、nullary 呼び出し演算子は取得できなくなります。好きなのを選びな。

于 2011-08-11T15:40:33.860 に答える
1

以下がうまくいくようです:

typedef bool (*MyFPtrT)(long id, std::string const& name);
typedef boost::function<bool (long id, std::string const& name)> MyFObjT;
...

...
  MyFPtrT pDllFun = NULL;
  long x = 42; string s = "Answer"; // API input, not hardcoded
  MyFObjT f = boost::bind(boost::ref(pDllFun), x, s);
  ...
  return Call(f, pDllFun);
...

template<class FT, class FP>
bool Call(FT f, FP& pDllFun) {
  pDllFun = (MyFunPtr)::GetProcAddress(...);
  return f();
}

ええ、そこには危険な参照がいくつかあります。特に、fへの参照を保持しますpDllFun。これはかなり簡単に軽減できます。2 つを 1 つのクラスにまとめて、寿命が明らかに同じになるようにします。

于 2011-08-12T10:57:36.600 に答える