6

私はシンプルなイベントライブラリを用意しています。これはC++で書かれており、Boostライブラリを使用しています。私は前記ライブラリをPythonに公開したかったので、当然私はBoost :: Pythonに目を向けるようになりました。最終的には、コンパイルするコードを手に入れましたが、今はかなり問題に直面しています。私のライブラリは、高次プログラミング技術を使用しています。たとえば、ライブラリーは、イベント・クラス、イベント・マネージャー・クラス、およびイベント・リスナー・クラスの3つのメイン・クラスで構成されています。イベントリスナークラスに問題があります。コード:Boost :: Pythonを使用した高次プログラミング

class listener{ 
     public: 
      listener(){} 
      void alert(cham::event::event e){ 
       if (responses[e.getName()]) 
        responses[e.getName()](e.getData()); 
      } 
      void setResponse(std::string n, boost::function<void (std::string d)> c){responses.insert(make_pair(n, c));} 
      void setManager(_manager<listener> *m){manager = m;} 
     private: 
      std::map<std::string, boost::function<void (std::string d)> > responses; 
      _manager<listener> *manager; 

ご覧のとおり、機能setResponseが問題です。残念ながら、Boost :: Pythonはこの状況でコンバータの魔法を適用しません。次のように呼び出されたとき:

>>> import chameleon 
>>> man = chameleon.manager() 
>>> lis = chameleon.listener() 
>>> def oup(s): 
... print s 
... 
>>> lis.setResponse("event", oup) 

それは、このエラーを与える:

Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
Boost.Python.ArgumentError: Python argument types in 
    listener.setResponse(listener, str, function) 
did not match C++ signature: 
    setResponse(cham::event::listener {lvalue}, std::string, boost::function<void()(std::string)>) 

だから、私の質問は、私はこの問題を解決できるか、でしょうか?私はライブラリをC++で呼び出し可能にしたいので、オーバーロードまたはラッパーを使用する必要があります。

+0

+1 Boost :: Pythonは非常にクールなアイデアだと思っています。 – zmbq

答えて

2

setResponseのラッパーが必要です。機能の代わりにboost::python::objectが必要です。これはbp::objectを既知の場所(おそらくlistenerサブクラスのメンバ変数)に格納する必要があります。

setResponseに別のC++関数を渡します。これは、bp::objectで関数を検索して呼び出す方法を知っています。イベントを別のスレッドで呼び出す場合は、boost.python not supporting parallelism?で説明するように、Pythonのグローバルインタープリタロックを適切に処理する必要があります。

+1

ありがとう!私はこれを読む前にそれを修正しました。ほとんど同じ方法論を使っていました。リスナーに追加のテンプレート引数を追加し、boost :: functionではなくpython :: objectに渡し、typedefでpython_listenerという名前を付けました。魅力のように動作します。 – chameco

関連する問題