Skip to content

Commit f6c09e7

Browse files
author
Matevz Morato
committed
Fix the mysterious issue with ownership
Related PR: pybind/pybind11#1049 (comment)
1 parent 4ac79a9 commit f6c09e7

File tree

4 files changed

+145
-163
lines changed

4 files changed

+145
-163
lines changed

cmake/Hunter/config.cmake

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
# Pybind11 2.9.2
1+
# Pybind11 2.11.0-smart_holder
22
hunter_config(
33
pybind11
4-
VERSION "2.9.2"
5-
URL "https://github.com/pybind/pybind11/archive/refs/tags/v2.9.2.tar.gz"
6-
SHA1 "5e05583a210282c3251281b6ee5677915f0cbf95"
4+
VERSION "2.11.0-smart_holder"
5+
URL "https://github.com/pybind/pybind11/archive/10283c2ef44a9100bc88d066a4972c4f51ded2b0.tar.gz"
6+
SHA1 "0da09bdd6987a33feb800e4b7f129df5c9aa5aed"
77
)

python_host_node.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ def run(self):
1010
print("hello world")
1111

1212
p = dai.Pipeline()
13-
printer = Printer()
14-
a = p.add(printer)
13+
p.create(Printer)
14+
a = p.add(Printer())
1515
p.start()
1616
p.wait()

src/DeviceBindings.cpp

