aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHugo Parente Lima <hugo.pl@gmail.com>2011-10-26 18:28:51 -0200
committerHugo Parente Lima <hugo.pl@gmail.com>2012-03-08 16:56:15 -0300
commit15ceed791f8dda4aa1256e67c11f8a748ce4b7b0 (patch)
treeb71a2c970c244e586de94ddfcb6f5e35e12d27ee
parentf55d088d4449f0a4b77ab428442a344790fbecd2 (diff)
Fix bug 1016 - "Calling of Q_INVOKABLE method returning not QVariant is impossible..."
-rw-r--r--libpyside/pysidemetafunction.cpp72
-rw-r--r--tests/pysidetest/CMakeLists.txt3
-rw-r--r--tests/pysidetest/bug_1016.py12
-rw-r--r--tests/pysidetest/hiddenobject.cpp38
-rw-r--r--tests/pysidetest/hiddenobject.h49
-rw-r--r--tests/pysidetest/pysidetest_global.h5
-rw-r--r--tests/pysidetest/typesystem_pysidetest.xml2
7 files changed, 163 insertions, 18 deletions
diff --git a/libpyside/pysidemetafunction.cpp b/libpyside/pysidemetafunction.cpp
index 9338f8eda..de4d3244a 100644
--- a/libpyside/pysidemetafunction.cpp
+++ b/libpyside/pysidemetafunction.cpp
@@ -97,31 +97,69 @@ void functionFree(void *self)
PyObject* functionCall(PyObject* self, PyObject* args, PyObject* kw)
{
- static Shiboken::TypeResolver* typeResolver = Shiboken::TypeResolver::get("QVariant");
- Q_ASSERT(typeResolver);
-
- QGenericArgument gArgs[10];
- QVariant vArgs[10];
PySideMetaFunction* function = reinterpret_cast<PySideMetaFunction*>(self);
QMetaMethod method = function->d->method;
- int argsGiven = method.parameterTypes().size();
+ QList<QByteArray> argTypes = method.parameterTypes();
+
+ // args given plus return type
+ int numArgs = PyTuple_GET_SIZE(args) + 1;
+
+ if (numArgs - 1 != argTypes.count()) {
+ PyErr_Format(PyExc_TypeError, "%s only accepts %d arguments, %d given!", method.signature(), argTypes.count(), numArgs);
+ return 0;
+ }
- for (int i = 0; i < argsGiven; ++i) {
- Shiboken::AutoDecRef pyArg(PySequence_GetItem(args, i));
- gArgs[i] = Q_ARG(QVariant, vArgs[i]);
- void* v[1] = { &vArgs[i] };
- typeResolver->toCpp(pyArg, v);
+ QVariant* methValues = new QVariant[numArgs];
+ void** methArgs = new void*[numArgs];
+
+ // Prepare room for return type
+ const char* returnType = method.typeName();
+ if (returnType)
+ argTypes.prepend(returnType);
+ else
+ argTypes.prepend(QByteArray());
+
+ int i;
+ for (i = 0; i < numArgs; ++i) {
+ const QByteArray& typeName = argTypes[i];
+ // This must happen only when the method hasn't return type.
+ if (typeName.isEmpty()) {
+ methArgs[i] = 0;
+ continue;
+ }
+
+ Shiboken::TypeResolver* typeResolver = Shiboken::TypeResolver::get(typeName);
+ if (typeResolver) {
+ if (Shiboken::TypeResolver::getType(typeName) == Shiboken::TypeResolver::ValueType) {
+ int typeId = QMetaType::type(typeName);
+ if (!typeId) {
+ PyErr_Format(PyExc_TypeError, "Value type used on signal needs to be registered on meta type: %s", typeName.data());
+ break;
+ }
+ methValues[i] = QVariant(typeId, (void*) 0);
+ }
+ methArgs[i] = methValues[i].data();
+ if (i != 0) // Don't do this for return type
+ typeResolver->toCpp(PyTuple_GET_ITEM(args, i - 1), &methArgs[i]);
+ } else {
+ PyErr_Format(PyExc_TypeError, "Unknown type used to emit a signal: %s", argTypes[i].constData());
+ break;
+ }
}
- QVariant retVariant;
- QGenericReturnArgument returnValue = Q_RETURN_ARG(QVariant, retVariant);
- method.invoke(function->d->qobject, returnValue, gArgs[0], gArgs[1], gArgs[2], gArgs[3], gArgs[4], gArgs[5], gArgs[6], gArgs[7], gArgs[8], gArgs[9]);
+ bool ok = i == numArgs;
+ if (ok)
+ QMetaObject::metacall(function->d->qobject, QMetaObject::InvokeMetaMethod, method.methodIndex(), methArgs);
+
+ static Shiboken::TypeResolver* qVariantTypeResolver = Shiboken::TypeResolver::get("QVariant");
+ Q_ASSERT(qVariantTypeResolver);
+ PyObject* retVal = qVariantTypeResolver->toPython(&methValues[0]);
- if (retVariant.isValid())
- return typeResolver->toPython(&retVariant);
+ delete[] methArgs;
+ delete[] methValues;
- Py_RETURN_NONE;
+ return retVal;
}
} // extern "C"
diff --git a/tests/pysidetest/CMakeLists.txt b/tests/pysidetest/CMakeLists.txt
index 807463dc9..7661da875 100644
--- a/tests/pysidetest/CMakeLists.txt
+++ b/tests/pysidetest/CMakeLists.txt
@@ -12,11 +12,13 @@ add_definitions(-DRXX_ALLOCATOR_INIT_0)
set(pysidetest_SRC
testobject.cpp
testview.cpp
+hiddenobject.cpp
)
set(pysidetest_MOC_HEADERS
testobject.h
testview.h
+hiddenobject.h
)
qt4_wrap_cpp(pysidetest_MOC_SRC ${pysidetest_MOC_HEADERS})
@@ -86,3 +88,4 @@ PYSIDE_TEST(signalwithdefaultvalue_test.py)
PYSIDE_TEST(signalemissionfrompython_test.py)
PYSIDE_TEST(version_test.py)
PYSIDE_TEST(typedef_signal_test.py)
+PYSIDE_TEST(bug_1016.py)
diff --git a/tests/pysidetest/bug_1016.py b/tests/pysidetest/bug_1016.py
new file mode 100644
index 000000000..38432c62f
--- /dev/null
+++ b/tests/pysidetest/bug_1016.py
@@ -0,0 +1,12 @@
+from testbinding import *
+import unittest
+
+class TestBug1016 (unittest.TestCase):
+
+ def testIt(self):
+ obj = getHiddenObject()
+ self.assertEqual(obj.callMe(), None)
+ self.assertTrue(obj.wasCalled())
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/pysidetest/hiddenobject.cpp b/tests/pysidetest/hiddenobject.cpp
new file mode 100644
index 000000000..00c7bed6e
--- /dev/null
+++ b/tests/pysidetest/hiddenobject.cpp
@@ -0,0 +1,38 @@
+/*
+ * This file is part of the PySide project.
+ *
+ * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "hiddenobject.h"
+
+void HiddenObject::callMe()
+{
+ m_called = true;
+}
+
+bool HiddenObject::wasCalled()
+{
+ return m_called;
+}
+
+QObject* getHiddenObject()
+{
+ return new HiddenObject();
+}
diff --git a/tests/pysidetest/hiddenobject.h b/tests/pysidetest/hiddenobject.h
new file mode 100644
index 000000000..eb02d142d
--- /dev/null
+++ b/tests/pysidetest/hiddenobject.h
@@ -0,0 +1,49 @@
+/*
+ * This file is part of the PySide project.
+ *
+ * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef HIDDENOBJECT_H
+#define HIDDENOBJECT_H
+
+#ifdef pysidetest_EXPORTS
+#define PYSIDE_EXPORTS 1
+#endif
+#include "pysidemacros.h"
+#include <QObject>
+
+// This class shouldn't be exported!
+class HiddenObject : public QObject
+{
+ Q_OBJECT
+public:
+ HiddenObject() : m_called(false) {}
+ Q_INVOKABLE void callMe();
+public slots:
+ bool wasCalled();
+private:
+ bool m_called;
+};
+
+// Return a instance of HiddenObject
+PYSIDE_API QObject* getHiddenObject();
+
+
+#endif
diff --git a/tests/pysidetest/pysidetest_global.h b/tests/pysidetest/pysidetest_global.h
index a7efcf91c..bad6e8e2a 100644
--- a/tests/pysidetest/pysidetest_global.h
+++ b/tests/pysidetest/pysidetest_global.h
@@ -1,3 +1,6 @@
-#include <pyside_global.h>
+// PySide global.h file
+#include "pyside_global.h"
#include "testobject.h"
#include "testview.h"
+#define PYSIDE_API
+#include "hiddenobject.h"
diff --git a/tests/pysidetest/typesystem_pysidetest.xml b/tests/pysidetest/typesystem_pysidetest.xml
index 5077f6b26..fb9b82b6f 100644
--- a/tests/pysidetest/typesystem_pysidetest.xml
+++ b/tests/pysidetest/typesystem_pysidetest.xml
@@ -6,6 +6,8 @@
<primitive-type name="TypedefValue"/>
<object-type name="TestObject" />
+ <function signature="getHiddenObject()" />
+
<inject-code position="end">
Shiboken::TypeResolver::createObjectTypeResolver&lt; ::PySideCPP2::TestObjectWithoutNamespace>("TestObjectWithoutNamespace*");
Shiboken::TypeResolver::createValueTypeResolver&lt; ::PySideCPP2::PySideLong>("PySideLong");