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

Shiboken does not recognize call operator from XML

    XMLWordPrintable

Details

    • Bug
    • Resolution: Done
    • Not Evaluated
    • 5.12.3
    • 5.13.2
    • Shiboken
    • None
    • Qt 5.13.0-beta1
      Fedora 29
    • Linux/X11
    • 5b42f97fdfc0334e7628bbe30149227d0834edcd (pyside/pyside-setup/5.12)

    Description

      I have a simple class, representing a functor:

      header.h
      #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:

      typesystem.xml
      <!-- 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"/>
          </add-function>
      </object-type>
      
      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;
          SBK_UNUSED(cppSelf)
          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{};
          SBK_UNUSED(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);
              SBK_UNUSED(cppArg0)
      
              if (!PyErr_Occurred()) {
                  // operator(QVector<QObject*>)const
              }
          }
      
          if (PyErr_Occurred()) {
              return {};
          }
          Py_RETURN_NONE;
      
          Sbk_bje_model_ChannelConfigurationFunctorFunc_operator_TypeError:
              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}
      };
      

      Attachments

        For Gerrit Dashboard: PYSIDE-995
        # Subject Branch Project Status CR V

        Activity

          People

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

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes