Skip to content

Commit 3b14721

Browse files
committed
stash pybind11 data structures in interpreter state dictionary
1 parent fcb5554 commit 3b14721

File tree

1 file changed

+26
-9
lines changed

1 file changed

+26
-9
lines changed

include/pybind11/detail/internals.h

+26-9
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,12 @@ struct type_info {
277277
# endif
278278
#endif
279279

280+
#if PY_VERSION_HEX < 0x03090000
281+
# define PYBIND11_INTERPRETER_STATE_GET _PyInterpreterState_Get
282+
#else
283+
# define PYBIND11_INTERPRETER_STATE_GET PyInterpreterState_Get
284+
#endif
285+
280286
#define PYBIND11_INTERNALS_ID \
281287
"__pybind11_internals_v" PYBIND11_TOSTRING(PYBIND11_INTERNALS_VERSION) \
282288
PYBIND11_INTERNALS_KIND PYBIND11_COMPILER_TYPE PYBIND11_STDLIB PYBIND11_BUILD_ABI \
@@ -403,7 +409,7 @@ inline void translate_local_exception(std::exception_ptr p) {
403409

404410
/// Return a reference to the current `internals` data
405411
PYBIND11_NOINLINE internals &get_internals() {
406-
auto **&internals_pp = get_internals_pp();
412+
internals **&internals_pp = get_internals_pp();
407413
if (internals_pp && *internals_pp) {
408414
return **internals_pp;
409415
}
@@ -419,11 +425,24 @@ PYBIND11_NOINLINE internals &get_internals() {
419425
} gil;
420426
error_scope err_scope;
421427

422-
PYBIND11_STR_TYPE id(PYBIND11_INTERNALS_ID);
423-
auto builtins = handle(PyEval_GetBuiltins());
424-
if (builtins.contains(id) && isinstance<capsule>(builtins[id])) {
425-
internals_pp = static_cast<internals **>(capsule(builtins[id]));
428+
const char *id_cstr = PYBIND11_INTERNALS_ID;
429+
PYBIND11_STR_TYPE id(id_cstr);
430+
431+
dict state_dict
432+
= reinterpret_borrow<dict>(PyInterpreterState_GetDict(PYBIND11_INTERPRETER_STATE_GET()));
433+
if (!state_dict)
434+
pybind11_fail("get_internals(): PyInterpreterState_GetDict() failed!");
435+
436+
if (state_dict.contains(id_cstr)) {
437+
object o = state_dict[id];
438+
// May fail if 'capsule_obj' is not a capsule, or if it has a different
439+
// name. We clear the error status below in that case
440+
internals_pp = static_cast<internals **>(PyCapsule_GetPointer(o.ptr(), id_cstr));
441+
if (!internals_pp)
442+
PyErr_Clear();
443+
}
426444

445+
if (internals_pp) {
427446
// We loaded builtins through python's builtins, which means that our `error_already_set`
428447
// and `builtin_exception` may be different local classes than the ones set up in the
429448
// initial exception translator, below, so add another for our local exception classes.
@@ -435,9 +454,7 @@ PYBIND11_NOINLINE internals &get_internals() {
435454
(*internals_pp)->registered_exception_translators.push_front(&translate_local_exception);
436455
#endif
437456
} else {
438-
if (!internals_pp) {
439-
internals_pp = new internals *();
440-
}
457+
internals_pp = new internals *();
441458
auto *&internals_ptr = *internals_pp;
442459
internals_ptr = new internals();
443460
#if defined(WITH_THREAD)
@@ -459,7 +476,7 @@ PYBIND11_NOINLINE internals &get_internals() {
459476
# endif
460477
internals_ptr->istate = tstate->interp;
461478
#endif
462-
builtins[id] = capsule(internals_pp);
479+
state_dict[id] = capsule(internals_pp, id_cstr);
463480
internals_ptr->registered_exception_translators.push_front(&translate_exception);
464481
internals_ptr->static_property_type = make_static_property_type();
465482
internals_ptr->default_metaclass = make_default_metaclass();

0 commit comments

Comments
 (0)