[PyQt] [SIP] SIP_PYCALLABLE in constructor

Sandro Mani manisandro at gmail.com
Thu Oct 31 09:22:42 GMT 2019


Hi

I'm trying to create bindings for a class Foo with a constructor taking 
a std::function, so basically for

     typedef std::function<Item*()> ItemFactory;
     Foo( ItemFactory factory, QObject* parent = 0 );

in the sip file I'm writing

     Foo( SIP_PYCALLABLE factory, QObject *parent = 0 );
     %MethodCode

     // Make sure the callable doesn't get garbage collected, this is 
needed because refcount for a1 is 0
     // and the creation function pointer is passed to the metadata and 
it needs to be kept in memory.
     Py_INCREF( a0 );

     Py_BEGIN_ALLOW_THREADS

     auto factory = [a0]() -> Item *
     {
       Item *result = nullptr;
       SIP_BLOCK_THREADS
       PyObject *s = sipCallMethod( NULL, a0, NULL );
       int state;
       int sipIsError = 0;
       result = reinterpret_cast<Item *>( sipConvertToType( s, 
sipType_Item, NULL, SIP_NO_CONVERTORS, &state, &sipIsError ) );
       SIP_UNBLOCK_THREADS
       return result;
     };

     sipCpp = new sipFoo( factory, a1 );

     Py_END_ALLOW_THREADS

     %End

This however does not work, due to

error: no matching function for call to ‘Foo::Foo(PyObject*&, QObject*&)’

Any pointers how to do this? Full example code below.

Many thanks
Sandro


-------------- foo.h --------------

#ifndef FOO_H
#define FOO_H

#include <functional>
#include <QObject>
#include <QVector>


class Item {
public:
     virtual ~Item() {}
};

class Foo : public QObject
{
     Q_OBJECT
   public:
     typedef std::function<Item*()> ItemFactory;
     Foo( ItemFactory factory, QObject* parent = 0 );
     ~Foo();
     void create();

   private:
     ItemFactory mFactory;
     QVector<Item *> mItems;
};

#endif // FOO_H


-------------- foo.cpp --------------

#include "foo.h"

Foo::Foo( ItemFactory factory, QObject *parent )
   : QObject( parent ), mFactory(factory)
{
}

Foo::~Foo()
{
   qDeleteAll( mItems );
}

void Foo::create()
{
     mItems.append(mFactory());
}


-------------- foo.sip --------------

%Module(name=foo,
         keyword_arguments="All")

%Import QtCore/QtCoremod.sip

class Item
{
%TypeHeaderCode
#include "foo.h"
%End
     virtual ~Item();
};

class Foo : QObject
{
%TypeHeaderCode
#include "foo.h"
%End
   public:
     Foo( SIP_PYCALLABLE factory, QObject *parent = 0 );
     %MethodCode

     // Make sure the callable doesn't get garbage collected, this is 
needed because refcount for a1 is 0
     // and the creation function pointer is passed to the metadata and 
it needs to be kept in memory.
     Py_INCREF( a0 );

     Py_BEGIN_ALLOW_THREADS

     auto factory = [a0]() -> Item *
     {
       Item *result = nullptr;
       SIP_BLOCK_THREADS
       PyObject *s = sipCallMethod( NULL, a0, NULL );
       int state;
       int sipIsError = 0;
       result = reinterpret_cast<Item *>( sipConvertToType( s, 
sipType_Item, NULL, SIP_NO_CONVERTORS, &state, &sipIsError ) );
       SIP_UNBLOCK_THREADS
       return result;
     };

     sipCpp = new sipFoo( factory, a1 );

     Py_END_ALLOW_THREADS

     %End
     ~Foo();
};


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://www.riverbankcomputing.com/pipermail/pyqt/attachments/20191031/fa068d3c/attachment.html>


More information about the PyQt mailing list