@@ -51,7 +51,7 @@ struct type_info {
51
51
std::vector<bool (*)(PyObject *, void *&)> *direct_conversions;
52
52
buffer_info *(*get_buffer)(PyObject *, void *) = nullptr ;
53
53
void *get_buffer_data = nullptr ;
54
- bool (type_caster_generic:: *module_local_load)(handle, bool ) = nullptr ;
54
+ void *( *module_local_load)(PyObject *, const type_info * ) = nullptr ;
55
55
/* A simple type never occurs as a (direct or indirect) parent
56
56
* of a class that makes use of multiple inheritance */
57
57
bool simple_type : 1 ;
@@ -586,6 +586,8 @@ class type_caster_generic {
586
586
PYBIND11_NOINLINE type_caster_generic (const std::type_info &type_info)
587
587
: typeinfo(get_type_info(type_info)) { }
588
588
589
+ type_caster_generic (const type_info *typeinfo) : typeinfo(typeinfo) { }
590
+
589
591
bool load (handle src, bool convert) {
590
592
return load_impl<type_caster_generic>(src, convert);
591
593
}
@@ -663,8 +665,6 @@ class type_caster_generic {
663
665
return inst.release ();
664
666
}
665
667
666
- protected:
667
-
668
668
// Base methods for generic caster; there are overridden in copyable_holder_caster
669
669
void load_value (value_and_holder &&v_h) {
670
670
auto *&vptr = v_h.value_ptr ();
@@ -694,35 +694,22 @@ class type_caster_generic {
694
694
}
695
695
void check_holder_compat () {}
696
696
697
- // If loading failed with the type visible to this module see if we can load by looking to
698
- // other modules. There are two possibilities here:
699
- // - the input type is actually for another module's `py::module_local` type; we can try getting
700
- // the other module to load it.
701
- // - the input type is a globally-registered type, but we failed to load it because we have a module-local
702
- // override; we can replace our typeinfo with the global typeinfo and try loading again.
703
- PYBIND11_NOINLINE bool try_external_load (handle src) {
704
- allow_externals = true ; // Don't recurse
705
-
706
- str local_key (" _pybind11_module_local_typeinfo" );
707
- if (hasattr ((PyObject *) Py_TYPE (src.ptr ()), local_key)) {
708
- type_info *foreign_typeinfo = reinterpret_borrow<capsule>(getattr (src, local_key));
709
-
710
- // Only consider this foreign loader if actually foreign
711
- if (foreign_typeinfo->module_local_load != &type_caster_generic::load) {
712
- typeinfo = foreign_typeinfo;
713
- return (this ->*(foreign_typeinfo->module_local_load ))(src, false );
714
- }
697
+ // / Try to load with foreign typeinfo, if available. Used when there is no
698
+ // / native typeinfo, or when the native one wasn't able to produce a value.
699
+ PYBIND11_NOINLINE bool try_load_foreign_module_local (handle src) {
700
+ constexpr auto *local_key = " _pybind11_module_local_typeinfo" ;
701
+ const auto pytype = src.get_type ();
702
+ if (!hasattr (pytype, local_key))
715
703
return false ;
716
- }
717
704
718
- // The type is not module_local; if the type we looked up is, try again with the global type
719
- if (typeinfo && typeinfo->module_local ) {
720
- if (auto gtype = get_global_type_info (*typeinfo->cpptype )) {
721
- typeinfo = gtype;
722
- return load (src, false );
723
- }
724
- }
705
+ type_info *foreign_typeinfo = reinterpret_borrow<capsule>(getattr (pytype, local_key));
706
+ if (foreign_typeinfo == typeinfo)
707
+ return false ; // Only consider this foreign loader if actually foreign
725
708
709
+ if (auto result = foreign_typeinfo->module_local_load (src.ptr (), foreign_typeinfo)) {
710
+ value = result;
711
+ return true ;
712
+ }
726
713
return false ;
727
714
}
728
715
@@ -732,7 +719,7 @@ class type_caster_generic {
732
719
template <typename ThisT>
733
720
PYBIND11_NOINLINE bool load_impl (handle src, bool convert) {
734
721
if (!src) return false ;
735
- if (!typeinfo) return allow_externals && try_external_load (src);
722
+ if (!typeinfo) return try_load_foreign_module_local (src);
736
723
if (src.is_none ()) {
737
724
// Defer accepting None to other overloads (if we aren't in convert mode):
738
725
if (!convert) return false ;
@@ -798,7 +785,16 @@ class type_caster_generic {
798
785
return true ;
799
786
}
800
787
801
- return allow_externals && try_external_load (src);
788
+ // Failed to match local typeinfo. Try again with global.
789
+ if (typeinfo->module_local ) {
790
+ if (auto gtype = get_global_type_info (*typeinfo->cpptype )) {
791
+ typeinfo = gtype;
792
+ return load (src, false );
793
+ }
794
+ }
795
+
796
+ // Global typeinfo has precedence over foreign module_local
797
+ return try_load_foreign_module_local (src);
802
798
}
803
799
804
800
@@ -820,7 +816,6 @@ class type_caster_generic {
820
816
821
817
const type_info *typeinfo = nullptr ;
822
818
void *value = nullptr ;
823
- bool allow_externals = true ;
824
819
};
825
820
826
821
/* *
0 commit comments