mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-22 05:05:11 +00:00
install a cleanup handler for nontrivial lambda closures
This commit is contained in:
parent
28f98aa298
commit
19208fe9a4
@ -72,4 +72,29 @@ void init_ex5(py::module &m) {
|
||||
m.def("test_callback2", &test_callback2);
|
||||
m.def("test_callback3", &test_callback3);
|
||||
m.def("test_callback4", &test_callback4);
|
||||
|
||||
/* Test cleanup of lambda closure */
|
||||
|
||||
struct Payload {
|
||||
Payload() {
|
||||
std::cout << "Payload constructor" << std::endl;
|
||||
}
|
||||
~Payload() {
|
||||
std::cout << "Payload destructor" << std::endl;
|
||||
}
|
||||
Payload(const Payload &) {
|
||||
std::cout << "Payload copy constructor" << std::endl;
|
||||
}
|
||||
Payload(Payload &&) {
|
||||
std::cout << "Payload move constructor" << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
m.def("test_cleanup", []() -> std::function<void(void)> {
|
||||
Payload p;
|
||||
|
||||
return [p]() {
|
||||
/* p should be cleaned up when the returned function is garbage collected */
|
||||
};
|
||||
});
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ from example import test_callback1
|
||||
from example import test_callback2
|
||||
from example import test_callback3
|
||||
from example import test_callback4
|
||||
from example import test_cleanup
|
||||
|
||||
def func1():
|
||||
print('Callback function 1 called!')
|
||||
@ -38,3 +39,5 @@ print(test_callback2(func2))
|
||||
test_callback3(lambda i: i + 1)
|
||||
f = test_callback4()
|
||||
print("func(43) = %i" % f(43))
|
||||
|
||||
test_cleanup()
|
||||
|
@ -12,3 +12,9 @@ Callback function 2 called : Hello, x, True, 5
|
||||
5
|
||||
func(43) = 44
|
||||
func(43) = 44
|
||||
Payload constructor
|
||||
Payload copy constructor
|
||||
Payload move constructor
|
||||
Payload destructor
|
||||
Payload destructor
|
||||
Payload destructor
|
||||
|
@ -69,6 +69,7 @@ private:
|
||||
void *data = nullptr;
|
||||
bool is_constructor = false, is_method = false;
|
||||
short keywords = 0;
|
||||
void (*free) (void *ptr) = nullptr;
|
||||
return_value_policy policy = return_value_policy::automatic;
|
||||
std::string signature;
|
||||
PyObject *class_ = nullptr;
|
||||
@ -242,6 +243,9 @@ private:
|
||||
m_entry = new function_entry();
|
||||
m_entry->data = new capture { std::forward<Func>(f), std::tuple<Extra...>(std::forward<Extra>(extra)...) };
|
||||
|
||||
if (!std::is_trivially_destructible<Func>::value)
|
||||
m_entry->free = [](void *ptr) { delete (capture *) ptr; };
|
||||
|
||||
typedef arg_value_caster<Arg...> cast_in;
|
||||
typedef return_value_caster<Return> cast_out;
|
||||
|
||||
@ -333,7 +337,10 @@ private:
|
||||
static void destruct(function_entry *entry) {
|
||||
while (entry) {
|
||||
delete entry->def;
|
||||
operator delete(entry->data);
|
||||
if (entry->free)
|
||||
entry->free(entry->data);
|
||||
else
|
||||
operator delete(entry->data);
|
||||
function_entry *next = entry->next;
|
||||
delete entry;
|
||||
entry = next;
|
||||
|
Loading…
Reference in New Issue
Block a user