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