pointer_holder and pure virtual base classes
This is a followup to my efforts in the thread here: http://thread.gmane.org/gmane.comp.python.c++/10125/focus=10125 I seemed to have everything working but I just ran into a new problem. A simplified summary is: class Base { public: int getSomething() = 0; }; class DerivedA : public Base { public: int getSomething() { return 1; } } class DerivedB : public DerivedA { public: int getSomething() { return 1; } } I am wrapping these classes with a held_type of RefPtr<classType> except for the Base class because it is pure virtual. (this is a custom ref counting pointer; see thread above for details) I thought everything was good until I tried to wrap a factory class. The class can return any class type but it returns it through a pointer to the Base class like this: class Store { public: RefPtr<Base> getObject(int id); }; The problem wrapping this is that since I do not have a held_type registered for the base type as RefPtr<Base>, there is no to_python (by-value) converter found for C++ type: RefPtr<Base>. As an attempt to fix this I set the held type for Base to RefPtr<Base>, but this fails because pointer_holder.hpp line 179 needs to be able to alloate an object of the pointee type. Since it is pure virtual the compiler fails here. So my question is, when dealing with a polymorphic hierarchy like this is is possible to use a smart pointer as a held type for the most basic types? (ie. the pure virtual base). If not, does anyone have suggested workarounds for me to try? Thanks, Allen Note: One simplification I made above is that there is another pointer type in the mix. So getObject is actually returning a BasePtr that boost.python knows how to convert to a RefPtr<BasePtr>. See the previous thread for all the details.
On 9/19/06, Allen Bierbaum <abierbaum@gmail.com> wrote:
This is a followup to my efforts in the thread here: http://thread.gmane.org/gmane.comp.python.c++/10125/focus=10125
I seemed to have everything working but I just ran into a new problem. A simplified summary is:
class Base { public: int getSomething() = 0; };
class DerivedA : public Base { public: int getSomething() { return 1; } }
class DerivedB : public DerivedA { public: int getSomething() { return 1; } }
I am wrapping these classes with a held_type of RefPtr<classType> except for the Base class because it is pure virtual. (this is a custom ref counting pointer; see thread above for details)
I thought everything was good until I tried to wrap a factory class. The class can return any class type but it returns it through a pointer to the Base class like this:
class Store { public: RefPtr<Base> getObject(int id); };
The problem wrapping this is that since I do not have a held_type registered for the base type as RefPtr<Base>, there is no to_python (by-value) converter found for C++ type: RefPtr<Base>.
As an attempt to fix this I set the held type for Base to RefPtr<Base>, but this fails because pointer_holder.hpp line 179 needs to be able to alloate an object of the pointee type. Since it is pure virtual the compiler fails here.
So my question is, when dealing with a polymorphic hierarchy like this is is possible to use a smart pointer as a held type for the most basic types? (ie. the pure virtual base). If not, does anyone have suggested workarounds for me to try?
David Abrahams solved this problem for my case. See "custom smart pointer" thread. Basically you will have to set as HeldType RefPtr<BaseWrapper>, where BaseWrapper is a wrapper class, that defines "override" for pure virtual functions. Your smart pointer shoud support construction of RefPtr<Base> from RefPtr<Derived>. -- Roman Yakovenko C++ Python language binding http://www.language-binding.net/
Sorry to reply to an old e-mail, but I just got time to revisit this issue. See below... On 9/19/06, Roman Yakovenko <roman.yakovenko@gmail.com> wrote:
On 9/19/06, Allen Bierbaum <abierbaum@gmail.com> wrote:
This is a followup to my efforts in the thread here: http://thread.gmane.org/gmane.comp.python.c++/10125/focus=10125
I seemed to have everything working but I just ran into a new problem. A simplified summary is:
class Base { public: int getSomething() = 0; };
class DerivedA : public Base { public: int getSomething() { return 1; } }
class DerivedB : public DerivedA { public: int getSomething() { return 1; } }
I am wrapping these classes with a held_type of RefPtr<classType> except for the Base class because it is pure virtual. (this is a custom ref counting pointer; see thread above for details)
I thought everything was good until I tried to wrap a factory class. The class can return any class type but it returns it through a pointer to the Base class like this:
class Store { public: RefPtr<Base> getObject(int id); };
The problem wrapping this is that since I do not have a held_type registered for the base type as RefPtr<Base>, there is no to_python (by-value) converter found for C++ type: RefPtr<Base>.
As an attempt to fix this I set the held type for Base to RefPtr<Base>, but this fails because pointer_holder.hpp line 179 needs to be able to alloate an object of the pointee type. Since it is pure virtual the compiler fails here.
So my question is, when dealing with a polymorphic hierarchy like this is is possible to use a smart pointer as a held type for the most basic types? (ie. the pure virtual base). If not, does anyone have suggested workarounds for me to try?
David Abrahams solved this problem for my case. See "custom smart pointer" thread.
Basically you will have to set as HeldType RefPtr<BaseWrapper>, where BaseWrapper is a wrapper class, that defines "override" for pure virtual functions.
Unfortunately I can't do this. The smart pointers I am using are not quite standard, so I can't apply them easily to the wrapper. I did find another way to do it though that almost works...
Your smart pointer shoud support construction of RefPtr<Base> from RefPtr<Derived>.
What I did was register a ptr_to_python for my base class RefPtr type. I also already had a to_python_converter registered for the type returned from the store (an FCPtr). So now with the ptr_to_python registered the path boost.python should be taking is: - I call the getObject method of the store which returns a FCPtr<Base> - A custom to_python converter gets called with returns a RefPtr<FcPtr<Base> >: "return bp::incref(bp::object(RefPtrType(fcPtr)).ptr());" - boost.python recognizes this type as a ptr because of a call I make to bp::register_ptr_to_python<RefPtr<FcPtr<Base> > >(); This all seems to work but I get a very strange error when trying to use an object returned through this path. Here is a sample run:
n = osg2.Node.create() osg2.FieldContainerFactory.the().getContainer(osg2.getContainerId(n)) <osg2._osg2.Node object at 0xb77eff2c> n2 = osg2.FieldContainerFactory.the().getContainer(191) n <osg2._osg2.Node object at 0xb77ef1ec> n2 <osg2._osg2.Node object at 0xb77ef36c> n.getType() <osg2._osg2.FieldContainerType object at 0xb7590ae4> n2.getType() Traceback (most recent call last): File "<input>", line 1, in ? ArgumentError: Python argument types in Node.getType(Node) did not match C++ signature: getType(OSG::Node {lvalue}) getType(OSG::Node {lvalue})
As you can see, the n2 variable type looks like it converted to the correct type but it doesn't work. Does anyone have any ideas what I should be looking for here? Any ideas how I can trace it down? Thanks, Allen
"Allen Bierbaum" <abierbaum@gmail.com> writes:
Unfortunately I can't do this. The smart pointers I am using are not quite standard
In most cases that shouldn't make a difference; you can always overload get_pointer and specialize pointee<>. -- Dave Abrahams Boost Consulting www.boost-consulting.com
On 10/29/06, David Abrahams <dave@boost-consulting.com> wrote:
"Allen Bierbaum" <abierbaum@gmail.com> writes:
Unfortunately I can't do this. The smart pointers I am using are not quite standard
In most cases that shouldn't make a difference; you can always overload get_pointer and specialize pointee<>.
I will look into this some more, but the issue wasn't telling boost.python about the pointers it was the the class library I am wrapping expects certain things to be true about the classes that you use it's smart pointers with and what can be done with them. Because of this it doesn't end up as easy as just making the held type be a smart ptr to the wrapper class. Like I said though I will give it some more thought and see if there is anything that can be done here. In the meantime, can you help point me in the right direction to figure out what is happening here that makes it look like I am wrapping an object of the right type but instead end up with an object that can't call it's methods? I just haven't run into this before so I am more then a bit confused about what could cause it. Thanks, Allen
participants (3)
-
Allen Bierbaum -
David Abrahams -
Roman Yakovenko