mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-25 14:45:12 +00:00
Support keep_alive where nurse may be None
For example keep_alive<0,1>() should work where the return value may sometimes be None. At present a "Could not allocate weak reference!" exception is thrown. Update documentation to clarify behaviour of keep_alive when nurse is None or does not support weak references.
This commit is contained in:
parent
e357ed3cc8
commit
f45bb585c3
@ -663,10 +663,13 @@ In addition to the above return value policies, further `call policies` can be
|
||||
specified to indicate dependencies between parameters. There is currently just
|
||||
one policy named ``keep_alive<Nurse, Patient>``, which indicates that the
|
||||
argument with index ``Patient`` should be kept alive at least until the
|
||||
argument with index ``Nurse`` is freed by the garbage collector; argument
|
||||
indices start at one, while zero refers to the return value. For methods, index
|
||||
one refers to the implicit ``this`` pointer, while regular arguments begin at
|
||||
index two. Arbitrarily many call policies can be specified.
|
||||
argument with index ``Nurse`` is freed by the garbage collector, as long as the
|
||||
nurse object supports weak references (pybind11 extension classes all support
|
||||
weak references). If the nurse object does not support weak references and is
|
||||
not None an appropriate exception will be thrown. Argument indices start at
|
||||
one, while zero refers to the return value. For methods, index one refers to
|
||||
the implicit ``this`` pointer, while regular arguments begin at index two.
|
||||
Arbitrarily many call policies can be specified.
|
||||
|
||||
Consider the following example: the binding code for a list append operation
|
||||
that ties the lifetime of the newly added element to the underlying container
|
||||
|
@ -22,6 +22,7 @@ public:
|
||||
~Parent() { std::cout << "Releasing parent." << std::endl; }
|
||||
void addChild(Child *) { }
|
||||
Child *returnChild() { return new Child(); }
|
||||
Child *returnNullChild() { return nullptr; }
|
||||
};
|
||||
|
||||
void init_ex_keep_alive(py::module &m) {
|
||||
@ -30,7 +31,9 @@ void init_ex_keep_alive(py::module &m) {
|
||||
.def("addChild", &Parent::addChild)
|
||||
.def("addChildKeepAlive", &Parent::addChild, py::keep_alive<1, 2>())
|
||||
.def("returnChild", &Parent::returnChild)
|
||||
.def("returnChildKeepAlive", &Parent::returnChild, py::keep_alive<1, 0>());
|
||||
.def("returnChildKeepAlive", &Parent::returnChild, py::keep_alive<1, 0>())
|
||||
.def("returnNullChildKeepAliveChild", &Parent::returnNullChild, py::keep_alive<1, 0>())
|
||||
.def("returnNullChildKeepAliveParent", &Parent::returnNullChild, py::keep_alive<0, 1>());
|
||||
|
||||
py::class_<Child>(m, "Child")
|
||||
.def(py::init<>());
|
||||
|
@ -31,6 +31,7 @@ if True:
|
||||
gc.collect()
|
||||
print(p)
|
||||
p = None
|
||||
|
||||
gc.collect()
|
||||
print("")
|
||||
|
||||
@ -41,6 +42,26 @@ if True:
|
||||
print(p)
|
||||
p = None
|
||||
|
||||
gc.collect()
|
||||
print("")
|
||||
|
||||
if True:
|
||||
p = Parent()
|
||||
p.returnNullChildKeepAliveChild()
|
||||
gc.collect()
|
||||
print(p)
|
||||
p = None
|
||||
|
||||
gc.collect()
|
||||
print("")
|
||||
|
||||
if True:
|
||||
p = Parent()
|
||||
p.returnNullChildKeepAliveParent()
|
||||
gc.collect()
|
||||
print(p)
|
||||
p = None
|
||||
|
||||
gc.collect()
|
||||
print("")
|
||||
print("Terminating..")
|
||||
|
@ -22,4 +22,12 @@ Allocating child.
|
||||
Releasing parent.
|
||||
Releasing child.
|
||||
|
||||
Allocating parent.
|
||||
<example.Parent object at 0x10eb726c0>
|
||||
Releasing parent.
|
||||
|
||||
Allocating parent.
|
||||
<example.Parent object at 0x10eb726c0>
|
||||
Releasing parent.
|
||||
|
||||
Terminating..
|
||||
|
@ -1098,8 +1098,8 @@ inline void keep_alive_impl(handle nurse, handle patient) {
|
||||
if (!nurse || !patient)
|
||||
pybind11_fail("Could not activate keep_alive!");
|
||||
|
||||
if (patient.ptr() == Py_None)
|
||||
return; /* Nothing to keep alive */
|
||||
if (patient.ptr() == Py_None || nurse.ptr() == Py_None)
|
||||
return; /* Nothing to keep alive or nothing to be kept alive by */
|
||||
|
||||
cpp_function disable_lifesupport(
|
||||
[patient](handle weakref) { patient.dec_ref(); weakref.dec_ref(); });
|
||||
|
Loading…
Reference in New Issue
Block a user