@@ -111,6 +111,12 @@ PYBIND11_NOINLINE inline internals &get_internals() {
111111 return *internals_ptr;
112112}
113113
114+ // Works like internals.registered_types_cpp, but for module-local registered types:
115+ inline type_map<void *> ®istered_local_types_cpp () {
116+ static type_map<void *> locals{};
117+ return locals;
118+ }
119+
114120// / A life support system for temporary objects created by `type_caster::load()`.
115121// / Adding a patient will keep it alive up until the enclosing function returns.
116122class loader_life_support {
@@ -198,7 +204,7 @@ PYBIND11_NOINLINE inline void all_type_info_populate(PyTypeObject *t, std::vecto
198204 // registered types
199205 if (i + 1 == check.size ()) {
200206 // When we're at the end, we can pop off the current element to avoid growing
201- // `check` when adding just one base (which is typical--.e. when there is no
207+ // `check` when adding just one base (which is typical--i .e. when there is no
202208 // multiple inheritance)
203209 check.pop_back ();
204210 i--;
@@ -242,13 +248,18 @@ PYBIND11_NOINLINE inline detail::type_info* get_type_info(PyTypeObject *type) {
242248 return bases.front ();
243249}
244250
245- PYBIND11_NOINLINE inline detail::type_info *get_type_info (const std::type_info &tp,
251+ // / Return the type info for a given C++ type; on lookup failure can either throw or return nullptr.
252+ PYBIND11_NOINLINE inline detail::type_info *get_type_info (const std::type_index &tp,
246253 bool throw_if_missing = false ) {
254+ std::type_index type_idx (tp);
247255 auto &types = get_internals ().registered_types_cpp ;
248-
249- auto it = types.find (std::type_index (tp));
256+ auto it = types.find (type_idx);
250257 if (it != types.end ())
251258 return (detail::type_info *) it->second ;
259+ auto &locals = registered_local_types_cpp ();
260+ it = locals.find (type_idx);
261+ if (it != locals.end ())
262+ return (detail::type_info *) it->second ;
252263 if (throw_if_missing) {
253264 std::string tname = tp.name ();
254265 detail::clean_type_id (tname);
@@ -706,10 +717,8 @@ class type_caster_generic {
706717 // with .second = nullptr. (p.first = nullptr is not an error: it becomes None).
707718 PYBIND11_NOINLINE static std::pair<const void *, const type_info *> src_and_type (
708719 const void *src, const std::type_info &cast_type, const std::type_info *rtti_type = nullptr ) {
709- auto &internals = get_internals ();
710- auto it = internals.registered_types_cpp .find (std::type_index (cast_type));
711- if (it != internals.registered_types_cpp .end ())
712- return {src, (const type_info *) it->second };
720+ if (auto *tpi = get_type_info (cast_type))
721+ return {src, const_cast <const type_info *>(tpi)};
713722
714723 // Not found, set error:
715724 std::string tname = rtti_type ? rtti_type->name () : cast_type.name ();
@@ -787,7 +796,6 @@ template <typename type> class type_caster_base : public type_caster_generic {
787796 template <typename T = itype, enable_if_t <std::is_polymorphic<T>::value, int > = 0 >
788797 static std::pair<const void *, const type_info *> src_and_type (const itype *src) {
789798 const void *vsrc = src;
790- auto &internals = get_internals ();
791799 auto &cast_type = typeid (itype);
792800 const std::type_info *instance_type = nullptr ;
793801 if (vsrc) {
@@ -796,9 +804,8 @@ template <typename type> class type_caster_base : public type_caster_generic {
796804 // This is a base pointer to a derived type; if it is a pybind11-registered type, we
797805 // can get the correct derived pointer (which may be != base pointer) by a
798806 // dynamic_cast to most derived type:
799- auto it = internals.registered_types_cpp .find (std::type_index (*instance_type));
800- if (it != internals.registered_types_cpp .end ())
801- return {dynamic_cast <const void *>(src), (const type_info *) it->second };
807+ if (auto *tpi = get_type_info (*instance_type))
808+ return {dynamic_cast <const void *>(src), const_cast <const type_info *>(tpi)};
802809 }
803810 }
804811 // Otherwise we have either a nullptr, an `itype` pointer, or an unknown derived pointer, so
0 commit comments