Lines changed: 133 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -23,135 +23,135 @@ PYBIND11_MAKE_OPAQUE(std::unordered_map<std::int8_t, dai::BoardConfig::UART>);
2323
// Patch for bind_map naming
2424
// Remove if it gets mainlined in pybind11
2525
namespace pybind11 {
26-
27-
template <typename Map, typename holder_type = std::unique_ptr<Map>, typename... Args>
28-
class_<Map, holder_type> bind_map_patched(handle scope, const std::string &name, Args &&...args) {
29-
using KeyType = typename Map::key_type;
30-
using MappedType = typename Map::mapped_type;
31-
using KeysView = detail::keys_view<Map>;
32-
using ValuesView = detail::values_view<Map>;
33-
using ItemsView = detail::items_view<Map>;
34-
using Class_ = class_<Map, holder_type>;
35-
36-
// If either type is a non-module-local bound type then make the map binding non-local as well;
37-
// otherwise (e.g. both types are either module-local or converting) the map will be
38-
// module-local.
39-
auto *tinfo = detail::get_type_info(typeid(MappedType));
40-
bool local = !tinfo || tinfo->module_local;
41-
if (local) {
42-
tinfo = detail::get_type_info(typeid(KeyType));
43-
local = !tinfo || tinfo->module_local;
44-
}
45-
46-
Class_ cl(scope, name.c_str(), pybind11::module_local(local), std::forward<Args>(args)...);
47-
class_<KeysView> keys_view(
48-
scope, ("KeysView_" + name).c_str(), pybind11::module_local(local));
49-
class_<ValuesView> values_view(
50-
scope, ("ValuesView_" + name).c_str(), pybind11::module_local(local));
51-
class_<ItemsView> items_view(
52-
scope, ("ItemsView_" + name).c_str(), pybind11::module_local(local));
53-
54-
cl.def(init<>());
55-
56-
// Register stream insertion operator (if possible)
57-
detail::map_if_insertion_operator<Map, Class_>(cl, name);
58-
59-
cl.def(
60-
"__bool__",
61-
[](const Map &m) -> bool { return !m.empty(); },
62-
"Check whether the map is nonempty");
63-
64-
cl.def(
65-
"__iter__",
66-
[](Map &m) { return make_key_iterator(m.begin(), m.end()); },
67-
keep_alive<0, 1>() /* Essential: keep map alive while iterator exists */
68-
);
69-
70-
cl.def(
71-
"keys",
72-
[](Map &m) { return KeysView{m}; },
73-
keep_alive<0, 1>() /* Essential: keep map alive while view exists */
74-
);
75-
76-
cl.def(
77-
"values",
78-
[](Map &m) { return ValuesView{m}; },
79-
keep_alive<0, 1>() /* Essential: keep map alive while view exists */
80-
);
81-
82-
cl.def(
83-
"items",
84-
[](Map &m) { return ItemsView{m}; },
85-
keep_alive<0, 1>() /* Essential: keep map alive while view exists */
86-
);
87-
88-
cl.def(
89-
"__getitem__",
90-
[](Map &m, const KeyType &k) -> MappedType & {
91-
auto it = m.find(k);
92-
if (it == m.end()) {
93-
throw key_error();
94-
}
95-
return it->second;
96-
},
97-
return_value_policy::reference_internal // ref + keepalive
98-
);
99-
100-
cl.def("__contains__", [](Map &m, const KeyType &k) -> bool {
101-
auto it = m.find(k);
102-
if (it == m.end()) {
103-
return false;
104-
}
105-
return true;
106-
});
107-
// Fallback for when the object is not of the key type
108-
cl.def("__contains__", [](Map &, const object &) -> bool { return false; });
109-
110-
// Assignment provided only if the type is copyable
111-
detail::map_assignment<Map, Class_>(cl);
112-
113-
cl.def("__delitem__", [](Map &m, const KeyType &k) {
114-
auto it = m.find(k);
115-
if (it == m.end()) {
116-
throw key_error();
117-
}
118-
m.erase(it);
119-
});
120-
121-
cl.def("__len__", &Map::size);
122-
123-
keys_view.def("__len__", [](KeysView &view) { return view.map.size(); });
124-
keys_view.def(
125-
"__iter__",
126-
[](KeysView &view) { return make_key_iterator(view.map.begin(), view.map.end()); },
127-
keep_alive<0, 1>() /* Essential: keep view alive while iterator exists */
128-
);
129-
keys_view.def("__contains__", [](KeysView &view, const KeyType &k) -> bool {
130-
auto it = view.map.find(k);
131-
if (it == view.map.end()) {
132-
return false;
133-
}
134-
return true;
135-
});
136-
// Fallback for when the object is not of the key type
137-
keys_view.def("__contains__", [](KeysView &, const object &) -> bool { return false; });
138-
139-
values_view.def("__len__", [](ValuesView &view) { return view.map.size(); });
140-
values_view.def(
141-
"__iter__",
142-
[](ValuesView &view) { return make_value_iterator(view.map.begin(), view.map.end()); },
143-
keep_alive<0, 1>() /* Essential: keep view alive while iterator exists */
144-
);
145-
146-
items_view.def("__len__", [](ItemsView &view) { return view.map.size(); });
147-
items_view.def(
148-
"__iter__",
149-
[](ItemsView &view) { return make_iterator(view.map.begin(), view.map.end()); },
150-
keep_alive<0, 1>() /* Essential: keep view alive while iterator exists */
151-
);
152-
153-
return cl;
154-
}
26+
// TODO(Morato) - check if fixed, doesn't compile on v2.11.1
27+
// template <typename Map, typename holder_type = std::unique_ptr<Map>, typename... Args>
28+
// class_<Map, holder_type> bind_map_patched(handle scope, const std::string &name, Args &&...args) {
29+
// using KeyType = typename Map::key_type;
30+
// using MappedType = typename Map::mapped_type;
31+
// using KeysView = detail::keys_view<Map>;
32+
// using ValuesView = detail::values_view<Map>;
33+
// using ItemsView = detail::items_view<Map>;
34+
// using Class_ = class_<Map, holder_type>;
35+
36+
// // If either type is a non-module-local bound type then make the map binding non-local as well;
37+
// // otherwise (e.g. both types are either module-local or converting) the map will be
38+
// // module-local.
39+
// auto *tinfo = detail::get_type_info(typeid(MappedType));
40+
// bool local = !tinfo || tinfo->module_local;
41+
// if (local) {
42+
// tinfo = detail::get_type_info(typeid(KeyType));
43+
// local = !tinfo || tinfo->module_local;
44+
// }
45+
46+
// Class_ cl(scope, name.c_str(), pybind11::module_local(local), std::forward<Args>(args)...);
47+
// class_<KeysView> keys_view(
48+
// scope, ("KeysView_" + name).c_str(), pybind11::module_local(local));
49+
// class_<ValuesView> values_view(
50+
// scope, ("ValuesView_" + name).c_str(), pybind11::module_local(local));
51+
// class_<ItemsView> items_view(
52+
// scope, ("ItemsView_" + name).c_str(), pybind11::module_local(local));
53+
54+
// cl.def(init<>());
55+
56+
// // Register stream insertion operator (if possible)
57+
// detail::map_if_insertion_operator<Map, Class_>(cl, name);
58+
59+
// cl.def(
60+
// "__bool__",
61+
// [](const Map &m) -> bool { return !m.empty(); },
62+
// "Check whether the map is nonempty");
63+
64+
// cl.def(
65+
// "__iter__",
66+
// [](Map &m) { return make_key_iterator(m.begin(), m.end()); },
67+
// keep_alive<0, 1>() /* Essential: keep map alive while iterator exists */
68+
// );
69+
70+
// cl.def(
71+
// "keys",
72+
// [](Map &m) { return KeysView{m}; },
73+
// keep_alive<0, 1>() /* Essential: keep map alive while view exists */
74+
// );
75+
76+
// cl.def(
77+
// "values",
78+
// [](Map &m) { return ValuesView{m}; },
79+
// keep_alive<0, 1>() /* Essential: keep map alive while view exists */
80+
// );
81+
82+
// cl.def(
83+
// "items",
84+
// [](Map &m) { return ItemsView{m}; },
85+
// keep_alive<0, 1>() /* Essential: keep map alive while view exists */
86+
// );
87+
88+
// cl.def(
89+
// "__getitem__",
90+
// [](Map &m, const KeyType &k) -> MappedType & {
91+
// auto it = m.find(k);
92+
// if (it == m.end()) {
93+
// throw key_error();
94+
// }
95+
// return it->second;
96+
// },
97+
// return_value_policy::reference_internal // ref + keepalive
98+
// );
99+
100+
// cl.def("__contains__", [](Map &m, const KeyType &k) -> bool {
101+
// auto it = m.find(k);
102+
// if (it == m.end()) {
103+
// return false;
104+
// }
105+
// return true;
106+
// });
107+
// // Fallback for when the object is not of the key type
108+
// cl.def("__contains__", [](Map &, const object &) -> bool { return false; });
109+
110+
// // Assignment provided only if the type is copyable
111+
// detail::map_assignment<Map, Class_>(cl);
112+
113+
// cl.def("__delitem__", [](Map &m, const KeyType &k) {
114+
// auto it = m.find(k);
115+
// if (it == m.end()) {
116+
// throw key_error();
117+
// }
118+
// m.erase(it);
119+
// });
120+
121+
// cl.def("__len__", &Map::size);
122+
123+
// keys_view.def("__len__", [](KeysView &view) { return view.map.size(); });
124+
// keys_view.def(
125+
// "__iter__",
126+
// [](KeysView &view) { return make_key_iterator(view.map.begin(), view.map.end()); },
127+
// keep_alive<0, 1>() /* Essential: keep view alive while iterator exists */
128+
// );
129+
// keys_view.def("__contains__", [](KeysView &view, const KeyType &k) -> bool {
130+
// auto it = view.map.find(k);
131+
// if (it == view.map.end()) {
132+
// return false;
133+
// }
134+
// return true;
135+
// });
136+
// // Fallback for when the object is not of the key type
137+
// keys_view.def("__contains__", [](KeysView &, const object &) -> bool { return false; });
138+
139+
// values_view.def("__len__", [](ValuesView &view) { return view.map.size(); });
140+
// values_view.def(
141+
// "__iter__",
142+
// [](ValuesView &view) { return make_value_iterator(view.map.begin(), view.map.end()); },
143+
// keep_alive<0, 1>() /* Essential: keep view alive while iterator exists */
144+
// );
145+
146+
// items_view.def("__len__", [](ItemsView &view) { return view.map.size(); });
147+
// items_view.def(
148+
// "__iter__",
149+
// [](ItemsView &view) { return make_iterator(view.map.begin(), view.map.end()); },
150+
// keep_alive<0, 1>() /* Essential: keep view alive while iterator exists */
151+
// );
152+
153+
// return cl;
154+
// }
155155

156156
} // namespace pybind11
157157

