forked from ModOrganizer2/modorganizer-plugin_python
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgenerator.h
More file actions
57 lines (46 loc) · 1.67 KB
/
generator.h
File metadata and controls
57 lines (46 loc) · 1.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#ifndef PYTHON_PYBIND11_GENERATOR_H
#define PYTHON_PYBIND11_GENERATOR_H
#include <generator>
#include <pybind11/pybind11.h>
namespace mo2::python {
// the code here is mostly taken from pybind11 itself, and relies on some pybind11
// internals so might be subject to change when upgrading pybind11 versions
namespace detail {
template <typename T>
struct generator_state {
std::generator<T> g;
decltype(g.begin()) it;
generator_state(std::generator<T> gen) : g(std::move(gen)), it(g.begin()) {}
};
} // namespace detail
// create a Python generator from a C++ generator
//
template <typename T, typename... Args>
auto make_generator(std::generator<T> g, Args&&... args)
{
using state = detail::generator_state<T>;
namespace py = pybind11;
if (!py::detail::get_type_info(typeid(state), false)) {
py::class_<state>(py::handle(), "iterator", pybind11::module_local())
.def("__iter__",
[](state& s) -> state& {
return s;
})
.def(
"__next__",
[](state& s) -> T {
if (s.it != s.g.end()) {
T v = *s.it;
s.it++;
return v;
}
else {
throw py::stop_iteration();
}
},
std::forward<Args>(args)...);
}
return py::cast(state{std::move(g)});
}
} // namespace mo2::python
#endif