MappedType for unique_ptr
Nyall Dawson
nyall.dawson at gmail.com
Wed Nov 20 22:18:05 GMT 2024
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
More information about the PyQt
mailing list