mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-22 13:15: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
|
specified to indicate dependencies between parameters. There is currently just
|
||||||
one policy named ``keep_alive<Nurse, Patient>``, which indicates that the
|
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 ``Patient`` should be kept alive at least until the
|
||||||
argument with index ``Nurse`` is freed by the garbage collector; argument
|
argument with index ``Nurse`` is freed by the garbage collector, as long as the
|
||||||
indices start at one, while zero refers to the return value. For methods, index
|
nurse object supports weak references (pybind11 extension classes all support
|
||||||
one refers to the implicit ``this`` pointer, while regular arguments begin at
|
weak references). If the nurse object does not support weak references and is
|
||||||
index two. Arbitrarily many call policies can be specified.
|
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
|
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
|
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; }
|
~Parent() { std::cout << "Releasing parent." << std::endl; }
|
||||||
void addChild(Child *) { }
|
void addChild(Child *) { }
|
||||||
Child *returnChild() { return new Child(); }
|
Child *returnChild() { return new Child(); }
|
||||||
|
Child *returnNullChild() { return nullptr; }
|
||||||
};
|
};
|
||||||
|
|
||||||
void init_ex_keep_alive(py::module &m) {
|
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("addChild", &Parent::addChild)
|
||||||
.def("addChildKeepAlive", &Parent::addChild, py::keep_alive<1, 2>())
|
.def("addChildKeepAlive", &Parent::addChild, py::keep_alive<1, 2>())
|
||||||
.def("returnChild", &Parent::returnChild)
|
.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")
|
py::class_<Child>(m, "Child")
|
||||||
.def(py::init<>());
|
.def(py::init<>());
|
||||||
|
@ -31,6 +31,7 @@ if True:
|
|||||||
gc.collect()
|
gc.collect()
|
||||||
print(p)
|
print(p)
|
||||||
p = None
|
p = None
|
||||||
|
|
||||||
gc.collect()
|
gc.collect()
|
||||||
print("")
|
print("")
|
||||||
|
|
||||||
@ -41,6 +42,26 @@ if True:
|
|||||||
print(p)
|
print(p)
|
||||||
p = None
|
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()
|
gc.collect()
|
||||||
print("")
|
print("")
|
||||||
print("Terminating..")
|
print("Terminating..")
|
||||||
|
@ -22,4 +22,12 @@ Allocating child.
|
|||||||
Releasing parent.
|
Releasing parent.
|
||||||
Releasing child.
|
Releasing child.
|
||||||
|
|
||||||
|
Allocating parent.
|
||||||
|
<example.Parent object at 0x10eb726c0>
|
||||||
|
Releasing parent.
|
||||||
|
|
||||||
|
Allocating parent.
|
||||||
|
<example.Parent object at 0x10eb726c0>
|
||||||
|
Releasing parent.
|
||||||
|
|
||||||
Terminating..
|
Terminating..
|
||||||
|
@ -1098,8 +1098,8 @@ inline void keep_alive_impl(handle nurse, handle patient) {
|
|||||||
if (!nurse || !patient)
|
if (!nurse || !patient)
|
||||||
pybind11_fail("Could not activate keep_alive!");
|
pybind11_fail("Could not activate keep_alive!");
|
||||||
|
|
||||||
if (patient.ptr() == Py_None)
|
if (patient.ptr() == Py_None || nurse.ptr() == Py_None)
|
||||||
return; /* Nothing to keep alive */
|
return; /* Nothing to keep alive or nothing to be kept alive by */
|
||||||
|
|
||||||
cpp_function disable_lifesupport(
|
cpp_function disable_lifesupport(
|
||||||
[patient](handle weakref) { patient.dec_ref(); weakref.dec_ref(); });
|
[patient](handle weakref) { patient.dec_ref(); weakref.dec_ref(); });
|
||||||
|
Loading…
Reference in New Issue
Block a user