[C++-sig] Is there a way to automatically convert a smart_ptr to a held_type (try 2)

Allen Bierbaum abierbaum at gmail.com
Thu Sep 7 22:37:34 CEST 2006


On 9/7/06, Allen Bierbaum <abierbaum at gmail.com> wrote:
> On 9/7/06, Alex Mohr <amohr at pixar.com> wrote:
> > > The non-obvious part of this for me is:
> > >
> > > - Does this mean that I now need to explicitly wrap (expose using
> > > bp::class_ ) all the ref_ptr<>  types?
> > >
> > > I haven't had to do that thus far because it was handled internally
> > > somehow because I used it has the held_type for all my classes.  If I
> > > expose them manually do I run the risk of breaking any of the
> > > held_type functionality?
> >
> > I'm not sure what you mean...  If ref_ptr<T> is the held type for T,
> > then just provide __eq__ in terms of ref_ptr<T>...
> >
> > template <class T>
> > static bool ref_ptr_eq(ref_ptr<T> const &self, ref_ptr<T> const &other)
> > {
> >      return self == other;
> > }
> >
> > class_<T, ... ref_ptr<T> ... >(...)
> >      .def("__eq__", ref_ptr_eq<T>)
> >      ;
> >
> > Am I misunderstanding your situation?
>
> Ahhh....
>
> No I see what you are meaning.  So I need the __eq__ op on the class
> itself.  Ok.  That makes more sense.  I thought I may have to wrap the
> ref_ptr<T> as a class a and put the __eq__ op on it.
>
> Something like:
>
> class_<ref_ptr<T>, ..>(..)
>   .def("__eq__", ref_ptr_eq<T>)
> ;
>
> Thanks for the feedback.  I will try your method out and reply to the
> list with the results so other people following along can see what
> ended up working.

(I apologize for the length of this e-mail, I just want to make sure I
describe everything in case there is something basic I am missing)

This did not work out well.  It still has major problems because:
- Object allocated in python, passed to C++, and then returned from
C++ can't be compared
- Objects can't be compared to None anymore

Here is what I have done so far, if anyone has suggestions please let
me know (code generated from py++).

This is a combination of all the ideas discussed in this thread.  You
will notice that instead of defining an __eq__ I defined __cmp__ so
all the comparison operations would work.

typedef ::boost::python::class_< Group_wrapper,
::boost::python::bases< ::osg::GroupBase >, OSG::GroupRefPtr,
::boost::noncopyable > Group_exposer_t;
        Group_exposer_t Group_exposer = Group_exposer_t( "Group",
::boost::python::no_init );
...
        Group_exposer.def("__cmp__",pyopensg::cmp_ref_ptrs<OSG::GroupRefPtr>);
        Group_exposer.def("__hash__",pyopensg::hash_ref_ptr<OSG::GroupRefPtr>);
        register_fcptr_to_python<RefPtrType>::execute();
        fcptr_from_python<typename RefPtrType::FCPtrType>();
        bp::implicitly_convertible< OSG::GroupRefPtr, OSG::GroupPtr >();
        bp::implicitly_convertible< OSG::GroupRefPtr, OSG::NodeCoreRefPtr >();
    }
}

// Helpers are attached to the mail

There is also a class Node involved in the example code below.  In the
example I use two methods from there:

void Node::setCore(ptr<Base>);
ptr<Base> Node::getCore();

Here is some code that shows the problems

>>> g = osg.Group.create()
>>> g2 = osg.Group.create()
>>> g3 = g
>>> g == g2
False
>>> g == g3
True
>>> hash(g)
163
>>> hash(g2)
164
>>> n = osg.Node.create()
>>> n.setCore(g)
>>> core_g = n.getCore()
>>> core_g
<osg._osg.Group object at 0xafbf722c>
>>> g
<osg._osg.Group object at 0xb781fdac>

// Next line shows problem where the object coming back
// out of C++ can't be compared.  It is like it thinks it has
// a different type.
>>> g == core_g
Traceback (most recent call last):
  File "<input>", line 1, in ?
ArgumentError: Python argument types in
    Group.__cmp__(Group, Group)
did not match C++ signature:
    __cmp__(osg::RefPtr<osg::FCPtr<osg::FCPtr<osg::AttachmentContainerPtr,
osg::NodeCore>, osg::Group> >,
osg::RefPtr<osg::FCPtr<osg::FCPtr<osg::AttachmentContainerPtr,
osg::NodeCore>, osg::Group> >)

// This line shows the same problem with __hash__
>>> hash(core_g)
Traceback (most recent call last):
  File "<input>", line 1, in ?
ArgumentError: Python argument types in
    Group.__hash__(Group)
did not match C++ signature:
    __hash__(osg::RefPtr<osg::FCPtr<osg::FCPtr<osg::AttachmentContainerPtr,
osg::NodeCore>, osg::Group> >)

// And here is the problem comparing to None
>>> g == None
Traceback (most recent call last):
  File "<input>", line 1, in ?
ArgumentError: Python argument types in
    Group.__cmp__(Group, NoneType)
did not match C++ signature:
    __cmp__(osg::RefPtr<osg::FCPtr<osg::FCPtr<osg::AttachmentContainerPtr,
osg::NodeCore>, osg::Group> >,
osg::RefPtr<osg::FCPtr<osg::FCPtr<osg::AttachmentContainerPtr,
osg::NodeCore>, osg::Group> >)
>>>

I am at a loss to see what is causing this signature problem.  I don't
know of any way to ask boost.python to give me the "signature" of
python object at run-time, so I can't compare this signature with the
"good" signatures that work above.  From what I see though they look
very much the same.

I am going to try to trace back through the mailing list and look for
the object identity discussions you mentioned.  Maybe something in
those threads will provide a workaround that I can use.

As always, feel free to tell me if something looks way off.

Thanks,
Allen
-------------- next part --------------
A non-text attachment was scrubbed...
Name: bp_helpers.h
Type: text/x-chdr
Size: 2617 bytes
Desc: not available
URL: <http://mail.python.org/pipermail/cplusplus-sig/attachments/20060907/c82f06a3/attachment.h>


More information about the Cplusplus-sig mailing list