Additional call policies
Additional call policies
In addition to the above return value policies, further call policies can be specified to indicate dependencies between parameters or ensure a certain state for the function call.
Keep alive
In general, this policy is required when the C++ object is any kind of container and another object is being added to the container. keep_alive<Nurse, Patient> 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 1 refers to the implicit this pointer, while regular arguments begin at index 2. Arbitrarily many call policies can be specified. When a Nurse with value None is detected at runtime, the call policy does nothing.
When the nurse is not a pybind11-registered type, the implementation internally relies on the ability to create a weak reference to the nurse object. When the nurse object is not a pybind11-registered type and does not support weak references, an exception will be thrown.
Consider the following example: here, the binding code for a list append operation ties the lifetime of the newly added element to the underlying container:
py::class_<List>(m, "List")
.def("append", &List::append, py::keep_alive<1, 2>());
For consistency, the argument indexing is identical for constructors. Index 1 still refers to the implicit this pointer, i.e. the object which is being constructed. Index 0 refers to the return type which is presumed to be void when a constructor is viewed like a function. The following example ties the lifetime of the constructor element to the constructed object:
py::class_<Nurse>(m, "Nurse")
.def(py::init<Patient &>(), py::keep_alive<1, 2>());
Note
keep_alive is analogous to the with_custodian_and_ward (if Nurse, Patient != 0) and with_custodian_and_ward_postcall (if Nurse/Patient == 0) policies from Boost.Python.
Call guard
The call_guard<T>
policy allows any scope guard type T to be placed around the function call. For example, this definition:
m.def("foo", foo, py::call_guard<T>());
is equivalent to the following pseudocode:
m.def("foo", [](args...) {
T scope_guard;
return foo(args...); // forwarded arguments
});
The only requirement is that T is default-constructible, but otherwise any scope guard will work. This is very useful in combination with gil_scoped_release. See Global Interpreter Lock (GIL).
Multiple guards can also be specified as py::call_guard<T1, T2, T3...>
. The constructor order is left to right and destruction happens in reverse.