6

Vì vậy, tôi có một thư viện sự kiện đơn giản, được viết bằng C++ và sử dụng thư viện Boost. Tôi muốn để lộ thư viện nói với Python, vì vậy tự nhiên tôi đã chuyển sang Boost :: Python. Tôi đã nhận được mã để biên dịch, cuối cùng, nhưng bây giờ tôi phải đối mặt với khá vấn đề: thư viện của tôi sử dụng kỹ thuật lập trình bậc cao hơn. Ví dụ, thư viện được tạo thành từ ba lớp chính: một lớp sự kiện, một lớp trình quản lý sự kiện và một lớp trình nghe sự kiện. Lớp người nghe sự kiện đặt ra một vấn đề. Mã số:Lập trình bậc cao hơn bằng cách sử dụng 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; 

Như bạn có thể thấy, hàm setResponse là sự cố. Nó đòi hỏi một hàm được truyền cho nó, và, thật không may, Boost :: Python không áp dụng ma thuật chuyển đổi của nó trong tình huống này. Khi được gọi như sau:

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

nó mang lại cho lỗi này:

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)>) 

Vì vậy, câu hỏi của tôi là, làm thế nào có thể sửa lỗi này? Nó sẽ phải sử dụng quá tải hoặc trình bao bọc, vì tôi muốn thư viện vẫn được gọi là C++.

+0

+1 vì tôi nghĩ rằng Boost :: Python là một ý tưởng rất hay. – zmbq

Trả lời

2

Bạn sẽ cần một trình bao bọc xung quanh setResponse, mất boost::python::object thay vì một hàm. Nó sẽ lưu trữ bp::object này ở một vị trí đã biết (có thể là biến thành viên của lớp con listener).

Sau đó, chuyển một hàm C++ khác vào cơ sở setResponse, sẽ biết cách tra cứu và gọi hàm trong bp::object. Nếu các sự kiện được gọi trên một chủ đề khác, bạn cũng sẽ cần phải đảm bảo xử lý đúng cách Khóa thông dịch toàn cầu của python, như được thảo luận tại đây: boost.python not supporting parallelism?.

+1

Cảm ơn! Tôi đã sửa nó trước khi tôi đọc nó, sử dụng khá nhiều phương pháp tương tự. Tôi vừa thêm một đối số mẫu bổ sung cho trình nghe, được truyền vào đối tượng python :: thay vì hàm boost :: và đặt tên nó là python_listener với một typedef. Làm việc như một say mê. – chameco

Các vấn đề liên quan