簡體   English   中英

使用boost :: python,如何將結構向量作為字典列表返回給Python?

[英]Using boost::python, how to return vector of structs as list of dicts to Python?

我有以下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到boost :: python :: list ),描述了如何使用vector_indexing_suitestd::vector<T>轉換為某些類型Tlist (例如,浮點數,字符串) ),但我不確定如何擴展它以處理struct-> dict轉換。 任何幫助將不勝感激。

下面是如何將C++代碼公開給Python MyType需要“等於”比較運算符重載,而且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()返回類型屬於列表,因此需要這樣訪問它。 如果您希望將其作為dict,請在Python中將其轉換為dict。

import pyA 

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

最后,我采用了以下解決方案,我將其發布在這里,以防將來對其他人有用。 可以通過添加boost的“只讀”限定符來改進此功能,但我尚未這樣做。

#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);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM