2010-09-21 273 views
20

最後,我可以使用[]運算符在python中使用std :: vector。訣竅是簡單的在處理內部向量東西升壓C++包裝提供了一個容器:boost :: python:python list to std :: vector

#include <boost/python.hpp> 
#include <vector> 
class world 
{ 
    std::vector<double> myvec; 

    void add(double n) 
    { 
     this->myvec.push_back(n); 
    } 

    std::vector<double> show() 
    { 
    return this->myvec; 
    } 
}; 

BOOST_PYTHON_MODULE(hello) 
{ 
    class_<std::vector<double> >("double_vector") 
     .def(vector_indexing_suite<std::vector<double> >()) 
    ; 

    class_<World>("World") 
    .def("show", &World::show) 
     .def("add", &World::add) 
    ; 
} 

另一個挑戰是:HOWTO Python列表轉換成標準::載體?我嘗試添加C++類期待一個std ::向量作爲參數,並加入相應的包裝代碼:

#include <boost/python.hpp> 
#include <vector> 
class world 
{ 
    std::vector<double> myvec; 

    void add(double n) 
    { 
     this->myvec.push_back(n); 
    } 

    void massadd(std::vector<double> ns) 
    { 
     // Append ns to this->myvec 
    } 

    std::vector<double> show() 
    { 
    return this->myvec; 
    } 
}; 

BOOST_PYTHON_MODULE(hello) 
{ 
    class_<std::vector<double> >("double_vector") 
     .def(vector_indexing_suite<std::vector<double> >()) 
    ; 

    class_<World>("World") 
    .def("show", &World::show) 
     .def("add", &World::add) 
     .def("massadd", &World::massadd) 
    ; 
} 

但是,如果這樣做,我結束了以下Boost.Python.ArgumentError:

>>> w.massadd([2.0,3.0]) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
Boost.Python.ArgumentError: Python argument types in 
    World.massadd(World, list) 
did not match C++ signature: 
    massadd(World {lvalue}, std::vector<double, std::allocator<double> >) 

有人能告訴我如何在我的C++函數中訪問python列表嗎?

感謝, 丹尼爾

回答

23

爲了讓你的C++方法接受Python列表,你應該使用boost::python::list

void massadd(boost::python::list& ns) 
{ 
    for (int i = 0; i < len(ns); ++i) 
    { 
     add(boost::python::extract<double>(ns[i])); 
    } 
} 
+0

'boost :: python :: list'可以是異構的,你也可以從'extract'中捕獲異常。 – eudoxos 2011-08-10 08:08:01

+0

我的道歉,'extract'的異常將自動轉換爲python。抱歉。 – eudoxos 2011-08-12 12:30:58

+4

是啊,很好,很簡單,只是提升python文檔是如此之差,並且operator []隱藏在一個模板object_operators層次上的幾個層次,而不是明顯的操作列表。我還沒有發現他們的網站文檔更友好。 使len()成爲外部方法並不像他們認爲的那樣酷。 Plus是否是迭代的唯一方法? – CashCow 2012-12-17 11:00:27

1

要想從Python列表自動轉換,你必須定義一個轉換器,它

  1. 檢查列表是否可以轉換爲您的類型(即,它是一個序列;此外,您還可以檢查是否所有元素都是重新但是可以在第二步中處理)
  2. 返回新對象,如果第一步成功;如果序列元素不能轉換爲您需要的,則拋出異常。

我現在找不到什麼比我的代碼一樣,你可以複製粘貼& this template(它是專門在該文件中的各種所含類型的結束)。

17

下面是我用什麼:

#include <boost/python/stl_iterator.hpp> 

namespace py = boost::python; 

template< typename T > 
inline 
std::vector<T> to_std_vector(const py::object& iterable) 
{ 
    return std::vector<T>(py::stl_input_iterator<T>(iterable), 
          py::stl_input_iterator<T>()); 
} 

,你應該找到輸入型(PY ::對象)過於寬鬆,隨意(在你的情況PY ::列表)來指定嚴格的類型。

3

基於我創建訪問用C Python列表++以及從C返回Python列表++函數的例子在上述的答案:

#include <boost/python.hpp> 
#include <string> 

namespace py = boost::python; 

// dummy class 
class drow{ 
    public: 
     std::string word; 
     drow(py::list words); 
     py::list get_chars(); 
}; 

// example of passing python list as argument (to constructor) 
drow::drow(py::list l){ 
    std::string w; 
    std::string token; 
    for (int i = 0; i < len(l) ; i++){ 
     token = py::extract<std::string>(l[i]); 
     w += token; 
    } 
    this -> word = w; 
} 

// example of returning a python list 
py::list drow::get_chars(){ 
    py::list char_vec; 
    for (auto c : word){ 
     char_vec.append(c); 
    } 
    return char_vec; 
} 

// binding with python 
BOOST_PYTHON_MODULE(drow){ 
    py::class_<drow>("drow", py::init<py::list>()) 
     .def("get_chars", &drow::get_chars); 
} 

對於一個構建實例和測試Python腳本來看看here

謝謝Arlaharen & rdesgroppes爲指針(雙關語沒有打算)。

相關問題