Skip to content

Commit 19ddbe5

Browse files
committed
Revert "Make wrapped C++ functions pickleable (#5580)"
This reverts commit e7e5d6e. Signed-off-by: Henry Schreiner <[email protected]>
1 parent 4dc4aca commit 19ddbe5

File tree

9 files changed

+88
-295
lines changed

9 files changed

+88
-295
lines changed

CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,6 @@ set(PYBIND11_HEADERS
186186
include/pybind11/detail/descr.h
187187
include/pybind11/detail/dynamic_raw_ptr_cast_if_possible.h
188188
include/pybind11/detail/exception_translation.h
189-
include/pybind11/detail/function_record_pyobject.h
190189
include/pybind11/detail/init.h
191190
include/pybind11/detail/internals.h
192191
include/pybind11/detail/native_enum_data.h

include/pybind11/attr.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,6 @@ struct argument_record {
193193

194194
/// Internal data structure which holds metadata about a bound function (signature, overloads,
195195
/// etc.)
196-
#define PYBIND11_DETAIL_FUNCTION_RECORD_ABI_ID "v1" // PLEASE UPDATE if the struct is changed.
197196
struct function_record {
198197
function_record()
199198
: is_constructor(false), is_new_style_constructor(false), is_stateless(false),

include/pybind11/detail/function_record_pyobject.h

Lines changed: 0 additions & 208 deletions
This file was deleted.

include/pybind11/detail/internals.h

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,11 @@
3737
/// further ABI-incompatible changes may be made before the ABI is officially
3838
/// changed to the new version.
3939
#ifndef PYBIND11_INTERNALS_VERSION
40-
# define PYBIND11_INTERNALS_VERSION 11
40+
# define PYBIND11_INTERNALS_VERSION 12
4141
#endif
4242

43-
#if PYBIND11_INTERNALS_VERSION < 11
44-
# error "PYBIND11_INTERNALS_VERSION 11 is the minimum for all platforms for pybind11v3."
43+
#if PYBIND11_INTERNALS_VERSION < 12
44+
# error "PYBIND11_INTERNALS_VERSION 12 is the minimum for all platforms for pybind11v3."
4545
#endif
4646

4747
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
@@ -254,6 +254,10 @@ struct internals {
254254
// Unused if PYBIND11_SIMPLE_GIL_MANAGEMENT is defined:
255255
PyInterpreterState *istate = nullptr;
256256

257+
// Note that we have to use a std::string to allocate memory to ensure a unique address
258+
// We want unique addresses since we use pointer equality to compare function records
259+
std::string function_record_capsule_name = internals_function_record_capsule_name;
260+
257261
type_map<PyObject *> native_enum_type_map;
258262

259263
internals()
@@ -747,6 +751,26 @@ const char *c_str(Args &&...args) {
747751
return strings.front().c_str();
748752
}
749753

754+
inline const char *get_function_record_capsule_name() {
755+
// On GraalPy, pointer equality of the names is currently not guaranteed
756+
#if !defined(GRAALVM_PYTHON)
757+
return get_internals().function_record_capsule_name.c_str();
758+
#else
759+
return nullptr;
760+
#endif
761+
}
762+
763+
// Determine whether or not the following capsule contains a pybind11 function record.
764+
// Note that we use `internals` to make sure that only ABI compatible records are touched.
765+
//
766+
// This check is currently used in two places:
767+
// - An important optimization in functional.h to avoid overhead in C++ -> Python -> C++
768+
// - The sibling feature of cpp_function to allow overloads
769+
inline bool is_function_record_capsule(const capsule &cap) {
770+
// Pointer equality as we rely on internals() to ensure unique pointers
771+
return cap.name() == get_function_record_capsule_name();
772+
}
773+
750774
PYBIND11_NAMESPACE_END(detail)
751775

752776
/// Returns a named pointer that is shared among all extension modules (using the same

include/pybind11/functional.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,15 @@ struct type_caster<std::function<Return(Args...)>> {
9191
auto *cfunc_self = PyCFunction_GET_SELF(cfunc.ptr());
9292
if (cfunc_self == nullptr) {
9393
PyErr_Clear();
94-
} else {
95-
function_record *rec = function_record_ptr_from_PyObject(cfunc_self);
94+
} else if (isinstance<capsule>(cfunc_self)) {
95+
auto c = reinterpret_borrow<capsule>(cfunc_self);
96+
97+
function_record *rec = nullptr;
98+
// Check that we can safely reinterpret the capsule into a function_record
99+
if (detail::is_function_record_capsule(c)) {
100+
rec = c.get_pointer<function_record>();
101+
}
102+
96103
while (rec != nullptr) {
97104
if (rec->is_stateless
98105
&& same_type(typeid(function_type),

0 commit comments

Comments
 (0)