Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

pybind11: convert py::list to std::vector<std::string>

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:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

When including the additional header file pybind11/stl.h, conversions
between
std::vector<>/std::deque<>/std::list<>/std::array<>/std::valarray<>,
std::set<>/std::unordered_set<>, and std::map<>/std::unordered_map<>
and the Python list, set and dict 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?

>Solution :

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

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading