##// END OF EJS Templates
added support for return by value of classes that are NOT registered with QMetaType but which have a default constructor decorator...
florianlink -
r46:1db88b846b4a
parent child
Show More
@@ -1,498 +1,515
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
4 *
4 *
5 * This library is free software; you can redistribute it and/or
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
8 * version 2.1 of the License, or (at your option) any later version.
9 *
9 *
10 * This library is distributed in the hope that it will be useful,
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
13 * Lesser General Public License for more details.
14 *
14 *
15 * Further, this software is distributed without any warranty that it is
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
20 * other software, or any other product whatsoever.
21 *
21 *
22 * You should have received a copy of the GNU Lesser General Public
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
25 *
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file PythonQtSlot.cpp
35 // \file PythonQtSlot.cpp
36 // \author Florian Link
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
37 // \author Last changed by $Author: florian $
38 // \date 2006-05
38 // \date 2006-05
39 */
39 */
40 //----------------------------------------------------------------------------------
40 //----------------------------------------------------------------------------------
41
41
42 #include "PythonQt.h"
42 #include "PythonQt.h"
43 #include "PythonQtSlot.h"
43 #include "PythonQtSlot.h"
44 #include "PythonQtInstanceWrapper.h"
44 #include "PythonQtInstanceWrapper.h"
45 #include "PythonQtClassInfo.h"
45 #include "PythonQtClassInfo.h"
46 #include "PythonQtMisc.h"
46 #include "PythonQtMisc.h"
47 #include "PythonQtConversion.h"
47 #include "PythonQtConversion.h"
48 #include <iostream>
48 #include <iostream>
49
49
50 #define PYTHONQT_MAX_ARGS 32
50 #define PYTHONQT_MAX_ARGS 32
51
51
52
52
53 bool PythonQtCallSlot(PythonQtClassInfo* classInfo, QObject* objectToCall, PyObject* args, bool strict, PythonQtSlotInfo* info, void* firstArgument, PyObject** pythonReturnValue, void** directReturnValuePointer)
53 bool PythonQtCallSlot(PythonQtClassInfo* classInfo, QObject* objectToCall, PyObject* args, bool strict, PythonQtSlotInfo* info, void* firstArgument, PyObject** pythonReturnValue, void** directReturnValuePointer)
54 {
54 {
55 static unsigned int recursiveEntry = 0;
55 static unsigned int recursiveEntry = 0;
56
56
57 if (directReturnValuePointer) {
57 if (directReturnValuePointer) {
58 *directReturnValuePointer = NULL;
58 *directReturnValuePointer = NULL;
59 }
59 }
60 // store the current storage position, so that we can get back to this state after a slot is called
60 // store the current storage position, so that we can get back to this state after a slot is called
61 // (do this locally, so that we have all positions on the stack
61 // (do this locally, so that we have all positions on the stack
62 PythonQtValueStoragePosition globalValueStoragePos;
62 PythonQtValueStoragePosition globalValueStoragePos;
63 PythonQtValueStoragePosition globalPtrStoragePos;
63 PythonQtValueStoragePosition globalPtrStoragePos;
64 PythonQtValueStoragePosition globalVariantStoragePos;
64 PythonQtValueStoragePosition globalVariantStoragePos;
65 PythonQtConv::global_valueStorage.getPos(globalValueStoragePos);
65 PythonQtConv::global_valueStorage.getPos(globalValueStoragePos);
66 PythonQtConv::global_ptrStorage.getPos(globalPtrStoragePos);
66 PythonQtConv::global_ptrStorage.getPos(globalPtrStoragePos);
67 PythonQtConv::global_variantStorage.getPos(globalVariantStoragePos);
67 PythonQtConv::global_variantStorage.getPos(globalVariantStoragePos);
68
68
69 recursiveEntry++;
69 recursiveEntry++;
70
70
71 // the arguments that are passed to qt_metacall
71 // the arguments that are passed to qt_metacall
72 void* argList[PYTHONQT_MAX_ARGS];
72 void* argList[PYTHONQT_MAX_ARGS];
73 PyObject* result = NULL;
73 PyObject* result = NULL;
74 int argc = info->parameterCount();
74 int argc = info->parameterCount();
75 const QList<PythonQtSlotInfo::ParameterInfo>& params = info->parameters();
75 const QList<PythonQtSlotInfo::ParameterInfo>& params = info->parameters();
76
76
77 bool returnValueIsEnum = false;
77 bool returnValueIsEnum = false;
78 const PythonQtSlotInfo::ParameterInfo& returnValueParam = params.at(0);
78 const PythonQtSlotInfo::ParameterInfo& returnValueParam = params.at(0);
79 // set return argument to NULL
79 // set return argument to NULL
80 argList[0] = NULL;
80 argList[0] = NULL;
81
81
82 bool ok = true;
82 bool ok = true;
83 bool skipFirst = false;
83 bool skipFirst = false;
84 if (info->isInstanceDecorator()) {
84 if (info->isInstanceDecorator()) {
85 skipFirst = true;
85 skipFirst = true;
86
86
87 // for decorators on CPP objects, we take the cpp ptr, for QObjects we take the QObject pointer
87 // for decorators on CPP objects, we take the cpp ptr, for QObjects we take the QObject pointer
88 void* arg1 = firstArgument;
88 void* arg1 = firstArgument;
89 if (!arg1) {
89 if (!arg1) {
90 arg1 = objectToCall;
90 arg1 = objectToCall;
91 }
91 }
92 if (arg1) {
92 if (arg1) {
93 // upcast to correct parent class
93 // upcast to correct parent class
94 arg1 = ((char*)arg1)+info->upcastingOffset();
94 arg1 = ((char*)arg1)+info->upcastingOffset();
95 }
95 }
96
96
97 argList[1] = &arg1;
97 argList[1] = &arg1;
98 if (ok) {
98 if (ok) {
99 for (int i = 2; i<argc && ok; i++) {
99 for (int i = 2; i<argc && ok; i++) {
100 const PythonQtSlotInfo::ParameterInfo& param = params.at(i);
100 const PythonQtSlotInfo::ParameterInfo& param = params.at(i);
101 //std::cout << param.name.data() << " " << param.typeId << (param.isPointer?"*":"") << (param.isConst?" const":"") << std::endl;
101 //std::cout << param.name.data() << " " << param.typeId << (param.isPointer?"*":"") << (param.isConst?" const":"") << std::endl;
102 argList[i] = PythonQtConv::ConvertPythonToQt(param, PyTuple_GET_ITEM(args, i-2), strict, classInfo);
102 argList[i] = PythonQtConv::ConvertPythonToQt(param, PyTuple_GET_ITEM(args, i-2), strict, classInfo);
103 if (argList[i]==NULL) {
103 if (argList[i]==NULL) {
104 ok = false;
104 ok = false;
105 break;
105 break;
106 }
106 }
107 }
107 }
108 }
108 }
109 } else {
109 } else {
110 for (int i = 1; i<argc && ok; i++) {
110 for (int i = 1; i<argc && ok; i++) {
111 const PythonQtSlotInfo::ParameterInfo& param = params.at(i);
111 const PythonQtSlotInfo::ParameterInfo& param = params.at(i);
112 //std::cout << param.name.data() << " " << param.typeId << (param.isPointer?"*":"") << (param.isConst?" const":"") << std::endl;
112 //std::cout << param.name.data() << " " << param.typeId << (param.isPointer?"*":"") << (param.isConst?" const":"") << std::endl;
113 argList[i] = PythonQtConv::ConvertPythonToQt(param, PyTuple_GET_ITEM(args, i-1), strict, classInfo);
113 argList[i] = PythonQtConv::ConvertPythonToQt(param, PyTuple_GET_ITEM(args, i-1), strict, classInfo);
114 if (argList[i]==NULL) {
114 if (argList[i]==NULL) {
115 ok = false;
115 ok = false;
116 break;
116 break;
117 }
117 }
118 }
118 }
119 }
119 }
120
120
121 if (ok) {
121 if (ok) {
122 // parameters are ok, now create the qt return value which is assigned to by metacall
122 // parameters are ok, now create the qt return value which is assigned to by metacall
123 if (returnValueParam.typeId != QMetaType::Void) {
123 if (returnValueParam.typeId != QMetaType::Void) {
124 // extra handling of enum return value
124 // extra handling of enum return value
125 if (!returnValueParam.isPointer && returnValueParam.typeId == PythonQtMethodInfo::Unknown) {
125 if (!returnValueParam.isPointer && returnValueParam.typeId == PythonQtMethodInfo::Unknown) {
126 returnValueIsEnum = PythonQtClassInfo::hasEnum(returnValueParam.name, classInfo);
126 returnValueIsEnum = PythonQtClassInfo::hasEnum(returnValueParam.name, classInfo);
127 if (returnValueIsEnum) {
127 if (returnValueIsEnum) {
128 // create enum return value
128 // create enum return value
129 PythonQtValueStorage_ADD_VALUE(PythonQtConv::global_valueStorage, long, 0, argList[0]);
129 PythonQtValueStorage_ADD_VALUE(PythonQtConv::global_valueStorage, long, 0, argList[0]);
130 }
130 }
131 }
131 }
132 if (argList[0]==NULL) {
132 if (argList[0]==NULL) {
133 // create empty default value for the return value
133 // create empty default value for the return value
134 if (!directReturnValuePointer) {
134 if (!directReturnValuePointer) {
135 // create empty default value for the return value
135 // create empty default value for the return value
136 argList[0] = PythonQtConv::CreateQtReturnValue(returnValueParam);
136 argList[0] = PythonQtConv::CreateQtReturnValue(returnValueParam);
137 if (argList[0]==NULL) {
138 // return value could not be created, maybe we have a registered class with a default constructor, so that we can construct the pythonqt wrapper object and
139 // pass its internal pointer
140 PythonQtClassInfo* info = PythonQt::priv()->getClassInfo(returnValueParam.name);
141 if (info && info->pythonQtClassWrapper()) {
142 PyObject* emptyTuple = PyTuple_New(0);
143 // 1) default construct an empty object as python object (owned by PythonQt), by calling the meta class with empty arguments
144 result = PyObject_Call((PyObject*)info->pythonQtClassWrapper(), emptyTuple, NULL);
145 if (result) {
146 argList[0] = ((PythonQtInstanceWrapper*)result)->_wrappedPtr;
147 }
148 Py_DECREF(emptyTuple);
149 }
150 }
137 } else {
151 } else {
138 // we can use our pointer directly!
152 // we can use our pointer directly!
139 argList[0] = directReturnValuePointer;
153 argList[0] = directReturnValuePointer;
140 }
154 }
141 }
155 }
142 }
156 }
143
157
144 // invoke the slot via metacall
158 // invoke the slot via metacall
145 (info->decorator()?info->decorator():objectToCall)->qt_metacall(QMetaObject::InvokeMetaMethod, info->slotIndex(), argList);
159 (info->decorator()?info->decorator():objectToCall)->qt_metacall(QMetaObject::InvokeMetaMethod, info->slotIndex(), argList);
146
160
147 // handle the return value (which in most cases still needs to be converted to a Python object)
161 // handle the return value (which in most cases still needs to be converted to a Python object)
148 if (argList[0] || returnValueParam.typeId == QMetaType::Void) {
162 if (argList[0] || returnValueParam.typeId == QMetaType::Void) {
149 if (directReturnValuePointer) {
163 if (directReturnValuePointer) {
150 result = NULL;
164 result = NULL;
151 } else {
165 } else {
152 if (!returnValueIsEnum) {
166 if (!returnValueIsEnum) {
167 // the resulting object maybe present already, because we created it above at 1)...
168 if (!result) {
153 result = PythonQtConv::ConvertQtValueToPython(returnValueParam, argList[0]);
169 result = PythonQtConv::ConvertQtValueToPython(returnValueParam, argList[0]);
170 }
154 } else {
171 } else {
155 result = PyInt_FromLong(*((unsigned int*)argList[0]));
172 result = PyInt_FromLong(*((unsigned int*)argList[0]));
156 }
173 }
157 }
174 }
158 } else {
175 } else {
159 QString e = QString("Called ") + info->fullSignature() + ", return type '" + returnValueParam.name + "' is ignored because it is unknown to PythonQt. Probaby you should register it using qRegisterMetaType().";
176 QString e = QString("Called ") + info->fullSignature() + ", return type '" + returnValueParam.name + "' is ignored because it is unknown to PythonQt. Probably you should register it using qRegisterMetaType() or add a default constructor decorator to the class.";
160 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
177 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
161 result = NULL;
178 result = NULL;
162 }
179 }
163 }
180 }
164 recursiveEntry--;
181 recursiveEntry--;
165
182
166 // reset the parameter storage position to the stored pos to "pop" the parameter stack
183 // reset the parameter storage position to the stored pos to "pop" the parameter stack
167 PythonQtConv::global_valueStorage.setPos(globalValueStoragePos);
184 PythonQtConv::global_valueStorage.setPos(globalValueStoragePos);
168 PythonQtConv::global_ptrStorage.setPos(globalPtrStoragePos);
185 PythonQtConv::global_ptrStorage.setPos(globalPtrStoragePos);
169 PythonQtConv::global_variantStorage.setPos(globalVariantStoragePos);
186 PythonQtConv::global_variantStorage.setPos(globalVariantStoragePos);
170
187
171 *pythonReturnValue = result;
188 *pythonReturnValue = result;
172 // NOTE: it is important to only return here, otherwise the stack will not be popped!!!
189 // NOTE: it is important to only return here, otherwise the stack will not be popped!!!
173 return result || (directReturnValuePointer && *directReturnValuePointer);
190 return result || (directReturnValuePointer && *directReturnValuePointer);
174 }
191 }
175
192
176 //-----------------------------------------------------------------------------------
193 //-----------------------------------------------------------------------------------
177
194
178 static PythonQtSlotFunctionObject *pythonqtslot_free_list = NULL;
195 static PythonQtSlotFunctionObject *pythonqtslot_free_list = NULL;
179
196
180 PyObject *PythonQtSlotFunction_Call(PyObject *func, PyObject *args, PyObject *kw)
197 PyObject *PythonQtSlotFunction_Call(PyObject *func, PyObject *args, PyObject *kw)
181 {
198 {
182 PythonQtSlotFunctionObject* f = (PythonQtSlotFunctionObject*)func;
199 PythonQtSlotFunctionObject* f = (PythonQtSlotFunctionObject*)func;
183 PythonQtSlotInfo* info = f->m_ml;
200 PythonQtSlotInfo* info = f->m_ml;
184 if (PyObject_TypeCheck(f->m_self, &PythonQtInstanceWrapper_Type)) {
201 if (PyObject_TypeCheck(f->m_self, &PythonQtInstanceWrapper_Type)) {
185 PythonQtInstanceWrapper* self = (PythonQtInstanceWrapper*) f->m_self;
202 PythonQtInstanceWrapper* self = (PythonQtInstanceWrapper*) f->m_self;
186 return PythonQtSlotFunction_CallImpl(self->classInfo(), self->_obj, info, args, kw, self->_wrappedPtr);
203 return PythonQtSlotFunction_CallImpl(self->classInfo(), self->_obj, info, args, kw, self->_wrappedPtr);
187 } else if (f->m_self->ob_type == &PythonQtClassWrapper_Type) {
204 } else if (f->m_self->ob_type == &PythonQtClassWrapper_Type) {
188 PythonQtClassWrapper* type = (PythonQtClassWrapper*) f->m_self;
205 PythonQtClassWrapper* type = (PythonQtClassWrapper*) f->m_self;
189 if (info->isClassDecorator()) {
206 if (info->isClassDecorator()) {
190 return PythonQtSlotFunction_CallImpl(type->classInfo(), NULL, info, args, kw);
207 return PythonQtSlotFunction_CallImpl(type->classInfo(), NULL, info, args, kw);
191 } else {
208 } else {
192 // otherwise, it is an unbound call and we have an instanceDecorator or normal slot...
209 // otherwise, it is an unbound call and we have an instanceDecorator or normal slot...
193 Py_ssize_t argc = PyTuple_Size(args);
210 Py_ssize_t argc = PyTuple_Size(args);
194 if (argc>0) {
211 if (argc>0) {
195 PyObject* firstArg = PyTuple_GET_ITEM(args, 0);
212 PyObject* firstArg = PyTuple_GET_ITEM(args, 0);
196 if (PyObject_TypeCheck(firstArg, (PyTypeObject*)&PythonQtInstanceWrapper_Type)
213 if (PyObject_TypeCheck(firstArg, (PyTypeObject*)&PythonQtInstanceWrapper_Type)
197 && ((PythonQtInstanceWrapper*)firstArg)->classInfo()->inherits(type->classInfo())) {
214 && ((PythonQtInstanceWrapper*)firstArg)->classInfo()->inherits(type->classInfo())) {
198 PythonQtInstanceWrapper* self = (PythonQtInstanceWrapper*)firstArg;
215 PythonQtInstanceWrapper* self = (PythonQtInstanceWrapper*)firstArg;
199 // strip the first argument...
216 // strip the first argument...
200 PyObject* newargs = PyTuple_GetSlice(args, 1, argc);
217 PyObject* newargs = PyTuple_GetSlice(args, 1, argc);
201 PyObject* result = PythonQtSlotFunction_CallImpl(self->classInfo(), self->_obj, info, newargs, kw, self->_wrappedPtr);
218 PyObject* result = PythonQtSlotFunction_CallImpl(self->classInfo(), self->_obj, info, newargs, kw, self->_wrappedPtr);
202 Py_DECREF(newargs);
219 Py_DECREF(newargs);
203 return result;
220 return result;
204 } else {
221 } else {
205 // first arg is not of correct type!
222 // first arg is not of correct type!
206 QString error = "slot " + info->fullSignature() + " requires " + type->classInfo()->className() + " instance as first argument, got " + firstArg->ob_type->tp_name;
223 QString error = "slot " + info->fullSignature() + " requires " + type->classInfo()->className() + " instance as first argument, got " + firstArg->ob_type->tp_name;
207 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
224 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
208 return NULL;
225 return NULL;
209 }
226 }
210 } else {
227 } else {
211 // wrong number of args
228 // wrong number of args
212 QString error = "slot " + info->fullSignature() + " requires " + type->classInfo()->className() + " instance as first argument.";
229 QString error = "slot " + info->fullSignature() + " requires " + type->classInfo()->className() + " instance as first argument.";
213 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
230 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
214 return NULL;
231 return NULL;
215 }
232 }
216 }
233 }
217 }
234 }
218 return NULL;
235 return NULL;
219 }
236 }
220
237
221 PyObject *PythonQtSlotFunction_CallImpl(PythonQtClassInfo* classInfo, QObject* objectToCall, PythonQtSlotInfo* info, PyObject *args, PyObject * /*kw*/, void* firstArg, void** directReturnValuePointer)
238 PyObject *PythonQtSlotFunction_CallImpl(PythonQtClassInfo* classInfo, QObject* objectToCall, PythonQtSlotInfo* info, PyObject *args, PyObject * /*kw*/, void* firstArg, void** directReturnValuePointer)
222 {
239 {
223 int argc = PyTuple_Size(args);
240 int argc = PyTuple_Size(args);
224
241
225 #ifdef PYTHONQT_DEBUG
242 #ifdef PYTHONQT_DEBUG
226 std::cout << "called " << info->metaMethod()->typeName() << " " << info->metaMethod()->signature() << std::endl;
243 std::cout << "called " << info->metaMethod()->typeName() << " " << info->metaMethod()->signature() << std::endl;
227 #endif
244 #endif
228
245
229 PyObject* r = NULL;
246 PyObject* r = NULL;
230 bool ok = false;
247 bool ok = false;
231 if (directReturnValuePointer) {
248 if (directReturnValuePointer) {
232 *directReturnValuePointer = NULL;
249 *directReturnValuePointer = NULL;
233 }
250 }
234 if (info->nextInfo()) {
251 if (info->nextInfo()) {
235 // overloaded slot call, try on all slots with strict conversion first
252 // overloaded slot call, try on all slots with strict conversion first
236 bool strict = true;
253 bool strict = true;
237 PythonQtSlotInfo* i = info;
254 PythonQtSlotInfo* i = info;
238 while (i) {
255 while (i) {
239 bool skipFirst = i->isInstanceDecorator();
256 bool skipFirst = i->isInstanceDecorator();
240 if (i->parameterCount()-1-(skipFirst?1:0) == argc) {
257 if (i->parameterCount()-1-(skipFirst?1:0) == argc) {
241 PyErr_Clear();
258 PyErr_Clear();
242 ok = PythonQtCallSlot(classInfo, objectToCall, args, strict, i, firstArg, &r, directReturnValuePointer);
259 ok = PythonQtCallSlot(classInfo, objectToCall, args, strict, i, firstArg, &r, directReturnValuePointer);
243 if (PyErr_Occurred() || ok) break;
260 if (PyErr_Occurred() || ok) break;
244 }
261 }
245 i = i->nextInfo();
262 i = i->nextInfo();
246 if (!i) {
263 if (!i) {
247 if (strict) {
264 if (strict) {
248 // one more run without being strict
265 // one more run without being strict
249 strict = false;
266 strict = false;
250 i = info;
267 i = info;
251 }
268 }
252 }
269 }
253 }
270 }
254 if (!ok && !PyErr_Occurred()) {
271 if (!ok && !PyErr_Occurred()) {
255 QString e = QString("Could not find matching overload for given arguments:\n" + PythonQtConv::PyObjGetString(args) + "\n The following slots are available:\n");
272 QString e = QString("Could not find matching overload for given arguments:\n" + PythonQtConv::PyObjGetString(args) + "\n The following slots are available:\n");
256 PythonQtSlotInfo* i = info;
273 PythonQtSlotInfo* i = info;
257 while (i) {
274 while (i) {
258 e += QString(i->fullSignature()) + "\n";
275 e += QString(i->fullSignature()) + "\n";
259 i = i->nextInfo();
276 i = i->nextInfo();
260 }
277 }
261 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
278 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
262 }
279 }
263 } else {
280 } else {
264 // simple (non-overloaded) slot call
281 // simple (non-overloaded) slot call
265 bool skipFirst = info->isInstanceDecorator();
282 bool skipFirst = info->isInstanceDecorator();
266 if (info->parameterCount()-1-(skipFirst?1:0) == argc) {
283 if (info->parameterCount()-1-(skipFirst?1:0) == argc) {
267 PyErr_Clear();
284 PyErr_Clear();
268 ok = PythonQtCallSlot(classInfo, objectToCall, args, false, info, firstArg, &r, directReturnValuePointer);
285 ok = PythonQtCallSlot(classInfo, objectToCall, args, false, info, firstArg, &r, directReturnValuePointer);
269 if (!ok && !PyErr_Occurred()) {
286 if (!ok && !PyErr_Occurred()) {
270 QString e = QString("Called ") + info->fullSignature() + " with wrong arguments: " + PythonQtConv::PyObjGetString(args);
287 QString e = QString("Called ") + info->fullSignature() + " with wrong arguments: " + PythonQtConv::PyObjGetString(args);
271 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
288 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
272 }
289 }
273 } else {
290 } else {
274 QString e = QString("Called ") + info->fullSignature() + " with wrong number of arguments: " + PythonQtConv::PyObjGetString(args);
291 QString e = QString("Called ") + info->fullSignature() + " with wrong number of arguments: " + PythonQtConv::PyObjGetString(args);
275 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
292 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
276 }
293 }
277 }
294 }
278
295
279 return r;
296 return r;
280 }
297 }
281
298
282 PyObject *
299 PyObject *
283 PythonQtSlotFunction_New(PythonQtSlotInfo *ml, PyObject *self, PyObject *module)
300 PythonQtSlotFunction_New(PythonQtSlotInfo *ml, PyObject *self, PyObject *module)
284 {
301 {
285 PythonQtSlotFunctionObject *op;
302 PythonQtSlotFunctionObject *op;
286 op = pythonqtslot_free_list;
303 op = pythonqtslot_free_list;
287 if (op != NULL) {
304 if (op != NULL) {
288 pythonqtslot_free_list = (PythonQtSlotFunctionObject *)(op->m_self);
305 pythonqtslot_free_list = (PythonQtSlotFunctionObject *)(op->m_self);
289 PyObject_INIT(op, &PythonQtSlotFunction_Type);
306 PyObject_INIT(op, &PythonQtSlotFunction_Type);
290 }
307 }
291 else {
308 else {
292 op = PyObject_GC_New(PythonQtSlotFunctionObject, &PythonQtSlotFunction_Type);
309 op = PyObject_GC_New(PythonQtSlotFunctionObject, &PythonQtSlotFunction_Type);
293 if (op == NULL)
310 if (op == NULL)
294 return NULL;
311 return NULL;
295 }
312 }
296 op->m_ml = ml;
313 op->m_ml = ml;
297 Py_XINCREF(self);
314 Py_XINCREF(self);
298 op->m_self = self;
315 op->m_self = self;
299 Py_XINCREF(module);
316 Py_XINCREF(module);
300 op->m_module = module;
317 op->m_module = module;
301 PyObject_GC_Track(op);
318 PyObject_GC_Track(op);
302 return (PyObject *)op;
319 return (PyObject *)op;
303 }
320 }
304
321
305 PythonQtSlotInfo*
322 PythonQtSlotInfo*
306 PythonQtSlotFunction_GetSlotInfo(PyObject *op)
323 PythonQtSlotFunction_GetSlotInfo(PyObject *op)
307 {
324 {
308 if (!PythonQtSlotFunction_Check(op)) {
325 if (!PythonQtSlotFunction_Check(op)) {
309 PyErr_BadInternalCall();
326 PyErr_BadInternalCall();
310 return NULL;
327 return NULL;
311 }
328 }
312 return ((PythonQtSlotFunctionObject *)op) -> m_ml;
329 return ((PythonQtSlotFunctionObject *)op) -> m_ml;
313 }
330 }
314
331
315 PyObject *
332 PyObject *
316 PythonQtSlotFunction_GetSelf(PyObject *op)
333 PythonQtSlotFunction_GetSelf(PyObject *op)
317 {
334 {
318 if (!PythonQtSlotFunction_Check(op)) {
335 if (!PythonQtSlotFunction_Check(op)) {
319 PyErr_BadInternalCall();
336 PyErr_BadInternalCall();
320 return NULL;
337 return NULL;
321 }
338 }
322 return ((PythonQtSlotFunctionObject *)op) -> m_self;
339 return ((PythonQtSlotFunctionObject *)op) -> m_self;
323 }
340 }
324
341
325 /* Methods (the standard built-in methods, that is) */
342 /* Methods (the standard built-in methods, that is) */
326
343
327 static void
344 static void
328 meth_dealloc(PythonQtSlotFunctionObject *m)
345 meth_dealloc(PythonQtSlotFunctionObject *m)
329 {
346 {
330 PyObject_GC_UnTrack(m);
347 PyObject_GC_UnTrack(m);
331 Py_XDECREF(m->m_self);
348 Py_XDECREF(m->m_self);
332 Py_XDECREF(m->m_module);
349 Py_XDECREF(m->m_module);
333 m->m_self = (PyObject *)pythonqtslot_free_list;
350 m->m_self = (PyObject *)pythonqtslot_free_list;
334 pythonqtslot_free_list = m;
351 pythonqtslot_free_list = m;
335 }
352 }
336
353
337 static PyObject *
354 static PyObject *
338 meth_get__doc__(PythonQtSlotFunctionObject * /*m*/, void * /*closure*/)
355 meth_get__doc__(PythonQtSlotFunctionObject * /*m*/, void * /*closure*/)
339 {
356 {
340 Py_INCREF(Py_None);
357 Py_INCREF(Py_None);
341 return Py_None;
358 return Py_None;
342 }
359 }
343
360
344 static PyObject *
361 static PyObject *
345 meth_get__name__(PythonQtSlotFunctionObject *m, void * /*closure*/)
362 meth_get__name__(PythonQtSlotFunctionObject *m, void * /*closure*/)
346 {
363 {
347 return PyString_FromString(m->m_ml->metaMethod()->signature());
364 return PyString_FromString(m->m_ml->metaMethod()->signature());
348 }
365 }
349
366
350 static int
367 static int
351 meth_traverse(PythonQtSlotFunctionObject *m, visitproc visit, void *arg)
368 meth_traverse(PythonQtSlotFunctionObject *m, visitproc visit, void *arg)
352 {
369 {
353 int err;
370 int err;
354 if (m->m_self != NULL) {
371 if (m->m_self != NULL) {
355 err = visit(m->m_self, arg);
372 err = visit(m->m_self, arg);
356 if (err)
373 if (err)
357 return err;
374 return err;
358 }
375 }
359 if (m->m_module != NULL) {
376 if (m->m_module != NULL) {
360 err = visit(m->m_module, arg);
377 err = visit(m->m_module, arg);
361 if (err)
378 if (err)
362 return err;
379 return err;
363 }
380 }
364 return 0;
381 return 0;
365 }
382 }
366
383
367 static PyObject *
384 static PyObject *
368 meth_get__self__(PythonQtSlotFunctionObject *m, void * /*closure*/)
385 meth_get__self__(PythonQtSlotFunctionObject *m, void * /*closure*/)
369 {
386 {
370 PyObject *self;
387 PyObject *self;
371 if (PyEval_GetRestricted()) {
388 if (PyEval_GetRestricted()) {
372 PyErr_SetString(PyExc_RuntimeError,
389 PyErr_SetString(PyExc_RuntimeError,
373 "method.__self__ not accessible in restricted mode");
390 "method.__self__ not accessible in restricted mode");
374 return NULL;
391 return NULL;
375 }
392 }
376 self = m->m_self;
393 self = m->m_self;
377 if (self == NULL)
394 if (self == NULL)
378 self = Py_None;
395 self = Py_None;
379 Py_INCREF(self);
396 Py_INCREF(self);
380 return self;
397 return self;
381 }
398 }
382
399
383 static PyGetSetDef meth_getsets [] = {
400 static PyGetSetDef meth_getsets [] = {
384 {"__doc__", (getter)meth_get__doc__, NULL, NULL},
401 {"__doc__", (getter)meth_get__doc__, NULL, NULL},
385 {"__name__", (getter)meth_get__name__, NULL, NULL},
402 {"__name__", (getter)meth_get__name__, NULL, NULL},
386 {"__self__", (getter)meth_get__self__, NULL, NULL},
403 {"__self__", (getter)meth_get__self__, NULL, NULL},
387 {NULL, NULL, NULL,NULL},
404 {NULL, NULL, NULL,NULL},
388 };
405 };
389
406
390 #if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 6
407 #if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 6
391 #define PY_WRITE_RESTRICTED WRITE_RESTRICTED
408 #define PY_WRITE_RESTRICTED WRITE_RESTRICTED
392 #endif
409 #endif
393
410
394 #define OFF(x) offsetof(PythonQtSlotFunctionObject, x)
411 #define OFF(x) offsetof(PythonQtSlotFunctionObject, x)
395
412
396 static PyMemberDef meth_members[] = {
413 static PyMemberDef meth_members[] = {
397 {"__module__", T_OBJECT, OFF(m_module), PY_WRITE_RESTRICTED},
414 {"__module__", T_OBJECT, OFF(m_module), PY_WRITE_RESTRICTED},
398 {NULL}
415 {NULL}
399 };
416 };
400
417
401 static PyObject *
418 static PyObject *
402 meth_repr(PythonQtSlotFunctionObject *f)
419 meth_repr(PythonQtSlotFunctionObject *f)
403 {
420 {
404 if (f->m_self->ob_type == &PythonQtClassWrapper_Type) {
421 if (f->m_self->ob_type == &PythonQtClassWrapper_Type) {
405 PythonQtClassWrapper* self = (PythonQtClassWrapper*) f->m_self;
422 PythonQtClassWrapper* self = (PythonQtClassWrapper*) f->m_self;
406 return PyString_FromFormat("<unbound qt slot %s of %s type>",
423 return PyString_FromFormat("<unbound qt slot %s of %s type>",
407 f->m_ml->slotName().data(),
424 f->m_ml->slotName().data(),
408 self->classInfo()->className());
425 self->classInfo()->className());
409 } else {
426 } else {
410 return PyString_FromFormat("<qt slot %s of %s instance at %p>",
427 return PyString_FromFormat("<qt slot %s of %s instance at %p>",
411 f->m_ml->slotName().data(),
428 f->m_ml->slotName().data(),
412 f->m_self->ob_type->tp_name,
429 f->m_self->ob_type->tp_name,
413 f->m_self);
430 f->m_self);
414 }
431 }
415 }
432 }
416
433
417 static int
434 static int
418 meth_compare(PythonQtSlotFunctionObject *a, PythonQtSlotFunctionObject *b)
435 meth_compare(PythonQtSlotFunctionObject *a, PythonQtSlotFunctionObject *b)
419 {
436 {
420 if (a->m_self != b->m_self)
437 if (a->m_self != b->m_self)
421 return (a->m_self < b->m_self) ? -1 : 1;
438 return (a->m_self < b->m_self) ? -1 : 1;
422 if (a->m_ml == b->m_ml)
439 if (a->m_ml == b->m_ml)
423 return 0;
440 return 0;
424 if (strcmp(a->m_ml->metaMethod()->signature(), b->m_ml->metaMethod()->signature()) < 0)
441 if (strcmp(a->m_ml->metaMethod()->signature(), b->m_ml->metaMethod()->signature()) < 0)
425 return -1;
442 return -1;
426 else
443 else
427 return 1;
444 return 1;
428 }
445 }
429
446
430 static long
447 static long
431 meth_hash(PythonQtSlotFunctionObject *a)
448 meth_hash(PythonQtSlotFunctionObject *a)
432 {
449 {
433 long x,y;
450 long x,y;
434 if (a->m_self == NULL)
451 if (a->m_self == NULL)
435 x = 0;
452 x = 0;
436 else {
453 else {
437 x = PyObject_Hash(a->m_self);
454 x = PyObject_Hash(a->m_self);
438 if (x == -1)
455 if (x == -1)
439 return -1;
456 return -1;
440 }
457 }
441 y = _Py_HashPointer((void*)(a->m_ml));
458 y = _Py_HashPointer((void*)(a->m_ml));
442 if (y == -1)
459 if (y == -1)
443 return -1;
460 return -1;
444 x ^= y;
461 x ^= y;
445 if (x == -1)
462 if (x == -1)
446 x = -2;
463 x = -2;
447 return x;
464 return x;
448 }
465 }
449
466
450
467
451 PyTypeObject PythonQtSlotFunction_Type = {
468 PyTypeObject PythonQtSlotFunction_Type = {
452 PyObject_HEAD_INIT(&PyType_Type)
469 PyObject_HEAD_INIT(&PyType_Type)
453 0,
470 0,
454 "builtin_qt_slot",
471 "builtin_qt_slot",
455 sizeof(PythonQtSlotFunctionObject),
472 sizeof(PythonQtSlotFunctionObject),
456 0,
473 0,
457 (destructor)meth_dealloc, /* tp_dealloc */
474 (destructor)meth_dealloc, /* tp_dealloc */
458 0, /* tp_print */
475 0, /* tp_print */
459 0, /* tp_getattr */
476 0, /* tp_getattr */
460 0, /* tp_setattr */
477 0, /* tp_setattr */
461 (cmpfunc)meth_compare, /* tp_compare */
478 (cmpfunc)meth_compare, /* tp_compare */
462 (reprfunc)meth_repr, /* tp_repr */
479 (reprfunc)meth_repr, /* tp_repr */
463 0, /* tp_as_number */
480 0, /* tp_as_number */
464 0, /* tp_as_sequence */
481 0, /* tp_as_sequence */
465 0, /* tp_as_mapping */
482 0, /* tp_as_mapping */
466 (hashfunc)meth_hash, /* tp_hash */
483 (hashfunc)meth_hash, /* tp_hash */
467 PythonQtSlotFunction_Call, /* tp_call */
484 PythonQtSlotFunction_Call, /* tp_call */
468 0, /* tp_str */
485 0, /* tp_str */
469 PyObject_GenericGetAttr, /* tp_getattro */
486 PyObject_GenericGetAttr, /* tp_getattro */
470 0, /* tp_setattro */
487 0, /* tp_setattro */
471 0, /* tp_as_buffer */
488 0, /* tp_as_buffer */
472 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
489 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
473 0, /* tp_doc */
490 0, /* tp_doc */
474 (traverseproc)meth_traverse, /* tp_traverse */
491 (traverseproc)meth_traverse, /* tp_traverse */
475 0, /* tp_clear */
492 0, /* tp_clear */
476 0, /* tp_richcompare */
493 0, /* tp_richcompare */
477 0, /* tp_weaklistoffset */
494 0, /* tp_weaklistoffset */
478 0, /* tp_iter */
495 0, /* tp_iter */
479 0, /* tp_iternext */
496 0, /* tp_iternext */
480 0, /* tp_methods */
497 0, /* tp_methods */
481 meth_members, /* tp_members */
498 meth_members, /* tp_members */
482 meth_getsets, /* tp_getset */
499 meth_getsets, /* tp_getset */
483 0, /* tp_base */
500 0, /* tp_base */
484 0, /* tp_dict */
501 0, /* tp_dict */
485 };
502 };
486
503
487 /* Clear out the free list */
504 /* Clear out the free list */
488
505
489 void
506 void
490 PythonQtSlotFunction_Fini(void)
507 PythonQtSlotFunction_Fini(void)
491 {
508 {
492 while (pythonqtslot_free_list) {
509 while (pythonqtslot_free_list) {
493 PythonQtSlotFunctionObject *v = pythonqtslot_free_list;
510 PythonQtSlotFunctionObject *v = pythonqtslot_free_list;
494 pythonqtslot_free_list = (PythonQtSlotFunctionObject *)(v->m_self);
511 pythonqtslot_free_list = (PythonQtSlotFunctionObject *)(v->m_self);
495 PyObject_GC_Del(v);
512 PyObject_GC_Del(v);
496 }
513 }
497 }
514 }
498
515
General Comments 0
You need to be logged in to leave comments. Login now