Skip to content

Instantly share code, notes, and snippets.

@oskaritimperi
Created September 18, 2019 08:04
Show Gist options
  • Select an option

  • Save oskaritimperi/7f16c3e413700a71b51e17f174de0bee to your computer and use it in GitHub Desktop.

Select an option

Save oskaritimperi/7f16c3e413700a71b51e17f174de0bee to your computer and use it in GitHub Desktop.
pybind11 bound function as callback keeping C++ object alive
#include <functional>
#include <cstdio>
#include <thread>
#include <chrono>
#include <pybind11/pybind11.h>
#include <pybind11/functional.h>
namespace py = pybind11;
struct Foobar {
Foobar() {
printf("Foobar::Foobar()\n");
}
~Foobar() {
printf("Foobar::~Foobar()\n");
}
void set_callback(std::function<void()> callback) {
this->callback = callback;
}
void call_callback() {
printf("Foobar::call_callback()\n");
std::thread t([this]() {
printf("Foobar::call_callback() sleeping\n");
std::this_thread::sleep_for(std::chrono::milliseconds(100));
printf("Foobar::call_callback() calling callback\n");
this->callback();
});
t.detach();
}
std::function<void()> callback;
};
PYBIND11_MODULE(pybindtest, m) {
py::class_<Foobar>(m, "Foobar", py::dynamic_attr())
.def(py::init<>())
.def("set_callback", &Foobar::set_callback)
.def("call_callback", &Foobar::call_callback)
.def("set_callback_2", [](py::object self, py::object callback) {
auto d = self.attr("__dict__");
d["_callback"] = callback;
py::handle callback_handle = callback;
Foobar &f = py::cast<Foobar &>(self);
f.set_callback([callback_handle]() {
py::gil_scoped_acquire acquire;
callback_handle();
});
});
}
import pybindtest
import time
class Parent:
def __init__(self):
self.foobar = pybindtest.Foobar()
self.foobar.set_callback(self.cb) # Foobar not GC'd
# self.foobar.set_callback_2(self.cb) # Foobar GC'd
def cb(self):
print("Parent.cb()")
def __call__(self):
self.foobar.call_callback()
time.sleep(0.5)
def __del__(self):
print("Parent.__del__()")
p = Parent()
p()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment