使用boost :: python,如何将结构的向量作为dicts列表返回给Python?

问题描述 投票:0回答:2

我有以下C ++代码:

    struct MyType { int x, y; };
    struct A { 
        std::vector<MyType> get_data();
    };

我想使用Boost Python与Python连接,以便它可以按以下方式使用:

    a = A()
    ret = a.get_data();
    for r in ret:
        print('x=%d; y=%d;' % (r['x'], r['y']))

我现在拥有的是一个相当天真的:

    BOOST_PYTHON_MODULE(pyA) { 
        class_<A>("A").def("get_data", &A::get_data);
    }

正如预期的那样,这给了我以下错误

     TypeError: No to_python (by-value) converter found for C++ type

当我尝试从Python代码调用get_data()函数时。

我在这里看过帖子(比如std::vector to boost::python::list),它描述了如何使用vector_indexing_suitestd::vector<T>转换为某些类型list(例如浮点数,字符串)的T,但我不知道如何扩展它以处理我的结构 - > dict转换也是如此。任何帮助将不胜感激。

python c++ boost boost-python
2个回答
2
投票

下面,如何将您的C++代码暴露给PythonMyType需要'等于'比较运算符超载,MyType本身也需要接触Python

#include <boost/python.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
using namespace boost::python;

struct MyType { 
    int x, y;  
    bool operator==(const MyType& data) const {
        return this->x == data.x && this->y == data.y;
    }   
};
struct A { 
    std::vector<MyType> get_data() const { return {{1,2},{3,4}};};
};

BOOST_PYTHON_MODULE(pyA) {
    class_<MyType>("MyType")
        .def_readwrite("x", &MyType::x)
        .def_readwrite("y", &MyType::y);
    class_<std::vector<MyType>>("MyList")
        .def(vector_indexing_suite<std::vector<MyType>>());
    class_<A>("A").def("get_data", &A::get_data);
}

下面略微修改了Python脚本。 get_data()返回类型是一个列表,所以它需要这样访问。如果你想让它成为一个字典,那么将它转换为Python中的dict。

import pyA 

a = pyA.A()
ret = a.get_data();
for r in ret:
    print('x=%d; y=%d;' % (r.x, r.y))

1
投票

最后我采用了如下的解决方案,我将在此处发布,以防将来对其他人有用。这可以通过添加boost的“readonly”限定符来改进,但我还没有这样做。

#include <boost/python.hpp>
using namespace boost::python;

struct Point { 
    int x, y;
};

using Points = std::vector<Point>;

struct Converter
{
    static PyObject* convert(const Points& v)
    {
        boost::python::list ret;
        for (const auto& c : v) {
            boost::python::dict *r = new boost::python::dict();
            (*r)["x"] = c.x;
            (*r)["y"] = c.y;
            ret.append(boost::python::object(*r));
         }
        return boost::python::incref(ret.ptr());
    }
};

BOOST_PYTHON_MODULE(mymodule)
{
    boost::python::to_python_converter<Points, Converter>();

    class_<MyClass, boost::noncopyable>("MyClass")
        .def("get_data", &MyClass::get_data);
}
© www.soinside.com 2019 - 2024. All rights reserved.