SIP: Virtual pure method with std::function

Julien Cabieces julien.cabieces at oslandia.com
Tue Apr 6 13:27:47 BST 2021


Hi Denis,

> For the sake of clarity, you might want to filter out what is specific to
> QGIS syntax, mainly all the SIP_* macros.
> The sipify script is a QGIS internal and not known further.

Indeed, I try to remove all the QGIS specifics, but I miss the SIP_*
macros.

Regards,
Julien

> Hi Julien,
>
> For the sake of clarity, you might want to filter out what is specific to
> QGIS syntax, mainly all the SIP_* macros.
> The sipify script is a QGIS internal and not known further.
>
>
> On Thu, 1 Apr 2021, 11:58 Julien Cabieces, <julien.cabieces at oslandia.com>
> wrote:
>
>>
>> Hi,
>>
>> I would like to define an interface (abstract class) where one method is
>> pure virtual and takes a std::function as a parameter.
>>
>> I have this in my C++ header
>>
>> ```
>> class MyInterface
>> {
>>   public:
>>
>> #ifndef SIP_RUN
>>     virtual MyObject *doThings( const QString &filePath, const QUrl &url,
>>                                 const std::function<void ( const QString &
>> )> &errorCallback = {} ) = 0 ;
>> #else
>>     virtual MyObject *doThings( const QString &filePath, const QUrl &url,
>> SIP_PYCALLABLE / AllowNone / ) = 0;
>>     % MethodCode
>>     {
>>       Py_BEGIN_ALLOW_THREADS
>>
>>       sipCpp->MyInterface::doThings( *a0, *a1, [a2]( const QString  &
>> error )
>>       {
>>         SIP_BLOCK_THREADS
>>         Py_XDECREF( sipCallMethod( NULL, a2, "D", &error, sipType_QString,
>> NULL ) );
>>         SIP_UNBLOCK_THREADS
>>       } );
>>
>>       sipRes = sipCpp;
>>
>>       Py_END_ALLOW_THREADS
>>     }
>>     % End
>> #endif
>> ```
>>
>> and this in the corresponding sip file
>>
>> ```
>> class MyInterface
>> {
>>
>> %TypeHeaderCode
>> #include "myinterface.h"
>> %End
>>   public:
>>
>>     virtual MyObject *doThings( const QString &filePath, const QUrl &url,
>> SIP_PYCALLABLE / AllowNone / ) = 0;
>> %MethodCode
>>     {
>>       Py_BEGIN_ALLOW_THREADS
>>
>>       sipCpp->MyInterface::doThings( *a0, *a1, [a2]( const QString  &
>> error )
>>       {
>>         SIP_BLOCK_THREADS
>>         Py_XDECREF( sipCallMethod( NULL, a2, "D", &error, sipType_QString,
>> NULL ) );
>>         SIP_UNBLOCK_THREADS
>>       } );
>>
>>       sipRes = sipCpp;
>>
>>       Py_END_ALLOW_THREADS
>>     }
>> %End
>>
>> };
>> ```
>>
>> I end up with the following compilation errors
>>
>> ```
>> error: non-virtual member function marked 'override' hides virtual member
>> function
>>      ::MyObject* doThings(const  ::QString&,const  ::QUrl&,PyObject *)
>> SIP_OVERRIDE;
>>
>> hidden overloaded virtual function 'MyInterface::doThings' declared here:
>> type mismatch at 3rd parameter ('const std::function<void (const QString
>> &)> &' vs 'PyObject *' (aka '_object *'))
>>            virtual MyObject *doThings( const QString &filePath, const QUrl
>> &url,
>>                      ^
>>  error: allocating an object of abstract class type 'sipMyInterface'
>>             sipCpp = new sipMyInterface();
>>                          ^
>> note: unimplemented pure virtual method 'doThings' in 'sipMyInterface'
>>     virtual MyObject *doThings( const QString &filePath, const QUrl &url,
>> ```
>>
>> The errors make sense to me because the sip doThings version has not the
>> same signature than the original Cpp one (Callable vs std::function) but
>> I fail to understand how to fix this.
>>
>> Kind regards,
>> Julien
>>



More information about the PyQt mailing list