From: Luke M. <lu...@si...> - 2006-05-04 03:18:22
|
Luke Moore wrote: > Thank you very much. It works beautifully. > > -Luke > > Marcelo Matus wrote: >> Check the refcount.i example and the %extend_smart_pointer macrlo. I >> think that solves >> most of the issues with smart pointers and smart pointers + vectors. >> >> Marcelo %extend_smart_pointer has worked great, but I've since run into a case that doesn't work. Here's a simple example describing the problem. Swig is wrapping a class named C, and I'm using boost::shared_ptr as the smart pointer. I have a function that takes a pointer to a C object named foo(): void foo(C* c); a function that returns a single shared pointer, createSingle(): boost::shared_ptr<C> createSingle(); and a function that returns multiple shared pointers, createMulti(): std::vector<boost::shared_ptr<C> > createMulti() foo(createSingle()) works without a problem. foo(createMulti()[0]) raises a TypeError because it can't convert to a C*. It seems to be because the C* isn't added to the swig object's "this" list: >>> foo.createSingle().this <Swig Object of type 'boost::shared_ptr<C > *' at 0x81a4540><Swig Object of type 'C *' at 0x8152438> >>> foo.createMulti()[0].this <Swig Object of type 'boost::shared_ptr<C > *' at 0x8146a08> Looking at the wrapper code, createSingle() is applying the SMARTPOINTER typemap from pytypemaps.swg, calling __deref__ and adding the result to "this". createMulti() is calling swig::from() on shared pointer, which I think eventually calls swig::traits_from_ptr<...>::from(), calling SWIG_NewPointerObj() but not applying the typemap. If I manually specialize traits_from_ptr for my shared pointer, I believe it works: %{ namespace swig { template <> struct traits_from_ptr<boost::shared_ptr<C> > { static PyObject *from(boost::shared_ptr<C> *val, int owner = 0) { PyObject *resultobj = SWIG_NewPointerObj(val, type_info<boost::shared_ptr<C> >(), owner); if (resultobj) { PyObject *robj = PyObject_CallMethod(resultobj, "__deref__", NULL); if (robj && !PyErr_Occurred()) { PySwigObject_append((PyObject *) SWIG_Python_GetSwigThis(resultobj), (PyObject *)SWIG_Python_GetSwigThis(robj)); Py_DECREF(robj); } } return resultobj; } }; } %} Shouldn't the typemap do this specialization automatically, though? Note that I'm using %extend_smart_pointer(boost::shared_ptr<C>); %template(_CShrdPtr) boost::shared_ptr<C>; %template(_CShrdPtrList) std::vector<boost::shared_ptr<C> >; and I'm running swig 1.3.29. Thanks for any help. -Luke |