mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-11 08:03:55 +00:00
Trivial refactoring to make the capsule API more user friendly. (#4720)
* Trivial refactoring to make the capsule API more user friendly. * Use new API in production code. Thanks @Lalaland for pointing this out.
This commit is contained in:
parent
e10da79b6e
commit
2fb3d7cbde
@ -508,8 +508,8 @@ protected:
|
|||||||
rec->def->ml_flags = METH_VARARGS | METH_KEYWORDS;
|
rec->def->ml_flags = METH_VARARGS | METH_KEYWORDS;
|
||||||
|
|
||||||
capsule rec_capsule(unique_rec.release(),
|
capsule rec_capsule(unique_rec.release(),
|
||||||
|
detail::get_function_record_capsule_name(),
|
||||||
[](void *ptr) { destruct((detail::function_record *) ptr); });
|
[](void *ptr) { destruct((detail::function_record *) ptr); });
|
||||||
rec_capsule.set_name(detail::get_function_record_capsule_name());
|
|
||||||
guarded_strdup.release();
|
guarded_strdup.release();
|
||||||
|
|
||||||
object scope_module;
|
object scope_module;
|
||||||
|
@ -1925,28 +1925,13 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Capsule name is nullptr.
|
||||||
capsule(const void *value, void (*destructor)(void *)) {
|
capsule(const void *value, void (*destructor)(void *)) {
|
||||||
m_ptr = PyCapsule_New(const_cast<void *>(value), nullptr, [](PyObject *o) {
|
initialize_with_void_ptr_destructor(value, nullptr, destructor);
|
||||||
// guard if destructor called while err indicator is set
|
|
||||||
error_scope error_guard;
|
|
||||||
auto destructor = reinterpret_cast<void (*)(void *)>(PyCapsule_GetContext(o));
|
|
||||||
if (destructor == nullptr && PyErr_Occurred()) {
|
|
||||||
throw error_already_set();
|
|
||||||
}
|
|
||||||
const char *name = get_name_in_error_scope(o);
|
|
||||||
void *ptr = PyCapsule_GetPointer(o, name);
|
|
||||||
if (ptr == nullptr) {
|
|
||||||
throw error_already_set();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (destructor != nullptr) {
|
capsule(const void *value, const char *name, void (*destructor)(void *)) {
|
||||||
destructor(ptr);
|
initialize_with_void_ptr_destructor(value, name, destructor);
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!m_ptr || PyCapsule_SetContext(m_ptr, reinterpret_cast<void *>(destructor)) != 0) {
|
|
||||||
throw error_already_set();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
explicit capsule(void (*destructor)()) {
|
explicit capsule(void (*destructor)()) {
|
||||||
@ -2014,6 +1999,32 @@ private:
|
|||||||
|
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void initialize_with_void_ptr_destructor(const void *value,
|
||||||
|
const char *name,
|
||||||
|
void (*destructor)(void *)) {
|
||||||
|
m_ptr = PyCapsule_New(const_cast<void *>(value), name, [](PyObject *o) {
|
||||||
|
// guard if destructor called while err indicator is set
|
||||||
|
error_scope error_guard;
|
||||||
|
auto destructor = reinterpret_cast<void (*)(void *)>(PyCapsule_GetContext(o));
|
||||||
|
if (destructor == nullptr && PyErr_Occurred()) {
|
||||||
|
throw error_already_set();
|
||||||
|
}
|
||||||
|
const char *name = get_name_in_error_scope(o);
|
||||||
|
void *ptr = PyCapsule_GetPointer(o, name);
|
||||||
|
if (ptr == nullptr) {
|
||||||
|
throw error_already_set();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (destructor != nullptr) {
|
||||||
|
destructor(ptr);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!m_ptr || PyCapsule_SetContext(m_ptr, reinterpret_cast<void *>(destructor)) != 0) {
|
||||||
|
throw error_already_set();
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class tuple : public object {
|
class tuple : public object {
|
||||||
|
@ -260,6 +260,15 @@ TEST_SUBMODULE(pytypes, m) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
m.def("return_capsule_with_destructor_3", []() {
|
||||||
|
py::print("creating capsule");
|
||||||
|
auto cap = py::capsule((void *) 1233, "oname", [](void *ptr) {
|
||||||
|
py::print("destructing capsule: {}"_s.format((size_t) ptr));
|
||||||
|
});
|
||||||
|
py::print("original name: {}"_s.format(cap.name()));
|
||||||
|
return cap;
|
||||||
|
});
|
||||||
|
|
||||||
m.def("return_renamed_capsule_with_destructor_2", []() {
|
m.def("return_renamed_capsule_with_destructor_2", []() {
|
||||||
py::print("creating capsule");
|
py::print("creating capsule");
|
||||||
auto cap = py::capsule((void *) 1234, [](void *ptr) {
|
auto cap = py::capsule((void *) 1234, [](void *ptr) {
|
||||||
|
@ -319,6 +319,19 @@ def test_capsule(capture):
|
|||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
|
||||||
|
with capture:
|
||||||
|
a = m.return_capsule_with_destructor_3()
|
||||||
|
del a
|
||||||
|
pytest.gc_collect()
|
||||||
|
assert (
|
||||||
|
capture.unordered
|
||||||
|
== """
|
||||||
|
creating capsule
|
||||||
|
destructing capsule: 1233
|
||||||
|
original name: oname
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
with capture:
|
with capture:
|
||||||
a = m.return_renamed_capsule_with_destructor_2()
|
a = m.return_renamed_capsule_with_destructor_2()
|
||||||
del a
|
del a
|
||||||
|
Loading…
Reference in New Issue
Block a user