Details
Description
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"/> </add-function> </object-type>
// @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.
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:
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:
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 |
258920,3 | shiboken: Pass around struct AddedFunction by QSharedPointer | 5.12 | pyside/pyside-setup | Status: MERGED | +2 | 0 |
258921,4 | shiboken: Fix code injection not working for operator functions | 5.12 | pyside/pyside-setup | Status: MERGED | +2 | 0 |
259034,2 | shiboken: Enable adding call operators | 5.12 | pyside/pyside-setup | Status: MERGED | +2 | 0 |