MappedType for unique_ptr

Nyall Dawson nyall.dawson at gmail.com
Thu Nov 21 08:53:59 GMT 2024


On Thu, 21 Nov 2024 at 18:36, Julien Cabieces
<julien.cabieces at oslandia.com> wrote:
>
>
> Hi,
>
> >       *sipCppPtr = new std::unique_ptr<TYPE>( t );
>
> If I understand well, you try to use the copy constructor which is
> deleted. I would rather write something like
>
> (*sipCppPtr).reset( t );

Unfortunately that doesn't help -- there's still a copy of the
unique_ptr made in the sip auto generated code:

std::unique_ptr< ::SomeClass>* a0;
...
Py_BEGIN_ALLOW_THREADS
try
{
  sipRes =  ::MyClass::setObject(*a0);
 }
catch (...)

(The copy is made by *a0 )

Nyall

>
> Regards,
> Julien
>
>
>
>
> > On Wed, 20 Nov 2024 at 20:40, Phil Thompson <phil at riverbankcomputing.com> wrote:
> >>
> >> On 20/11/2024 04:57, Nyall Dawson wrote:
> >> > Hi list,
> >> >
> >> > I'm wondering if any one has had any luck in creating a MappedType to
> >> > handle unique_ptr objects.
> >> >
> >> > I've been experimenting with the following implementation, which seems
> >> > to
> >> > work well for converting from unique_ptrs to Python owned objects. But
> >> > I
> >> > can't find any way to implement the ConvertToTypeCode so that I can
> >> > wrap
> >> > functions which have unique_ptr arguments.
> >> >
> >> > I'm really hoping to modernize some API and move away from raw
> >> > pointers,
> >> > but this is a stumbling block...
> >> >
> >> > template <TYPE>
> >> > %MappedType std::unique_ptr< TYPE >
> >> > /NoRelease,AllowNone,TypeHint="Optional[TYPE]",TypeHintValue="TYPE"/
> >> > {
> >> > %TypeHeaderCode
> >> > #include <memory>
> >> > %End
> >> >
> >> > %ConvertFromTypeCode
> >> >   const sipTypeDef *sip_type = sipFindType("TYPE*");
> >> >   return sipConvertFromNewType(sipCpp->release(), sip_type, NULL);
> >> > %End
> >>
> >> Obviously I don't know the detail of your use-case but you are
> >> hard-coding a particular ownership protocol by using
> >> sipConvertFromNewType() and release() rather than sipConvertFromType()
> >> and get().
> >
> > What I'm attempting to do is modernize some c++ API which looks like this:
> >
> >     SomeClass* createObject() { return new SomeClass(); }
> >     void setObject( SomeClass* object ) { // something which takes
> > ownership of object }
> >
> > Currently this would be exposed using sip bindings:
> >
> >    SomeClass* createObject() /Factory/;
> >    void setObject( SomeClass* object /Transfer/ );
> >
> > The modernized c++ API would be something like:
> >
> >     std::unique_ptr< SomeClass > createObject() { return
> > std::make_unique< SomeClass >(); }
> >     void setObject( std::unique_ptr< SomeClass > object ) { //
> > something which takes ownership of the pointed to object }
> >
> >> Obviously I don't know the detail of your use-case but you are
> >> hard-coding a particular ownership protocol by using
> >> sipConvertFromNewType() and release() rather than sipConvertFromType()
> >> and get().
> >
> > Here I can safely assume that .release() is correct, because we are
> > ALWAYS transferring ownership to the Python caller.
> >
> >>
> >> > %ConvertToTypeCode
> >> >   // only one way for now...
> >> >   return 0;
> >> > %End
> >> > };
> >>
> >> What's the problem with using the unique_ptr<> ctor?
> >
> > This is the closest I got:
> >
> > %ConvertToTypeCode
> >   const sipTypeDef *sip_type = sipFindType("TYPE");
> >
> >   if (sipIsErr == NULL)
> >   {
> >     if (!sipCanConvertToType(sipPy, sip_type, 0))
> >       return 0;
> >     return 1;
> >   }
> >
> >   if (sipPy == Py_None)
> >   {
> >       *sipCppPtr = new std::unique_ptr<TYPE>();
> >       return 1;
> >   }
> >   else
> >   {
> >       int state;
> >       TYPE *t = reinterpret_cast<TYPE *>(sipConvertToType(sipPy,
> > sip_type, sipTransferObj, 0, &state, sipIsErr));
> >       sipReleaseType(t, sip_type, state);
> >       if (*sipIsErr)
> >       {
> >           return 0;
> >       }
> >       *sipCppPtr = new std::unique_ptr<TYPE>( t );
> >       return sipGetState(sipTransferObj);
> >   }
> > %End
> >
> > However, it fails to build when used with the "void setObject(
> > std::unique_ptr< SomeClass > object );" function. I get a compilation
> > error:
> >
> > In function ‘PyObject* meth_MyClass_setObject(PyObject*, PyObject*, PyObject*)’:
> > error: use of deleted function ‘std::unique_ptr<_Tp,
> > _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp =
> > SomeClass; _Dp = std::default_delete<SomeClass>]’
> >
> > Thanks,
> > Nyall
>
> --
>
> Julien Cabieces
> Senior Developer at Oslandia
> julien.cabieces at oslandia.com


More information about the PyQt mailing list