MappedType for unique_ptr

Julien Cabieces julien.cabieces at oslandia.com
Thu Nov 21 08:35:55 GMT 2024


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 );

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