mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-25 22:52:01 +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_callback2", &test_callback2);
|
||||||
m.def("test_callback3", &test_callback3);
|
m.def("test_callback3", &test_callback3);
|
||||||
m.def("test_callback4", &test_callback4);
|
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_callback2
|
||||||
from example import test_callback3
|
from example import test_callback3
|
||||||
from example import test_callback4
|
from example import test_callback4
|
||||||
|
from example import test_cleanup
|
||||||
|
|
||||||
def func1():
|
def func1():
|
||||||
print('Callback function 1 called!')
|
print('Callback function 1 called!')
|
||||||
@ -38,3 +39,5 @@ print(test_callback2(func2))
|
|||||||
test_callback3(lambda i: i + 1)
|
test_callback3(lambda i: i + 1)
|
||||||
f = test_callback4()
|
f = test_callback4()
|
||||||
print("func(43) = %i" % f(43))
|
print("func(43) = %i" % f(43))
|
||||||
|
|
||||||
|
test_cleanup()
|
||||||
|
@ -12,3 +12,9 @@ Callback function 2 called : Hello, x, True, 5
|
|||||||
5
|
5
|
||||||
func(43) = 44
|
func(43) = 44
|
||||||
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;
|
void *data = nullptr;
|
||||||
bool is_constructor = false, is_method = false;
|
bool is_constructor = false, is_method = false;
|
||||||
short keywords = 0;
|
short keywords = 0;
|
||||||
|
void (*free) (void *ptr) = nullptr;
|
||||||
return_value_policy policy = return_value_policy::automatic;
|
return_value_policy policy = return_value_policy::automatic;
|
||||||
std::string signature;
|
std::string signature;
|
||||||
PyObject *class_ = nullptr;
|
PyObject *class_ = nullptr;
|
||||||
@ -242,6 +243,9 @@ private:
|
|||||||
m_entry = new function_entry();
|
m_entry = new function_entry();
|
||||||
m_entry->data = new capture { std::forward<Func>(f), std::tuple<Extra...>(std::forward<Extra>(extra)...) };
|
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 arg_value_caster<Arg...> cast_in;
|
||||||
typedef return_value_caster<Return> cast_out;
|
typedef return_value_caster<Return> cast_out;
|
||||||
|
|
||||||
@ -333,7 +337,10 @@ private:
|
|||||||
static void destruct(function_entry *entry) {
|
static void destruct(function_entry *entry) {
|
||||||
while (entry) {
|
while (entry) {
|
||||||
delete entry->def;
|
delete entry->def;
|
||||||
operator delete(entry->data);
|
if (entry->free)
|
||||||
|
entry->free(entry->data);
|
||||||
|
else
|
||||||
|
operator delete(entry->data);
|
||||||
function_entry *next = entry->next;
|
function_entry *next = entry->next;
|
||||||
delete entry;
|
delete entry;
|
||||||
entry = next;
|
entry = next;
|
||||||
|
Loading…
Reference in New Issue
Block a user