Uploaded image for project: 'Qt for Python'
  1. Qt for Python
  2. PYSIDE-995

Shiboken does not recognize call operator from XML


    • Type: Bug
    • Status: Closed
    • Priority: Not Evaluated
    • Resolution: Done
    • Affects Version/s: 5.13
    • Fix Version/s: 5.12.3
    • Component/s: Shiboken
    • Labels:
    • Environment:
      Qt 5.13.0-beta1
      Fedora 29
    • Platform/s:
    • Commits:
      5b42f97fdfc0334e7628bbe30149227d0834edcd (pyside/pyside-setup/5.12)


      I have a simple class, representing a functor:

      #pragma once
      #include <QVector>
      #include <QObject>
      namespace bje::model {
      struct ChannelConfigurationFunctor {
          static QString name() { return "channel.configure"; }
          void operator()(QVector<QObject*> const&) const;

      When generating a wrapper for this class, the implementation of operator() is broken. I therefore remove it via the typesystem's XML file and replace it with a different implementation snippet:

      <!-- Escape sequences replaced with normal chars for convenience. Actual XML uses escaped chars. -->
      <object-type name="ChannelConfigurationFunctor">
          <modify-function signature="operator()(QVector<QObject*> const&)const" remove="all"/>
          <add-function signature="operator()(QVector<QObject*> const&)const">
              <inject-code file="glue/processors.cpp" snippet="generic-operatorcall"/>
      From the glue code file
      // @snippet generic-operatorcall
      PyThreadState* _save = PyEval_SaveThread(); // Py_BEGIN_ALLOW_THREADS
      const_cast<const ::bje::model::%CPPTYPE*>(%CPPSELF)->operator()(%1);
      PyEval_RestoreThread(_save); // Py_END_ALLOW_THREADS
      // @snippet generic-operatorcall

      This should, in theory, add a function named Sbk_bje_model_ChannelConfigurationFunctorFunc___call__ to the wrapper, as well as mark this function as this object's implementation of Python's __call__ method.

      As an aside...

      The implementation for the operator() method from the header file that Shiboken generates is, while broken in its implementation, correctly named and registered as this wrapper's implementation of __call__.

      The generated function, however, has a different name:

      From bje_model_channelconfigurationfunctor_wrapper.cpp
      static PyObject* Sbk_bje_model_ChannelConfigurationFunctorFunc_operator(PyObject* self, PyObject* pyArg)
          ::bje::model::ChannelConfigurationFunctor* cppSelf = nullptr;
          if (!Shiboken::Object::isValid(self))
              return {};
          cppSelf = reinterpret_cast< ::bje::model::ChannelConfigurationFunctor *>(Shiboken::Conversions::cppPointer(SbkfreeathomeTypes[SBK_BJE_MODEL_CHANNELCONFIGURATIONFUNCTOR_IDX], reinterpret_cast<SbkObject *>(self)));
          int overloadId = -1;
          PythonToCppFunc pythonToCpp{};
          // Overloaded function decisor
          // 0: ChannelConfigurationFunctor::operator(QVector<QObject*>)const
          if ((pythonToCpp = Shiboken::Conversions::isPythonToCppConvertible(SbkfreeathomeTypeConverters[SBK_FREEATHOME_QVECTOR_QOBJECTPTR_IDX], (pyArg)))) {
              overloadId = 0; // operator(QVector<QObject*>)const
          // Function signature not found.
          if (overloadId == -1) goto Sbk_bje_model_ChannelConfigurationFunctorFunc_operator_TypeError;
          // Call function/method
              ::QVector<QObject* > cppArg0;
              pythonToCpp(pyArg, &cppArg0);
              if (!PyErr_Occurred()) {
                  // operator(QVector<QObject*>)const
          if (PyErr_Occurred()) {
              return {};
              Shiboken::setErrorAboutWrongArguments(pyArg, "freeathome.bje.model.ChannelConfigurationFunctor.operator");
              return {};

      Also, note the empty block where the call to operator() should be made. There should be a snippet of code from my glue code file.

      When I rename the function to __call__ in the XML file, the generated function has the expected name (as well as the snippet correctly inserted), but is not marked as this object's __call__ implementation:

      From bje_model_channelconfigurationfunctor_wrapper.cpp
      static PyType_Slot Sbk_bje_model_ChannelConfigurationFunctor_slots[] = {
          {Py_tp_base,        nullptr}, // inserted by introduceWrapperType
          {Py_tp_dealloc,     reinterpret_cast<void*>(&SbkDeallocWrapper)},
          {Py_tp_repr,        nullptr},
          {Py_tp_hash,        nullptr},
          {Py_tp_call,        nullptr}, // <- this should reference the __call__ implementation
          {Py_tp_str,         nullptr},
          {Py_tp_getattro,    nullptr},
          {Py_tp_setattro,    nullptr},
          {Py_tp_traverse,    reinterpret_cast<void*>(Sbk_bje_model_ChannelConfigurationFunctor_traverse)},
          {Py_tp_clear,       reinterpret_cast<void*>(Sbk_bje_model_ChannelConfigurationFunctor_clear)},
          {Py_tp_richcompare, nullptr},
          {Py_tp_iter,        nullptr},
          {Py_tp_iternext,    nullptr},
          {Py_tp_methods,     reinterpret_cast<void*>(Sbk_bje_model_ChannelConfigurationFunctor_methods)},
          {Py_tp_getset,      nullptr},
          {Py_tp_init,        reinterpret_cast<void*>(Sbk_bje_model_ChannelConfigurationFunctor_Init)},
          {Py_tp_new,         reinterpret_cast<void*>(SbkObjectTpNew)},
          {0, nullptr}


        1. pyside995_log.txt
          0.3 kB
        2. pyside995_repr.diff
          2 kB
        For Gerrit Dashboard: PYSIDE-995
        # Subject Branch Project Status CR V



            • Assignee:
              kleint Friedemann Kleint
              snkauoe Sebastian Kaupe
            • Votes:
              0 Vote for this issue
              2 Start watching this issue


              • Created:

                Gerrit Reviews

                There are no open Gerrit changes