SIP: Virtual pure method with std::function

Phil Thompson phil at riverbankcomputing.com
Thu Apr 1 11:53:31 BST 2021


On 01/04/2021 10:58, Julien Cabieces 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.

You need to provide the C++ signature in [] after the Python signature. 
See the example in this section...

https://www.riverbankcomputing.com/static/Docs/sip/directives.html#std-directive-VirtualCatcherCode

...and you need to provide %VirtualCatcherCode.

Phil


More information about the PyQt mailing list