6

所以,我有一個簡單的事件庫,用C++編寫並使用Boost庫。我想把這個庫暴露給Python,所以自然我轉向了Boost :: Python。最終我得到了編譯代碼,但現在我面臨着相當多的問題:我的庫使用高階編程技術。例如,庫由三個主要類組成:事件類,事件管理器類和事件偵聽器類。事件監聽器類提出了一個問題。代碼:使用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 2012-02-27 21:58:12

回答

2

你需要一個圍繞setResponse的包裝,它需要一個boost::python::object而不是一個函數。它應該將此bp::object存儲在已知位置(可能是listener子類的成員變量)。

然後通過不同的C++函數,基地setResponse,會知道如何查找和調用函數中bp::object。如果要在不同的線程上調用事件,則還需要確保正確處理python的全局解釋器鎖,如下所述:boost.python not supporting parallelism?

+1

謝謝!我在閱讀本文之前修正了它,使用了幾乎相同的方法。我只是添加了一個額外的模板參數給偵聽器,通過python :: object而不是boost :: function傳入,並用typedef命名爲python_listener。奇蹟般有效。 – chameco 2012-03-02 21:54:06