Skip to content

Instantly share code, notes, and snippets.

@blapid
Last active March 10, 2018 10:24
Show Gist options
  • Save blapid/69cba9f58abf38ecb84a0d3c1a241fef to your computer and use it in GitHub Desktop.
Save blapid/69cba9f58abf38ecb84a0d3c1a241fef to your computer and use it in GitHub Desktop.
Playing around with ownerships and lists in pybind11
#include <stdio.h>
#include <list>
#include <memory>
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
struct B;
struct A {
A() {};
~A() {
printf("~A()\n");
if (!b_list.empty()) {
printf("b_list not empty!\n");
}
};
void register_b(B *b) {
b_list.push_back(b);
};
void unregister_b(B *b) {
auto removed = std::remove(b_list.begin(), b_list.end(), b);
b_list.erase(removed, b_list.end());
};
std::list<B *> b_list;
};
struct B {
B(A& a) : m_a(a) {
m_a.register_b(this);
};
~B() {
printf("~B()\n");
m_a.unregister_b(this);
};
A& m_a;
};
/*
* Enforce the destruction order by wrapping A in a shared_ptr, and
* B in a unique_ptr to itself and a shared_ptr to A.
* This means that each B item in the list which python receives from
* "get_b_list" holds a shared_ptr to the A that was used in it's creation.
* If python deletes it's A before all of the B's, the shared_ptr refcount
* will still be positive and A will not be deleted until the last of the
* B's are deleted by python.
*/
struct AHolder : public std::shared_ptr<A> {
AHolder() : std::shared_ptr<A>(new A()) {}
};
//Note: The order of inheritance is important! We want B to get destructed before AHolder!
struct BHolder : public AHolder, std::unique_ptr<B> {
BHolder(AHolder& a) : AHolder(a), std::unique_ptr<B>(new B(*a)) {}
};
namespace py = pybind11;
PYBIND11_MODULE(example, m) {
m.doc() = "pybind11 example plugin"; // optional module docstring
py::class_<BHolder>(m, "B");
py::class_<AHolder>(m, "A")
.def(py::init<>())
.def("get_b_list", [](AHolder _this) -> std::list<BHolder> {
std::list<BHolder> b_list;
b_list.push_back({_this});
b_list.push_back({_this});
return b_list;
}, py::return_value_policy::move);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment