[C++-sig] problem returning polymorphic shared_ptr instances

2011-01-12 Thread Matt Bendiksen
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

2011-01-12 Thread Jim Bosch

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

2011-01-12 Thread Matt Bendiksen
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

2011-01-12 Thread Jim Bosch

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

2011-01-12 Thread Matt Bendiksen
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