@@ -348,9 +348,10 @@ void DeviceBindings::bind(pybind11::module& m, void* pCallstack){
348348
py::class_<PyClock> clock(m, "Clock");
349349

350350

351-
py::bind_map_patched<std::unordered_map<std::int8_t, dai::BoardConfig::GPIO>>(boardConfig, "GPIOMap");
352-
py::bind_map_patched<std::unordered_map<std::int8_t, dai::BoardConfig::UART>>(boardConfig, "UARTMap");
353-
351+
// py::bind_map_patched<std::unordered_map<std::int8_t, dai::BoardConfig::GPIO>>(boardConfig, "GPIOMap");
352+
// py::bind_map_patched<std::unordered_map<std::int8_t, dai::BoardConfig::UART>>(boardConfig, "UARTMap");
353+
py::bind_map<std::unordered_map<std::int8_t, dai::BoardConfig::GPIO>>(boardConfig, "GPIOMap");
354+
py::bind_map<std::unordered_map<std::int8_t, dai::BoardConfig::UART>>(boardConfig, "UARTMap");
354355

355356
// pybind11 limitation of having actual classes as exceptions
356357
// Possible but requires a larger workaround

src/pipeline/PipelineBindings.cpp

Lines changed: 6 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -121,43 +121,24 @@ void PipelineBindings::bind(pybind11::module& m, void* pCallstack){
121121
.def("add",
122122
[](Pipeline &p, std::shared_ptr<Node> hostNode) {
123123
p.add(hostNode);
124-
// TODO(Morato) TMP TMP only a test
125-
if (std::dynamic_pointer_cast<HostNode>(hostNode) != nullptr) {
126-
std::dynamic_pointer_cast<HostNode>(hostNode)->run();
127-
}
128124
})
129125
// 'Template' create function
130126
.def("create",
131127
[](dai::Pipeline &p, py::object class_) {
132-
// TODO(zimen) re-introduce create function for custom host nodes
133-
// if
134-
// (py::cast<std::string>(class_.attr("__base__").attr("__name__"))
135-
// == "HostNode") { Call the constructor of the class auto
136-
// host_node =
137-
// py::cast<std::shared_ptr<Node>>(class_.attr("__new__")(class_));
138-
// std::cout << py::str(class_.attr("a")) << std::endl;
139-
// class_().attr("run")();
140-
// auto host_node = py::cast<std::shared_ptr<Node>>(class_());
141-
// std::shared_ptr<HostNode> host_node =
142-
// py::cast<std::shared_ptr<HostNode>>(class_());
143-
// std::shared_ptr<HostNode> host_node =
144-
// class_().cast<std::shared_ptr<HostNode>>();
145-
// host_node->run();
146-
// return class_();
147128

148-
// p.add(host_node);
149-
// return (std::shared_ptr<Node>) host_node;
150-
// return (std::shared_ptr<Node>) nullptr;
151-
// }
129+
if(py::cast<std::string>(class_.attr("__base__").attr("__name__")) == "HostNode") {
130+
std::shared_ptr<Node> host_node = py::cast<std::shared_ptr<Node>>(class_());
131+
p.add(host_node);
132+
return host_node;
133+
}
152134
auto node = createNode(p, class_);
153135
if (node == nullptr) {
154136
throw std::invalid_argument(
155137
std::string(py::str(class_)) +
156138
" is not a subclass of depthai.node");
157139
}
158140
// Cast the node to a py::object
159-
py::object obj = py::cast(node);
160-
return obj;
141+
return node;
161142
})
162143
// TODO(themarpe) DEPRECATE, use pipeline.create([class name])
163144
// templated create<NODE> function

0 commit comments

Comments
 (0)