mirror of
https://github.com/pybind/pybind11.git
synced 2025-02-16 21:57:55 +00:00
Alternative approach to #3807 that supports an important PyCLIF use case: Base
not specified in classh<Derived>
statement, but passing Derived as Base works anyway.
This commit is contained in:
parent
fb78376ecd
commit
f27bd9a3bb
@ -60,7 +60,7 @@ inline void *try_as_void_ptr_capsule_get_pointer(handle src, const char *typeid_
|
||||
|
||||
std::string as_void_ptr_function_name("as_");
|
||||
as_void_ptr_function_name += type_name;
|
||||
if (hasattr(src, as_void_ptr_function_name.c_str())) {
|
||||
if (hasattr(src, as_void_ptr_function_name.c_str()) && !hasattr(src, "__getattr__")) {
|
||||
auto as_void_ptr_function = function(src.attr(as_void_ptr_function_name.c_str()));
|
||||
auto void_ptr_capsule = as_void_ptr_function();
|
||||
if (isinstance<capsule>(void_ptr_capsule)) {
|
||||
@ -304,11 +304,8 @@ public:
|
||||
loaded_v_h = value_and_holder();
|
||||
return true;
|
||||
}
|
||||
if (convert && cpptype) {
|
||||
const auto &bases = all_type_info(srctype);
|
||||
if (bases.empty() && try_as_void_ptr_capsule(src)) {
|
||||
return true;
|
||||
}
|
||||
if (convert && cpptype && try_as_void_ptr_capsule(src)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -58,20 +58,33 @@ struct Derived2 : Base12 {
|
||||
int bar() const { return 2; }
|
||||
};
|
||||
|
||||
struct UnspecBase {
|
||||
virtual ~UnspecBase() = default;
|
||||
virtual int Get() const { return 100; }
|
||||
};
|
||||
|
||||
inline int PassUnspecBase(const UnspecBase &sb) { return sb.Get() + 30; }
|
||||
|
||||
struct UnspecDerived : UnspecBase {
|
||||
int Get() const override { return 200; }
|
||||
};
|
||||
|
||||
} // namespace class_sh_void_ptr_capsule
|
||||
} // namespace pybind11_tests
|
||||
|
||||
PYBIND11_SMART_HOLDER_TYPE_CASTERS(pybind11_tests::class_sh_void_ptr_capsule::Valid)
|
||||
PYBIND11_SMART_HOLDER_TYPE_CASTERS(pybind11_tests::class_sh_void_ptr_capsule::TypeWithGetattr)
|
||||
PYBIND11_SMART_HOLDER_TYPE_CASTERS(pybind11_tests::class_sh_void_ptr_capsule::Base1)
|
||||
PYBIND11_SMART_HOLDER_TYPE_CASTERS(pybind11_tests::class_sh_void_ptr_capsule::Base2)
|
||||
PYBIND11_SMART_HOLDER_TYPE_CASTERS(pybind11_tests::class_sh_void_ptr_capsule::Base12)
|
||||
PYBIND11_SMART_HOLDER_TYPE_CASTERS(pybind11_tests::class_sh_void_ptr_capsule::Derived1)
|
||||
PYBIND11_SMART_HOLDER_TYPE_CASTERS(pybind11_tests::class_sh_void_ptr_capsule::Derived2)
|
||||
using namespace pybind11_tests::class_sh_void_ptr_capsule;
|
||||
|
||||
PYBIND11_SMART_HOLDER_TYPE_CASTERS(Valid)
|
||||
PYBIND11_SMART_HOLDER_TYPE_CASTERS(TypeWithGetattr)
|
||||
PYBIND11_SMART_HOLDER_TYPE_CASTERS(Base1)
|
||||
PYBIND11_SMART_HOLDER_TYPE_CASTERS(Base2)
|
||||
PYBIND11_SMART_HOLDER_TYPE_CASTERS(Base12)
|
||||
PYBIND11_SMART_HOLDER_TYPE_CASTERS(Derived1)
|
||||
PYBIND11_SMART_HOLDER_TYPE_CASTERS(Derived2)
|
||||
PYBIND11_SMART_HOLDER_TYPE_CASTERS(UnspecBase)
|
||||
PYBIND11_SMART_HOLDER_TYPE_CASTERS(UnspecDerived)
|
||||
|
||||
TEST_SUBMODULE(class_sh_void_ptr_capsule, m) {
|
||||
using namespace pybind11_tests::class_sh_void_ptr_capsule;
|
||||
|
||||
py::classh<Valid>(m, "Valid");
|
||||
|
||||
m.def("get_from_valid_capsule", &get_from_valid_capsule);
|
||||
@ -102,4 +115,13 @@ TEST_SUBMODULE(class_sh_void_ptr_capsule, m) {
|
||||
py::classh<Derived1, Base12>(m, "Derived1").def(py::init<>()).def("bar", &Derived1::bar);
|
||||
|
||||
py::classh<Derived2, Base12>(m, "Derived2").def(py::init<>()).def("bar", &Derived2::bar);
|
||||
|
||||
py::classh<UnspecBase>(m, "UnspecBase");
|
||||
m.def("PassUnspecBase", PassUnspecBase);
|
||||
py::classh<UnspecDerived>(m, "UnspecDerived") // UnspecBase NOT specified as base here.
|
||||
.def(py::init<>())
|
||||
.def("as_pybind11_tests_class_sh_void_ptr_capsule_UnspecBase", [](UnspecDerived *self) {
|
||||
return py::reinterpret_steal<py::object>(
|
||||
PyCapsule_New(static_cast<void *>(self), nullptr, nullptr));
|
||||
});
|
||||
}
|
||||
|
@ -94,3 +94,7 @@ def test_multiple_inheritance_getattr():
|
||||
assert d2.foo() == 0
|
||||
assert d2.bar() == 2
|
||||
assert d2.prop2 == "Base GetAttr: prop2"
|
||||
|
||||
|
||||
def test_pass_unspecified_base():
|
||||
assert m.PassUnspecBase(m.UnspecDerived()) == 230
|
||||
|
Loading…
Reference in New Issue
Block a user