@@ -242,6 +242,16 @@ inline void translate_exception(std::exception_ptr p) {
242
242
}
243
243
}
244
244
245
+ #if !defined(__GLIBCXX__)
246
+ inline void translate_local_exception (std::exception_ptr p) {
247
+ try {
248
+ if (p) std::rethrow_exception (p);
249
+ } catch (error_already_set &e) { e.restore (); return ;
250
+ } catch (const builtin_exception &e) { e.set_error (); return ;
251
+ }
252
+ }
253
+ #endif
254
+
245
255
// / Return a reference to the current `internals` data
246
256
PYBIND11_NOINLINE inline internals &get_internals () {
247
257
auto **&internals_pp = get_internals_pp ();
@@ -260,6 +270,17 @@ PYBIND11_NOINLINE inline internals &get_internals() {
260
270
auto builtins = handle (PyEval_GetBuiltins ());
261
271
if (builtins.contains (id) && isinstance<capsule>(builtins[id])) {
262
272
internals_pp = static_cast <internals **>(capsule (builtins[id]));
273
+
274
+ // We loaded builtins through python's builtins, which means that our `error_already_set`
275
+ // and `builtin_exception` may be different local classes than the ones set up in the
276
+ // initial exception translator, below, so add another for our local exception classes.
277
+ //
278
+ // libstdc++ doesn't require this (types there are identified only by name)
279
+ // libc++ with CPython doesn't require this (types are explicitly exported)
280
+ // libc++ with PyPy still need it, awaiting further investigation
281
+ #if !defined(__GLIBCXX__)
282
+ (*internals_pp)->registered_exception_translators .push_front (&translate_local_exception);
283
+ #endif
263
284
} else {
264
285
if (!internals_pp) internals_pp = new internals*();
265
286
auto *&internals_ptr = *internals_pp;
0 commit comments