I have the following sample code which obtains a py::list
as the output of evaluating some python code.
I would like to convert it to a std::vector<std::string>
, but am getting an error:
conversion from 'pybind11::list' to non-scalar type 'std::vector<std::__cxx11::basic_string<char> >' requested
Per the documentation:
When including the additional header file
pybind11/stl.h
, conversions betweenstd::vector<>
/std::deque<>
/std::list<>
/std::array<>
/std::valarray<>
,std::set<>
/std::unordered_set<>
, andstd::map<>
/std::unordered_map<>
and the Pythonlist
,set
anddict
data structures are automatically enabled.
As you can see from the below code example, I have included stl.h
, but automatic conversion doesn't work.
#include <iostream>
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/eval.h>
namespace py = pybind11;
py::list func()
{
py::object scope = py::module_::import("__main__").attr("__dict__");
return py::eval("[ 'foo', 'bar', 'baz' ]", scope);
}
int main()
{
Py_Initialize();
// call the function and iterate over the returned list of strings
py::list list = func();
for (auto it : list)
std::cout << py::str(it) << '\n';
// error
// conversion from 'pybind11::list' to non-scalar type 'std::vector<std::__cxx11::basic_string<char> >' requested
std::vector<std::string> vec = list;
for (auto str : vec)
std::cout << str << '\n';
return 0;
}
I can iterate over the py::list
manually and call vector::push_back
with each element
// populating the vector manually myself works
std::vector<std::string> vec;
vec.reserve(list.size());
for (auto it : list)
vec.push_back(py::str(it));
So I guess the linked documentation above only refers to c -> python conversions, and not the other way?
What is the recommended way to convert from py::list
to std::vector
?
CodePudding user response:
You need to call .cast<>
:
auto vec = list.cast<std::vector<std::string>>();
<pybind11/stl.h>
simply brings specializations of the conversion templates that allow such cast, and that also allow implicit conversion when you bind function with vector arguments or returning vectors (or other standard containers).