2011-05-27 49 views
30

我有一個方法在c + +從python調用,需要返回一個python列表對象。std ::向量提升:: python ::列表

我已經創建了該方法,並將其附加到一個暴露的類並可以從python調用,現在...(它返回void)。

所以現在的問題是,如何從這個創建一個Python列表:

std::vector<std::string> results;

我沒有真正理解構造函數從該文件是如何工作的:

http://www.boost.org/doc/libs/1_37_0/libs/python/doc/v2/list.html

另外...我真的不想返回一種包裝的矢量...我只是想創建一個新的Python列表與矢量字符串值。

我很抱歉,如果這是一個重複的...我發現了很多列表矢量的問題,但我找不到任何關於創建一個新的Python列表。

我可能會擴大這個問題,包括一些其他的問題,如:std::map<std::string, std::string>等:

從創建一個新的Python字典。

+0

我看到了這樣一個問題:http://stackoverflow.com/questions/3240971/does-boost-python-support-a-function-返回一個矢量的參考或值 但那是在談論返回一個包裝的矢量......我只是想創建一個新的python對象並返回它。 – mcot 2011-05-27 20:37:40

+0

可能的重複:http://stackoverflow.com/q/5314319/198633 – inspectorG4dget 2017-04-10 19:36:13

回答

11

我使用了迭代器來轉換std::vectorpy::list有此功能:

namespace py = boost::python; 

template<class T> 
py::list std_vector_to_py_list(const std::vector<T>& v) 
{ 
    py::object get_iter = py::iterator<std::vector<T> >(); 
    py::object iter = get_iter(v); 
    py::list l(iter); 
    return l; 
} 
+0

沒有這麼大的開銷? 這真的是一個問題 – 2012-07-02 09:56:18

+3

我試過這個,我得到一個'py :: object iter = get_iter(v)':'找不到to_python(by-value)轉換器的C++類型的異常:class std :: vector >同樣Boost 1.51 – 2012-11-11 23:28:02

+4

'找不到to_python(by-value)轉換器的C++類型:std :: vector >',boost 1.48 – 2013-09-18 13:56:47

44

boost::python已包含用於包裝向量和地圖的功能。下面是向量的示例代碼,你可以看到兩個傳遞和返回列表很簡單:

// C++ code 
typedef std::vector<std::string> MyList; 
class MyClass { 
    MyList myFuncGet(); 
    void myFuncSet(const Mylist& list); 
    //  stuff 
}; 

// Wrapper code 

#include <boost/python/suite/indexing/vector_indexing_suite.hpp> 

using namespace boost::python; 


BOOST_PYTHON_MODULE(mymodule) 
{ 
    class_<MyList>("MyList") 
     .def(vector_indexing_suite<MyList>()); 

    class_<MyClass>("MyClass") 
     .def("myFuncGet", &MyClass::myFuncGet) 
     .def("myFuncSet", &MyClass::myFuncSet) 
     ; 
} 

地圖是非常相似的載體和在這個崗位描述: Boost::Python- possible to automatically convert from dict --> std::map?

可惜boost::python目前不包括包裝清單的設施。您可以手動創建包裝,但我沒有時間來解答這個問題。我可以在今天或明天發佈。我很感激關於這個特殊問題的一個新問題,因爲答案會非常廣泛,可能超出了本文的範圍。我只是避免列表,並使用向量。

+0

hello @Aleksey, 我想我有一個相關的問題給你[link](http://stackoverflow.com/q/6776888/814180) – 2011-07-21 13:34:31

8

如果只想手動創建Python列表(並有函數返回PY ::列表,而不是載體),像這樣做:

/* using namespace std; namespace py=boost::python; 
    #define FOREACH BOOST_FOREACH 
*/ 
vector<string> ss; 
py::list ret; 
FOREACH(const string& s, ss) ret.append(s); 
return s; 

對於自動轉換,定義轉換器從矢量python list to C++ and from C++ to python list - 我剛剛在Instantiating shared_ptr's in boost::python(回覆的第二部分)中寫到了這個問題;這樣,你會得到真正的Python列表。

另一種自動轉換(我沒有經驗)的可能性是使用indexing_suite,它將Python作爲一個特殊的類來包裝vector<string>,就像這裏已經提到的一個同事一樣。

1

FWIW,這裏是在同樣的eudoxos的解決方案模板化的功能:

namespace py = boost::python; 

template<class T> 
py::list std_vector_to_py_list(const std::vector<T>& v) 
{ 
    py::list l; 
    typename std::vector<T>::const_iterator it; 
    for (it = v.begin(); it != v.end(); ++it) 
    l.append(*it); 
    return l; 
} 
+0

這會拷貝附加到列表中的值,對吧?有什麼辦法可以避免這種情況(假設這些值是某種類型的),所以在python中get_list(0)== get_list(0)'返回true?像'bp :: reference_existing_object',但在函數內? – GaryO 2014-02-06 18:35:51

6

http://gist.github.com/octavifs/5362272

// Converts a C++ vector to a python list 
template <class T> 
boost::python::list toPythonList(std::vector<T> vector) { 
    typename std::vector<T>::iterator iter; 
    boost::python::list list; 
    for (iter = vector.begin(); iter != vector.end(); ++iter) { 
     list.append(*iter); 
    } 
    return list; 
} 
+1

這一個工程,不像anwser @rafak。謝謝。 – Marcin 2015-11-05 03:10:26

+0

是的,它可以工作,但我不確定是否需要迭代矢量並追加每個元素,從而導致開銷太大。也許使用numpy數組更有效率? – user819893 2018-02-13 18:50:42

1

我使用以下utili ty函數將從/轉換爲stl容器。平凡的和函數說明了它們是如何使用的。此外,我發現其中有相當多的轉換工具以下開源軟件包:https://github.com/cctbx/cctbx_project/tree/master/scitbx/boost_python

#include <vector> 
#include <boost/python.hpp> 
#include <boost/python/object.hpp> 
#include <boost/python/stl_iterator.hpp> 

namespace bpy = boost::python; 

namespace fm { 

template <typename Container> 
bpy::list stl2py(const Container& vec) { 
    typedef typename Container::value_type T; 
    bpy::list lst; 
    std::for_each(vec.begin(), vec.end(), [&](const T& t) { lst.append(t); }); 
    return lst; 
} 

template <typename Container> 
void py2stl(const bpy::list& lst, Container& vec) { 
    typedef typename Container::value_type T; 
    bpy::stl_input_iterator<T> beg(lst), end; 
    std::for_each(beg, end, [&](const T& t) { vec.push_back(t); }); 
} 

bpy::list sum(const bpy::list& lhs, const bpy::list& rhs) { 
    std::vector<double> lhsv; 
    py2stl(lhs, lhsv); 

    std::vector<double> rhsv; 
    py2stl(rhs, rhsv); 

    std::vector<double> result(lhsv.size(), 0.0); 
    for (int i = 0; i < lhsv.size(); ++i) { 
    result[i] = lhsv[i] + rhsv[i]; 
    } 
    return stl2py(result); 
} 

} // namespace fm 

BOOST_PYTHON_MODULE(fm) 
{ 
    bpy::def("sum", &fm::sum); 
}