@@ -128,6 +128,14 @@ PYBIND11_NOINLINE inline internals &get_internals() {
128128 return *internals_ptr;
129129}
130130
131+ namespace {
132+ // Works like internals.registered_types_cpp, but for module-local registered types:
133+ inline type_map<void *> ®istered_local_types_cpp () {
134+ static type_map<void *> locals{};
135+ return locals;
136+ }
137+ }
138+
131139// / A life support system for temporary objects created by `type_caster::load()`.
132140// / Adding a patient will keep it alive up until the enclosing function returns.
133141class loader_life_support {
@@ -215,7 +223,7 @@ PYBIND11_NOINLINE inline void all_type_info_populate(PyTypeObject *t, std::vecto
215223 // registered types
216224 if (i + 1 == check.size ()) {
217225 // When we're at the end, we can pop off the current element to avoid growing
218- // `check` when adding just one base (which is typical--.e. when there is no
226+ // `check` when adding just one base (which is typical--i .e. when there is no
219227 // multiple inheritance)
220228 check.pop_back ();
221229 i--;
@@ -259,13 +267,18 @@ PYBIND11_NOINLINE inline detail::type_info* get_type_info(PyTypeObject *type) {
259267 return bases.front ();
260268}
261269
262- PYBIND11_NOINLINE inline detail::type_info *get_type_info (const std::type_info &tp,
270+ // / Return the type info for a given C++ type; on lookup failure can either throw or return nullptr.
271+ PYBIND11_NOINLINE inline detail::type_info *get_type_info (const std::type_index &tp,
263272 bool throw_if_missing = false ) {
273+ std::type_index type_idx (tp);
264274 auto &types = get_internals ().registered_types_cpp ;
265-
266- auto it = types.find (std::type_index (tp));
275+ auto it = types.find (type_idx);
267276 if (it != types.end ())
268277 return (detail::type_info *) it->second ;
278+ auto &locals = registered_local_types_cpp ();
279+ it = locals.find (type_idx);
280+ if (it != locals.end ())
281+ return (detail::type_info *) it->second ;
269282 if (throw_if_missing) {
270283 std::string tname = tp.name ();
271284 detail::clean_type_id (tname);
@@ -723,10 +736,8 @@ class type_caster_generic {
723736 // with .second = nullptr. (p.first = nullptr is not an error: it becomes None).
724737 PYBIND11_NOINLINE static std::pair<const void *, const type_info *> src_and_type (
725738 const void *src, const std::type_info &cast_type, const std::type_info *rtti_type = nullptr ) {
726- auto &internals = get_internals ();
727- auto it = internals.registered_types_cpp .find (std::type_index (cast_type));
728- if (it != internals.registered_types_cpp .end ())
729- return {src, (const type_info *) it->second };
739+ if (auto *tpi = get_type_info (cast_type))
740+ return {src, const_cast <const type_info *>(tpi)};
730741
731742 // Not found, set error:
732743 std::string tname = rtti_type ? rtti_type->name () : cast_type.name ();
@@ -804,7 +815,6 @@ template <typename type> class type_caster_base : public type_caster_generic {
804815 template <typename T = itype, enable_if_t <std::is_polymorphic<T>::value, int > = 0 >
805816 static std::pair<const void *, const type_info *> src_and_type (const itype *src) {
806817 const void *vsrc = src;
807- auto &internals = get_internals ();
808818 auto &cast_type = typeid (itype);
809819 const std::type_info *instance_type = nullptr ;
810820 if (vsrc) {
@@ -813,9 +823,8 @@ template <typename type> class type_caster_base : public type_caster_generic {
813823 // This is a base pointer to a derived type; if it is a pybind11-registered type, we
814824 // can get the correct derived pointer (which may be != base pointer) by a
815825 // dynamic_cast to most derived type:
816- auto it = internals.registered_types_cpp .find (std::type_index (*instance_type));
817- if (it != internals.registered_types_cpp .end ())
818- return {dynamic_cast <const void *>(src), (const type_info *) it->second };
826+ if (auto *tpi = get_type_info (*instance_type))
827+ return {dynamic_cast <const void *>(src), const_cast <const type_info *>(tpi)};
819828 }
820829 }
821830 // Otherwise we have either a nullptr, an `itype` pointer, or an unknown derived pointer, so
0 commit comments