通过 pybind11 迭代包裹在 Python 中的 C++ 对象
Iterating over C++ objects wrapped in Python via pybind11
我有 C++ 代码定义 curves
class、curve
class 和 point
class,我正在尝试通过 pybind11 为那些 classes 编写 Python 绑定并在 Python 中使用它们。
这些 classes 的 pybind11 绑定如下所示:
namespace py = pybind11;
PYBIND11_MODULE(mymodule, m) {
py::class_<_point>(m, "_point")
.def(py::init<double, double>())
.def_readwrite("next", &point::next)
.def_readwrite("prev", &point::prev)
.def_readonly("x1", &point::x1)
.def_readonly("x2", &point::x2);
py::class_<curve>(m, "curve")
.def(py::init<point*>()) //constructor 1
.def(py::init()) //constructor 2
.def_readwrite("first", &curve::first)
.def_readwrite("last", &curve::last)
.def_readwrite("next", &curve::next)
.def_readwrite("prev", &curve::prev);
py::class_<curves>(m, "curves")
.def(py::init())
.def_readwrite("first", &curves::first)
.def_readwrite("last", &curves::last);
}
在 C++ 中,我可以迭代由 curve
组成的 curves
对象
它又按以下方式由 point
个对象组成:
for(curve *c=curves_pointer->first; c; c=c->next) {
for(point *p=c->first; p; p=p->next) {
cout << p->x1 << "," <<p->x2 << std::endl;
}
}
在 Python 中,例如,我可以使用 curves_instance.last.first.x1
访问单个点,但我不知道如何遍历所有曲线、点等
您可以 def
一个简单的生成器:
def iterate_from(item):
while item is not None:
yield item
item = item.next
这将允许您编写如下代码(这只是一个概念,如果需要请更新)
for c in iterate_from(curves_instance.first):
for p in iterate_from(c.first):
print p.x1, ",", p.x2
我认为正确答案应该是
使用 pybind11::make_iterator
来实现 __iter__
。提供了一个例子 here.
我认为是 py::make_iterator
:
.def("__iter__", [](const Sequence &s) { return py::make_iterator(s.begin(), s.end()); },
py::keep_alive<0, 1>() /* Essential: keep object alive while iterator exists */)
我有 C++ 代码定义 curves
class、curve
class 和 point
class,我正在尝试通过 pybind11 为那些 classes 编写 Python 绑定并在 Python 中使用它们。
这些 classes 的 pybind11 绑定如下所示:
namespace py = pybind11;
PYBIND11_MODULE(mymodule, m) {
py::class_<_point>(m, "_point")
.def(py::init<double, double>())
.def_readwrite("next", &point::next)
.def_readwrite("prev", &point::prev)
.def_readonly("x1", &point::x1)
.def_readonly("x2", &point::x2);
py::class_<curve>(m, "curve")
.def(py::init<point*>()) //constructor 1
.def(py::init()) //constructor 2
.def_readwrite("first", &curve::first)
.def_readwrite("last", &curve::last)
.def_readwrite("next", &curve::next)
.def_readwrite("prev", &curve::prev);
py::class_<curves>(m, "curves")
.def(py::init())
.def_readwrite("first", &curves::first)
.def_readwrite("last", &curves::last);
}
在 C++ 中,我可以迭代由 curve
组成的 curves
对象
它又按以下方式由 point
个对象组成:
for(curve *c=curves_pointer->first; c; c=c->next) {
for(point *p=c->first; p; p=p->next) {
cout << p->x1 << "," <<p->x2 << std::endl;
}
}
在 Python 中,例如,我可以使用 curves_instance.last.first.x1
访问单个点,但我不知道如何遍历所有曲线、点等
您可以 def
一个简单的生成器:
def iterate_from(item):
while item is not None:
yield item
item = item.next
这将允许您编写如下代码(这只是一个概念,如果需要请更新)
for c in iterate_from(curves_instance.first):
for p in iterate_from(c.first):
print p.x1, ",", p.x2
我认为正确答案应该是
使用 pybind11::make_iterator
来实现 __iter__
。提供了一个例子 here.
我认为是 py::make_iterator
:
.def("__iter__", [](const Sequence &s) { return py::make_iterator(s.begin(), s.end()); },
py::keep_alive<0, 1>() /* Essential: keep object alive while iterator exists */)