Replies: 2 comments 1 reply
-
There are two ways: easy and advanced. Easy hot-fix is to simply bind py::class_<C, std::shared_ptr<C>, B> cls_c(m, "C"); This also allows to inherit all function bindings of However you want upcasting (upcasting from child to parent). Here comes a solution with the custom caster, notice the lack of explicit namespace pybind11
{
namespace detail
{
template <>
struct type_caster<std::shared_ptr<C>>
{
public:
// Python -> C++
bool load(handle src, bool convert)
{
if (!isinstance<std::shared_ptr<C>>(src))
{
return false;
}
// Add code here if necessary...
return true;
}
// C++ -> Python
static handle cast(std::shared_ptr<C> &&src, return_value_policy policy, handle parent)
{
// If there is a need to cast shared_ptr<C> back to Python, use caster from parent class
// which is already registered when py::class_ is called during compilation bindings.
// Leave rest of the work to the internals of C++.
return type_caster<std::shared_ptr<B>>::cast(src, policy, parent);
}
// Name of type is just for demonstration:)
PYBIND11_TYPE_CASTER(std::shared_ptr<C>, const_name("C_downgraded"));
};
}
}
PYBIND11_MODULE(mymodule, m)
{
py::class_<A, std::shared_ptr<A>> cls_a(m, "A");
py::class_<B, std::shared_ptr<B>, A> cls_b(m, "B");
cls_b.def("g", &B::g);
m.def("fun", []()
{ return std::make_shared<A>(); });
m.def("bar", []()
{ return std::make_shared<B>(); });
m.def("boo", []()
{ return std::make_shared<C>(); });
} Now let's test it out: >>> import mymodule
>>> tmp = mymodule.fun()
>>> tmp
<mymodule.A object at 0x1012980b0>
>>> tmp = mymodule.bar()
>>> tmp
<mymodule.B object at 0x101298130>
>>> tmp.g()
1
>>> tmp = mymodule.boo()
>>> tmp
<mymodule.B object at 0x1012980f0>
>>> tmp.g()
1 Nice! Even if you look into
I hope that provides a base for your fully working solution, cheers! |
Beta Was this translation helpful? Give feedback.
-
@jiwaszki Thanks for your solution, unfortunately, I have no clue about the actual implementation under I managed to fix it by using the |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
I have a class hierarchy like so:
Both
A
andB
have bindings:If I return a
std::shared_ptr<B>
from a function returning astd::shared_ptr<A>
, I get proper downcasting, but not if I return astd::shared_ptr<C>
. Is there a way to get proper downcasting, i.e., get aB
on the Python side when returning astd::shared_ptr<C>
?I tried using
polymorphic_type_hook
:But that completely breaks stuff, e.g., if something returns a
std::shared_ptr<B>
(orC
), the output ofg()
in Python is something like-1175756672
instead of 1. In my actual application, this just crashes everything.Beta Was this translation helpful? Give feedback.
All reactions