[C++-sig] problem returning polymorphic shared_ptr instances
I'm stumped on a problem encountered when trying to return a derived instance
via a shared_ptr to python. The python instance is always shown as a base class
and not the subclass that was created, as if the instance was sliced.
struct A {
};
struct B : A {
};
shared_ptr get_a_or_b_instance(bool returnB) {
return shared_ptr(returnB ? new B() : new A());
}
…
def("get_a_or_b_instance", get_a_or_b_instance);
class_ >("A", init<>())
;
class_, boost::noncopyable>("B", init<>())
;
And the Python result is always a type A object:
>>> type(app.get_a_or_b_instance(False))
>>> type(app.get_a_or_b_instance(True))
Where I would expect the derived instance type B returned from the second call.
I'm using Boost 1.42.0.
Thanks in advance for any help.
Matt Bendiksen
___
Cplusplus-sig mailing list
[email protected]
http://mail.python.org/mailman/listinfo/cplusplus-sig
Re: [C++-sig] problem returning polymorphic shared_ptr instances
On 01/12/2011 09:03 AM, Matt Bendiksen wrote:
I'm stumped on a problem encountered when trying to return a derived instance
via a shared_ptr to python. The python instance is always shown as a base class
and not the subclass that was created, as if the instance was sliced.
struct A {
};
struct B : A {
};
shared_ptr get_a_or_b_instance(bool returnB) {
return shared_ptr(returnB ? new B() : new A());
}
…
def("get_a_or_b_instance", get_a_or_b_instance);
class_ >("A", init<>())
;
class_, boost::noncopyable>("B", init<>())
;
And the Python result is always a type A object:
>>> type(app.get_a_or_b_instance(False))
>>> type(app.get_a_or_b_instance(True))
Where I would expect the derived instance type B returned from the second call.
I'm using Boost 1.42.0.
Thanks in advance for any help.
You need to either declare B with
"class_, bases"
or do
"register_ptr_to_python< boost::shared_ptr >()"
somewhere in your Python module. The latter will not cause B instances
to be stored in a shared_ptr when a Python constructor is called, but it
will still enable shared_ptr downcasting on return.
Jim
Matt Bendiksen
___
Cplusplus-sig mailing list
[email protected]
http://mail.python.org/mailman/listinfo/cplusplus-sig
___
Cplusplus-sig mailing list
[email protected]
http://mail.python.org/mailman/listinfo/cplusplus-sig
Re: [C++-sig] problem returning polymorphic shared_ptr instances
Thanks Jim, but I still cannot get it to work. I now have it defined as:
def("get_a_or_b_instance", get_a_or_b_instance);
class_ >("A", init<>())
;
class_, bases >("B", init<>())
;
(note I change your example line from "bases" to "bases")
I tried it with and without:
register_ptr_to_python< boost::shared_ptr >();
But from Python whenever I call:
type(app.get_a_or_b_instance(True))
I always get back:
Any other ideas?
Matt
___
Cplusplus-sig mailing list
[email protected]
http://mail.python.org/mailman/listinfo/cplusplus-sig
Re: [C++-sig] problem returning polymorphic shared_ptr instances
On 01/12/2011 12:06 PM, Matt Bendiksen wrote:
Thanks Jim, but I still cannot get it to work. I now have it defined as:
def("get_a_or_b_instance", get_a_or_b_instance);
class_ >("A", init<>())
;
class_, bases >("B", init<>())
;
(note I change your example line from "bases" to "bases")
Yeah, that's correct. Error on my part.
I tried it with and without:
register_ptr_to_python< boost::shared_ptr >();
But from Python whenever I call:
type(app.get_a_or_b_instance(True))
I always get back:
Any other ideas?
Yes. I just remembered that the downcasting only works if your classes
are polymorphic; otherwise dynamic_cast (which is the underlying
mechanism) doesn't work.
Adding a virtual destructor to the base class would be sufficient.
Jim
Matt
___
Cplusplus-sig mailing list
[email protected]
http://mail.python.org/mailman/listinfo/cplusplus-sig
___
Cplusplus-sig mailing list
[email protected]
http://mail.python.org/mailman/listinfo/cplusplus-sig
Re: [C++-sig] problem returning polymorphic shared_ptr instances
You are indeed correct -- I just needed to add a virtual method to the base class. As it turns out this wasn't the problem I was originally having in our application, so my attempt at creating a small sample of the problem wasn't complete. My project's code was failing for what turned out to be a different, albeit somewhat related reason. It already had many virtual methods including the destructor. The problem with my app was I had 2 levels deep of subclasses and I didn't realize the instance I was returning was the second descendant class and not the first, which was a problem because I hadn't yet defined the python bindings for the second descendant yet. So in python it ended up giving me the base class instead. Anyhow, everything is working now and I appreciate the prompt help. Regards, Matt > Yes. I just remembered that the downcasting only works if your classes are > polymorphic; otherwise dynamic_cast (which is the underlying mechanism) > doesn't work. > > Adding a virtual destructor to the base class would be sufficient. > > Jim ___ Cplusplus-sig mailing list [email protected] http://mail.python.org/mailman/listinfo/cplusplus-sig
