MappedType for unique_ptr

Julien Cabieces julien.cabieces at oslandia.com
Thu Nov 21 11:12:53 GMT 2024


Ho yes, we need to std::move the *a0 but I have no idea on how we can
do that

> 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

-- 

Julien Cabieces
Senior Developer at Oslandia
julien.cabieces at oslandia.com


More information about the PyQt mailing list