##// END OF EJS Templates
moved return value creation AFTER the successful check of the call parameters, otherwise the return value allocation is done for nothing...
florianlink -
r45:73b37bcd54f9
parent child
Show More
@@ -1,1099 +1,1099
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 PythonQtConversion.cpp
35 // \file PythonQtConversion.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 "PythonQtConversion.h"
42 #include "PythonQtConversion.h"
43 #include "PythonQtVariants.h"
43 #include "PythonQtVariants.h"
44 #include <QDateTime>
44 #include <QDateTime>
45 #include <QTime>
45 #include <QTime>
46 #include <QDate>
46 #include <QDate>
47
47
48 PythonQtValueStorage<qint64, 128> PythonQtConv::global_valueStorage;
48 PythonQtValueStorage<qint64, 128> PythonQtConv::global_valueStorage;
49 PythonQtValueStorage<void*, 128> PythonQtConv::global_ptrStorage;
49 PythonQtValueStorage<void*, 128> PythonQtConv::global_ptrStorage;
50 PythonQtValueStorage<QVariant, 32> PythonQtConv::global_variantStorage;
50 PythonQtValueStorage<QVariant, 32> PythonQtConv::global_variantStorage;
51
51
52 QHash<int, PythonQtConvertMetaTypeToPythonCB*> PythonQtConv::_metaTypeToPythonConverters;
52 QHash<int, PythonQtConvertMetaTypeToPythonCB*> PythonQtConv::_metaTypeToPythonConverters;
53 QHash<int, PythonQtConvertPythonToMetaTypeCB*> PythonQtConv::_pythonToMetaTypeConverters;
53 QHash<int, PythonQtConvertPythonToMetaTypeCB*> PythonQtConv::_pythonToMetaTypeConverters;
54
54
55 PyObject* PythonQtConv::GetPyBool(bool val)
55 PyObject* PythonQtConv::GetPyBool(bool val)
56 {
56 {
57 PyObject* r = val?Py_True:Py_False;
57 PyObject* r = val?Py_True:Py_False;
58 Py_INCREF(r);
58 Py_INCREF(r);
59 return r;
59 return r;
60 }
60 }
61
61
62 PyObject* PythonQtConv::ConvertQtValueToPython(const PythonQtMethodInfo::ParameterInfo& info, const void* data) {
62 PyObject* PythonQtConv::ConvertQtValueToPython(const PythonQtMethodInfo::ParameterInfo& info, const void* data) {
63 if (info.typeId == QMetaType::Void) {
63 if (info.typeId == QMetaType::Void) {
64 Py_INCREF(Py_None);
64 Py_INCREF(Py_None);
65 return Py_None;
65 return Py_None;
66 } else if (info.isPointer && (info.typeId == QMetaType::Char)) {
66 } else if (info.isPointer && (info.typeId == QMetaType::Char)) {
67 // a char ptr will probably be a null terminated string, so we support that:
67 // a char ptr will probably be a null terminated string, so we support that:
68 return PyString_FromString(*((char**)data));
68 return PyString_FromString(*((char**)data));
69 } else if ((info.typeId == PythonQtMethodInfo::Unknown || info.typeId >= QMetaType::User) &&
69 } else if ((info.typeId == PythonQtMethodInfo::Unknown || info.typeId >= QMetaType::User) &&
70 info.name.startsWith("QList<")) {
70 info.name.startsWith("QList<")) {
71 // it is a QList template:
71 // it is a QList template:
72 // (TODO: check what happens if this is a pointer type?!)
72 // (TODO: check what happens if this is a pointer type?!)
73 QByteArray innerType = info.name.mid(6,info.name.length()-7);
73 QByteArray innerType = info.name.mid(6,info.name.length()-7);
74 if (innerType.endsWith("*")) {
74 if (innerType.endsWith("*")) {
75 innerType.truncate(innerType.length()-1);
75 innerType.truncate(innerType.length()-1);
76 return ConvertQListOfPointerTypeToPythonList((QList<void*>*)data, innerType);
76 return ConvertQListOfPointerTypeToPythonList((QList<void*>*)data, innerType);
77 }
77 }
78 }
78 }
79
79
80 if (info.typeId >= QMetaType::User) {
80 if (info.typeId >= QMetaType::User) {
81 // if a converter is registered, we use is:
81 // if a converter is registered, we use is:
82 PythonQtConvertMetaTypeToPythonCB* converter = _metaTypeToPythonConverters.value(info.typeId);
82 PythonQtConvertMetaTypeToPythonCB* converter = _metaTypeToPythonConverters.value(info.typeId);
83 if (converter) {
83 if (converter) {
84 return (*converter)(data, info.typeId);
84 return (*converter)(data, info.typeId);
85 }
85 }
86 }
86 }
87
87
88 // special handling did not match, so we convert the usual way (either pointer or value version):
88 // special handling did not match, so we convert the usual way (either pointer or value version):
89 if (info.isPointer) {
89 if (info.isPointer) {
90 // convert the pointer to a Python Object (we can handle ANY C++ object, in the worst case we just know the type and the pointer)
90 // convert the pointer to a Python Object (we can handle ANY C++ object, in the worst case we just know the type and the pointer)
91 return PythonQt::priv()->wrapPtr(*((void**)data), info.name);
91 return PythonQt::priv()->wrapPtr(*((void**)data), info.name);
92 } else {
92 } else {
93 // handle values that are not yet handled and not pointers
93 // handle values that are not yet handled and not pointers
94 return ConvertQtValueToPythonInternal(info.typeId, data);
94 return ConvertQtValueToPythonInternal(info.typeId, data);
95 }
95 }
96 }
96 }
97
97
98 PyObject* PythonQtConv::ConvertQtValueToPythonInternal(int type, const void* data) {
98 PyObject* PythonQtConv::ConvertQtValueToPythonInternal(int type, const void* data) {
99 switch (type) {
99 switch (type) {
100 case QMetaType::Void:
100 case QMetaType::Void:
101 Py_INCREF(Py_None);
101 Py_INCREF(Py_None);
102 return Py_None;
102 return Py_None;
103 case QMetaType::Char:
103 case QMetaType::Char:
104 return PyInt_FromLong(*((char*)data));
104 return PyInt_FromLong(*((char*)data));
105 case QMetaType::UChar:
105 case QMetaType::UChar:
106 return PyInt_FromLong(*((unsigned char*)data));
106 return PyInt_FromLong(*((unsigned char*)data));
107 case QMetaType::Short:
107 case QMetaType::Short:
108 return PyInt_FromLong(*((short*)data));
108 return PyInt_FromLong(*((short*)data));
109 case QMetaType::UShort:
109 case QMetaType::UShort:
110 return PyInt_FromLong(*((unsigned short*)data));
110 return PyInt_FromLong(*((unsigned short*)data));
111 case QMetaType::Long:
111 case QMetaType::Long:
112 return PyInt_FromLong(*((long*)data));
112 return PyInt_FromLong(*((long*)data));
113 case QMetaType::ULong:
113 case QMetaType::ULong:
114 // does not fit into simple int of python
114 // does not fit into simple int of python
115 return PyLong_FromUnsignedLong(*((unsigned long*)data));
115 return PyLong_FromUnsignedLong(*((unsigned long*)data));
116 case QMetaType::Bool:
116 case QMetaType::Bool:
117 return PythonQtConv::GetPyBool(*((bool*)data));
117 return PythonQtConv::GetPyBool(*((bool*)data));
118 case QMetaType::Int:
118 case QMetaType::Int:
119 return PyInt_FromLong(*((int*)data));
119 return PyInt_FromLong(*((int*)data));
120 case QMetaType::UInt:
120 case QMetaType::UInt:
121 return PyInt_FromLong(*((unsigned int*)data));
121 return PyInt_FromLong(*((unsigned int*)data));
122 case QMetaType::QChar:
122 case QMetaType::QChar:
123 return PyInt_FromLong(*((short*)data));
123 return PyInt_FromLong(*((short*)data));
124 case QMetaType::Float:
124 case QMetaType::Float:
125 return PyFloat_FromDouble(*((float*)data));
125 return PyFloat_FromDouble(*((float*)data));
126 case QMetaType::Double:
126 case QMetaType::Double:
127 return PyFloat_FromDouble(*((double*)data));
127 return PyFloat_FromDouble(*((double*)data));
128 case QMetaType::LongLong:
128 case QMetaType::LongLong:
129 return PyLong_FromLongLong(*((qint64*)data));
129 return PyLong_FromLongLong(*((qint64*)data));
130 case QMetaType::ULongLong:
130 case QMetaType::ULongLong:
131 return PyLong_FromUnsignedLongLong(*((quint64*)data));
131 return PyLong_FromUnsignedLongLong(*((quint64*)data));
132 case QMetaType::QByteArray: {
132 case QMetaType::QByteArray: {
133 QByteArray* v = (QByteArray*) data;
133 QByteArray* v = (QByteArray*) data;
134 return PyString_FromStringAndSize(*v, v->size());
134 return PyString_FromStringAndSize(*v, v->size());
135 }
135 }
136 case QMetaType::QVariantMap:
136 case QMetaType::QVariantMap:
137 return PythonQtConv::QVariantMapToPyObject(*((QVariantMap*)data));
137 return PythonQtConv::QVariantMapToPyObject(*((QVariantMap*)data));
138 case QMetaType::QVariantList:
138 case QMetaType::QVariantList:
139 return PythonQtConv::QVariantListToPyObject(*((QVariantList*)data));
139 return PythonQtConv::QVariantListToPyObject(*((QVariantList*)data));
140 case QMetaType::QString:
140 case QMetaType::QString:
141 return PythonQtConv::QStringToPyObject(*((QString*)data));
141 return PythonQtConv::QStringToPyObject(*((QString*)data));
142 case QMetaType::QStringList:
142 case QMetaType::QStringList:
143 return PythonQtConv::QStringListToPyObject(*((QStringList*)data));
143 return PythonQtConv::QStringListToPyObject(*((QStringList*)data));
144
144
145 case PythonQtMethodInfo::Variant:
145 case PythonQtMethodInfo::Variant:
146 return PythonQtConv::QVariantToPyObject(*((QVariant*)data));
146 return PythonQtConv::QVariantToPyObject(*((QVariant*)data));
147 case QMetaType::QObjectStar:
147 case QMetaType::QObjectStar:
148 case QMetaType::QWidgetStar:
148 case QMetaType::QWidgetStar:
149 return PythonQt::priv()->wrapQObject(*((QObject**)data));
149 return PythonQt::priv()->wrapQObject(*((QObject**)data));
150
150
151 default:
151 default:
152 if (PythonQt::priv()->isPythonQtObjectPtrMetaId(type)) {
152 if (PythonQt::priv()->isPythonQtObjectPtrMetaId(type)) {
153 // special case, it is a PythonQtObjectPtr which contains a PyObject, take it directly:
153 // special case, it is a PythonQtObjectPtr which contains a PyObject, take it directly:
154 PyObject* o = ((PythonQtObjectPtr*)data)->object();
154 PyObject* o = ((PythonQtObjectPtr*)data)->object();
155 Py_INCREF(o);
155 Py_INCREF(o);
156 return o;
156 return o;
157 } else {
157 } else {
158 if (type > 0) {
158 if (type > 0) {
159 // if the type is known, we can construct it via QMetaType::construct
159 // if the type is known, we can construct it via QMetaType::construct
160 void* newCPPObject = QMetaType::construct(type, data);
160 void* newCPPObject = QMetaType::construct(type, data);
161 // XXX this could be optimized by using metatypeid directly
161 // XXX this could be optimized by using metatypeid directly
162 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)PythonQt::priv()->wrapPtr(newCPPObject, QMetaType::typeName(type));
162 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)PythonQt::priv()->wrapPtr(newCPPObject, QMetaType::typeName(type));
163 wrap->_ownedByPythonQt = true;
163 wrap->_ownedByPythonQt = true;
164 wrap->_useQMetaTypeDestroy = true;
164 wrap->_useQMetaTypeDestroy = true;
165 return (PyObject*)wrap;
165 return (PyObject*)wrap;
166 }
166 }
167 std::cerr << "Unknown type that can not be converted to Python: " << type << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
167 std::cerr << "Unknown type that can not be converted to Python: " << type << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
168 }
168 }
169 }
169 }
170 Py_INCREF(Py_None);
170 Py_INCREF(Py_None);
171 return Py_None;
171 return Py_None;
172 }
172 }
173
173
174 void* PythonQtConv::CreateQtReturnValue(const PythonQtMethodInfo::ParameterInfo& info) {
174 void* PythonQtConv::CreateQtReturnValue(const PythonQtMethodInfo::ParameterInfo& info) {
175 void* ptr = NULL;
175 void* ptr = NULL;
176 if (info.isPointer) {
176 if (info.isPointer) {
177 PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, NULL, ptr);
177 PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, NULL, ptr);
178 } else {
178 } else {
179 switch (info.typeId) {
179 switch (info.typeId) {
180 case QMetaType::Char:
180 case QMetaType::Char:
181 case QMetaType::UChar:
181 case QMetaType::UChar:
182 case QMetaType::Short:
182 case QMetaType::Short:
183 case QMetaType::UShort:
183 case QMetaType::UShort:
184 case QMetaType::Long:
184 case QMetaType::Long:
185 case QMetaType::ULong:
185 case QMetaType::ULong:
186 case QMetaType::Bool:
186 case QMetaType::Bool:
187 case QMetaType::Int:
187 case QMetaType::Int:
188 case QMetaType::UInt:
188 case QMetaType::UInt:
189 case QMetaType::QChar:
189 case QMetaType::QChar:
190 case QMetaType::Float:
190 case QMetaType::Float:
191 case QMetaType::Double:
191 case QMetaType::Double:
192 PythonQtValueStorage_ADD_VALUE(global_valueStorage, long, 0, ptr);
192 PythonQtValueStorage_ADD_VALUE(global_valueStorage, long, 0, ptr);
193 break;
193 break;
194 case PythonQtMethodInfo::Variant:
194 case PythonQtMethodInfo::Variant:
195 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, 0, ptr);
195 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, 0, ptr);
196 // return the ptr to the variant
196 // return the ptr to the variant
197 break;
197 break;
198 default:
198 default:
199 if (info.typeId == PythonQtMethodInfo::Unknown) {
199 if (info.typeId == PythonQtMethodInfo::Unknown) {
200 // check if we have a QList of pointers, which we can circumvent with a QList<void*>
200 // check if we have a QList of pointers, which we can circumvent with a QList<void*>
201 if (info.name.startsWith("QList<")) {
201 if (info.name.startsWith("QList<")) {
202 QByteArray innerType = info.name.mid(6,info.name.length()-7);
202 QByteArray innerType = info.name.mid(6,info.name.length()-7);
203 if (innerType.endsWith("*")) {
203 if (innerType.endsWith("*")) {
204 static int id = QMetaType::type("QList<void*>");
204 static int id = QMetaType::type("QList<void*>");
205 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(id), ptr);
205 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(id), ptr);
206 // return the constData pointer that will be filled with the result value later on
206 // return the constData pointer that will be filled with the result value later on
207 ptr = (void*)((QVariant*)ptr)->constData();
207 ptr = (void*)((QVariant*)ptr)->constData();
208 }
208 }
209 }
209 }
210 }
210 }
211
211
212 if (!ptr) {
212 if (!ptr && info.typeId!=PythonQtMethodInfo::Unknown) {
213 // everything else is stored in a QVariant...
213 // everything else is stored in a QVariant, if we know the meta type...
214 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(info.typeId), ptr);
214 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(info.typeId), ptr);
215 // return the constData pointer that will be filled with the result value later on
215 // return the constData pointer that will be filled with the result value later on
216 ptr = (void*)((QVariant*)ptr)->constData();
216 ptr = (void*)((QVariant*)ptr)->constData();
217 }
217 }
218 }
218 }
219 }
219 }
220 return ptr;
220 return ptr;
221 }
221 }
222
222
223 void* PythonQtConv::castWrapperTo(PythonQtInstanceWrapper* wrapper, const QByteArray& className, bool& ok)
223 void* PythonQtConv::castWrapperTo(PythonQtInstanceWrapper* wrapper, const QByteArray& className, bool& ok)
224 {
224 {
225 void* object;
225 void* object;
226 if (wrapper->classInfo()->isCPPWrapper()) {
226 if (wrapper->classInfo()->isCPPWrapper()) {
227 object = wrapper->_wrappedPtr;
227 object = wrapper->_wrappedPtr;
228 } else {
228 } else {
229 QObject* tmp = wrapper->_obj;
229 QObject* tmp = wrapper->_obj;
230 object = tmp;
230 object = tmp;
231 }
231 }
232 if (object) {
232 if (object) {
233 // if we can be upcasted to the given name, we pass the casted pointer in:
233 // if we can be upcasted to the given name, we pass the casted pointer in:
234 object = wrapper->classInfo()->castTo(object, className);
234 object = wrapper->classInfo()->castTo(object, className);
235 ok = object!=NULL;
235 ok = object!=NULL;
236 } else {
236 } else {
237 // if it is a NULL ptr, we need to check if it inherits, so that we might pass the NULL ptr
237 // if it is a NULL ptr, we need to check if it inherits, so that we might pass the NULL ptr
238 ok = wrapper->classInfo()->inherits(className);
238 ok = wrapper->classInfo()->inherits(className);
239 }
239 }
240 return object;
240 return object;
241 }
241 }
242
242
243 void* PythonQtConv::ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& info, PyObject* obj, bool strict, PythonQtClassInfo* meta, void* alreadyAllocatedCPPObject)
243 void* PythonQtConv::ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& info, PyObject* obj, bool strict, PythonQtClassInfo* meta, void* alreadyAllocatedCPPObject)
244 {
244 {
245 bool ok;
245 bool ok;
246 void* ptr = NULL;
246 void* ptr = NULL;
247 if (PyObject_TypeCheck(obj, &PythonQtInstanceWrapper_Type) && info.typeId != PythonQtMethodInfo::Variant) {
247 if (PyObject_TypeCheck(obj, &PythonQtInstanceWrapper_Type) && info.typeId != PythonQtMethodInfo::Variant) {
248 // if we have a Qt wrapper object and if we do not need a QVariant, we do the following:
248 // if we have a Qt wrapper object and if we do not need a QVariant, we do the following:
249 // (the Variant case is handled below in a switch)
249 // (the Variant case is handled below in a switch)
250
250
251 // a C++ wrapper (can be passed as pointer or reference)
251 // a C++ wrapper (can be passed as pointer or reference)
252 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)obj;
252 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)obj;
253 bool ok;
253 bool ok;
254 void* object = castWrapperTo(wrap, info.name, ok);
254 void* object = castWrapperTo(wrap, info.name, ok);
255 if (ok) {
255 if (ok) {
256 if (info.isPointer) {
256 if (info.isPointer) {
257 // store the wrapped pointer in an extra pointer and let ptr point to the extra pointer
257 // store the wrapped pointer in an extra pointer and let ptr point to the extra pointer
258 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, object, ptr);
258 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, object, ptr);
259 } else {
259 } else {
260 // store the wrapped pointer directly, since we are a reference
260 // store the wrapped pointer directly, since we are a reference
261 ptr = object;
261 ptr = object;
262 }
262 }
263 } else {
263 } else {
264 // not matching
264 // not matching
265 }
265 }
266 } else if (info.isPointer) {
266 } else if (info.isPointer) {
267 // a pointer
267 // a pointer
268 if (info.typeId == QMetaType::Char || info.typeId == QMetaType::UChar)
268 if (info.typeId == QMetaType::Char || info.typeId == QMetaType::UChar)
269 {
269 {
270 QString str = PyObjGetString(obj, strict, ok);
270 QString str = PyObjGetString(obj, strict, ok);
271 if (ok) {
271 if (ok) {
272 void* ptr2 = NULL;
272 void* ptr2 = NULL;
273 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(str.toUtf8()), ptr2);
273 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(str.toUtf8()), ptr2);
274 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, (((QByteArray*)((QVariant*)ptr2)->constData())->data()), ptr);
274 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, (((QByteArray*)((QVariant*)ptr2)->constData())->data()), ptr);
275 }
275 }
276 } else if (info.name == "PyObject") {
276 } else if (info.name == "PyObject") {
277 // handle low level PyObject directly
277 // handle low level PyObject directly
278 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, obj, ptr);
278 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, obj, ptr);
279 } else if (obj == Py_None) {
279 } else if (obj == Py_None) {
280 // None is treated as a NULL ptr
280 // None is treated as a NULL ptr
281 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, NULL, ptr);
281 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, NULL, ptr);
282 } else {
282 } else {
283 // if we are not strict, we try if we are passed a 0 integer
283 // if we are not strict, we try if we are passed a 0 integer
284 if (!strict) {
284 if (!strict) {
285 bool ok;
285 bool ok;
286 int value = PyObjGetInt(obj, true, ok);
286 int value = PyObjGetInt(obj, true, ok);
287 if (ok && value==0) {
287 if (ok && value==0) {
288 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, NULL, ptr);
288 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, NULL, ptr);
289 }
289 }
290 }
290 }
291 }
291 }
292 } else {
292 } else {
293 // not a pointer
293 // not a pointer
294 switch (info.typeId) {
294 switch (info.typeId) {
295 case QMetaType::Char:
295 case QMetaType::Char:
296 {
296 {
297 int val = PyObjGetInt(obj, strict, ok);
297 int val = PyObjGetInt(obj, strict, ok);
298 if (ok) {
298 if (ok) {
299 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, char, val, ptr);
299 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, char, val, ptr);
300 }
300 }
301 }
301 }
302 break;
302 break;
303 case QMetaType::UChar:
303 case QMetaType::UChar:
304 {
304 {
305 int val = PyObjGetInt(obj, strict, ok);
305 int val = PyObjGetInt(obj, strict, ok);
306 if (ok) {
306 if (ok) {
307 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned char, val, ptr);
307 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned char, val, ptr);
308 }
308 }
309 }
309 }
310 break;
310 break;
311 case QMetaType::Short:
311 case QMetaType::Short:
312 {
312 {
313 int val = PyObjGetInt(obj, strict, ok);
313 int val = PyObjGetInt(obj, strict, ok);
314 if (ok) {
314 if (ok) {
315 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, short, val, ptr);
315 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, short, val, ptr);
316 }
316 }
317 }
317 }
318 break;
318 break;
319 case QMetaType::UShort:
319 case QMetaType::UShort:
320 {
320 {
321 int val = PyObjGetInt(obj, strict, ok);
321 int val = PyObjGetInt(obj, strict, ok);
322 if (ok) {
322 if (ok) {
323 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned short, val, ptr);
323 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned short, val, ptr);
324 }
324 }
325 }
325 }
326 break;
326 break;
327 case QMetaType::Long:
327 case QMetaType::Long:
328 {
328 {
329 long val = (long)PyObjGetLongLong(obj, strict, ok);
329 long val = (long)PyObjGetLongLong(obj, strict, ok);
330 if (ok) {
330 if (ok) {
331 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, long, val, ptr);
331 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, long, val, ptr);
332 }
332 }
333 }
333 }
334 break;
334 break;
335 case QMetaType::ULong:
335 case QMetaType::ULong:
336 {
336 {
337 unsigned long val = (unsigned long)PyObjGetLongLong(obj, strict, ok);
337 unsigned long val = (unsigned long)PyObjGetLongLong(obj, strict, ok);
338 if (ok) {
338 if (ok) {
339 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned long, val, ptr);
339 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned long, val, ptr);
340 }
340 }
341 }
341 }
342 break;
342 break;
343 case QMetaType::Bool:
343 case QMetaType::Bool:
344 {
344 {
345 bool val = PyObjGetBool(obj, strict, ok);
345 bool val = PyObjGetBool(obj, strict, ok);
346 if (ok) {
346 if (ok) {
347 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, bool, val, ptr);
347 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, bool, val, ptr);
348 }
348 }
349 }
349 }
350 break;
350 break;
351 case QMetaType::Int:
351 case QMetaType::Int:
352 {
352 {
353 int val = PyObjGetInt(obj, strict, ok);
353 int val = PyObjGetInt(obj, strict, ok);
354 if (ok) {
354 if (ok) {
355 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, int, val, ptr);
355 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, int, val, ptr);
356 }
356 }
357 }
357 }
358 break;
358 break;
359 case QMetaType::UInt:
359 case QMetaType::UInt:
360 {
360 {
361 unsigned int val = (unsigned int)PyObjGetLongLong(obj, strict, ok);
361 unsigned int val = (unsigned int)PyObjGetLongLong(obj, strict, ok);
362 if (ok) {
362 if (ok) {
363 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned int, val, ptr);
363 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned int, val, ptr);
364 }
364 }
365 }
365 }
366 break;
366 break;
367 case QMetaType::QChar:
367 case QMetaType::QChar:
368 {
368 {
369 int val = PyObjGetInt(obj, strict, ok);
369 int val = PyObjGetInt(obj, strict, ok);
370 if (ok) {
370 if (ok) {
371 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, short, val, ptr);
371 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, short, val, ptr);
372 }
372 }
373 }
373 }
374 break;
374 break;
375 case QMetaType::Float:
375 case QMetaType::Float:
376 {
376 {
377 float val = (float)PyObjGetDouble(obj, strict, ok);
377 float val = (float)PyObjGetDouble(obj, strict, ok);
378 if (ok) {
378 if (ok) {
379 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, float, val, ptr);
379 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, float, val, ptr);
380 }
380 }
381 }
381 }
382 break;
382 break;
383 case QMetaType::Double:
383 case QMetaType::Double:
384 {
384 {
385 double val = (double)PyObjGetDouble(obj, strict, ok);
385 double val = (double)PyObjGetDouble(obj, strict, ok);
386 if (ok) {
386 if (ok) {
387 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, double, val, ptr);
387 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, double, val, ptr);
388 }
388 }
389 }
389 }
390 break;
390 break;
391 case QMetaType::LongLong:
391 case QMetaType::LongLong:
392 {
392 {
393 qint64 val = PyObjGetLongLong(obj, strict, ok);
393 qint64 val = PyObjGetLongLong(obj, strict, ok);
394 if (ok) {
394 if (ok) {
395 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, qint64, val, ptr);
395 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, qint64, val, ptr);
396 }
396 }
397 }
397 }
398 break;
398 break;
399 case QMetaType::ULongLong:
399 case QMetaType::ULongLong:
400 {
400 {
401 quint64 val = PyObjGetULongLong(obj, strict, ok);
401 quint64 val = PyObjGetULongLong(obj, strict, ok);
402 if (ok) {
402 if (ok) {
403 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, quint64, val, ptr);
403 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, quint64, val, ptr);
404 }
404 }
405 }
405 }
406 break;
406 break;
407 case QMetaType::QByteArray:
407 case QMetaType::QByteArray:
408 {
408 {
409 QByteArray bytes = PyObjGetBytes(obj, strict, ok);
409 QByteArray bytes = PyObjGetBytes(obj, strict, ok);
410 if (ok) {
410 if (ok) {
411 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(bytes), ptr);
411 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(bytes), ptr);
412 ptr = (void*)((QVariant*)ptr)->constData();
412 ptr = (void*)((QVariant*)ptr)->constData();
413 }
413 }
414 }
414 }
415 break;
415 break;
416 case QMetaType::QString:
416 case QMetaType::QString:
417 {
417 {
418 QString str = PyObjGetString(obj, strict, ok);
418 QString str = PyObjGetString(obj, strict, ok);
419 if (ok) {
419 if (ok) {
420 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(str), ptr);
420 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(str), ptr);
421 ptr = (void*)((QVariant*)ptr)->constData();
421 ptr = (void*)((QVariant*)ptr)->constData();
422 }
422 }
423 }
423 }
424 break;
424 break;
425 case QMetaType::QStringList:
425 case QMetaType::QStringList:
426 {
426 {
427 QStringList l = PyObjToStringList(obj, strict, ok);
427 QStringList l = PyObjToStringList(obj, strict, ok);
428 if (ok) {
428 if (ok) {
429 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(l), ptr);
429 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(l), ptr);
430 ptr = (void*)((QVariant*)ptr)->constData();
430 ptr = (void*)((QVariant*)ptr)->constData();
431 }
431 }
432 }
432 }
433 break;
433 break;
434
434
435 case PythonQtMethodInfo::Variant:
435 case PythonQtMethodInfo::Variant:
436 {
436 {
437 QVariant v = PyObjToQVariant(obj);
437 QVariant v = PyObjToQVariant(obj);
438 if (v.isValid()) {
438 if (v.isValid()) {
439 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, v, ptr);
439 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, v, ptr);
440 }
440 }
441 }
441 }
442 break;
442 break;
443 default:
443 default:
444 {
444 {
445 if (info.typeId == PythonQtMethodInfo::Unknown) {
445 if (info.typeId == PythonQtMethodInfo::Unknown) {
446 // check for enum case
446 // check for enum case
447 if (PythonQtClassInfo::hasEnum(info.name, meta)) {
447 if (PythonQtClassInfo::hasEnum(info.name, meta)) {
448 unsigned int val = (unsigned int)PyObjGetLongLong(obj, strict, ok);
448 unsigned int val = (unsigned int)PyObjGetLongLong(obj, strict, ok);
449 if (ok) {
449 if (ok) {
450 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned int, val, ptr);
450 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned int, val, ptr);
451 return ptr;
451 return ptr;
452 } else {
452 } else {
453 return NULL;
453 return NULL;
454 }
454 }
455 }
455 }
456 }
456 }
457 if (info.typeId == PythonQtMethodInfo::Unknown || info.typeId >= QMetaType::User) {
457 if (info.typeId == PythonQtMethodInfo::Unknown || info.typeId >= QMetaType::User) {
458 // check for QList<AnyPtr*> case, where we will use a QList<void*> QVariant
458 // check for QList<AnyPtr*> case, where we will use a QList<void*> QVariant
459 if (info.name.startsWith("QList<")) {
459 if (info.name.startsWith("QList<")) {
460 QByteArray innerType = info.name.mid(6,info.name.length()-7);
460 QByteArray innerType = info.name.mid(6,info.name.length()-7);
461 if (innerType.endsWith("*")) {
461 if (innerType.endsWith("*")) {
462 innerType.truncate(innerType.length()-1);
462 innerType.truncate(innerType.length()-1);
463 static int id = QMetaType::type("QList<void*>");
463 static int id = QMetaType::type("QList<void*>");
464 if (!alreadyAllocatedCPPObject) {
464 if (!alreadyAllocatedCPPObject) {
465 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant::Type(id), ptr);
465 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant::Type(id), ptr);
466 ptr = (void*)((QVariant*)ptr)->constData();
466 ptr = (void*)((QVariant*)ptr)->constData();
467 } else {
467 } else {
468 ptr = alreadyAllocatedCPPObject;
468 ptr = alreadyAllocatedCPPObject;
469 }
469 }
470 ok = ConvertPythonListToQListOfPointerType(obj, (QList<void*>*)ptr, innerType, strict);
470 ok = ConvertPythonListToQListOfPointerType(obj, (QList<void*>*)ptr, innerType, strict);
471 if (ok) {
471 if (ok) {
472 return ptr;
472 return ptr;
473 } else {
473 } else {
474 return NULL;
474 return NULL;
475 }
475 }
476 }
476 }
477 }
477 }
478 }
478 }
479
479
480 // We only do this for registered type > QMetaType::User for performance reasons.
480 // We only do this for registered type > QMetaType::User for performance reasons.
481 if (info.typeId >= QMetaType::User) {
481 if (info.typeId >= QMetaType::User) {
482 // Maybe we have a special converter that is registered for that type:
482 // Maybe we have a special converter that is registered for that type:
483 PythonQtConvertPythonToMetaTypeCB* converter = _pythonToMetaTypeConverters.value(info.typeId);
483 PythonQtConvertPythonToMetaTypeCB* converter = _pythonToMetaTypeConverters.value(info.typeId);
484 if (converter) {
484 if (converter) {
485 if (!alreadyAllocatedCPPObject) {
485 if (!alreadyAllocatedCPPObject) {
486 // create a new empty variant of concrete type:
486 // create a new empty variant of concrete type:
487 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant::Type(info.typeId), ptr);
487 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant::Type(info.typeId), ptr);
488 ptr = (void*)((QVariant*)ptr)->constData();
488 ptr = (void*)((QVariant*)ptr)->constData();
489 } else {
489 } else {
490 ptr = alreadyAllocatedCPPObject;
490 ptr = alreadyAllocatedCPPObject;
491 }
491 }
492 // now call the converter, passing the internal object of the variant
492 // now call the converter, passing the internal object of the variant
493 ok = (*converter)(obj, ptr, info.typeId, strict);
493 ok = (*converter)(obj, ptr, info.typeId, strict);
494 if (ok) {
494 if (ok) {
495 return ptr;
495 return ptr;
496 } else {
496 } else {
497 return NULL;
497 return NULL;
498 }
498 }
499 }
499 }
500 }
500 }
501 // if no type id is available, conversion to a QVariant makes no sense/is not possible
501 // if no type id is available, conversion to a QVariant makes no sense/is not possible
502 if (info.typeId != PythonQtMethodInfo::Unknown) {
502 if (info.typeId != PythonQtMethodInfo::Unknown) {
503 // for all other types, we use the same qvariant conversion and pass out the constData of the variant:
503 // for all other types, we use the same qvariant conversion and pass out the constData of the variant:
504 QVariant v = PyObjToQVariant(obj, info.typeId);
504 QVariant v = PyObjToQVariant(obj, info.typeId);
505 if (v.isValid()) {
505 if (v.isValid()) {
506 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, v, ptr);
506 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, v, ptr);
507 ptr = (void*)((QVariant*)ptr)->constData();
507 ptr = (void*)((QVariant*)ptr)->constData();
508 }
508 }
509 }
509 }
510 }
510 }
511 }
511 }
512 }
512 }
513 return ptr;
513 return ptr;
514 }
514 }
515
515
516
516
517 QStringList PythonQtConv::PyObjToStringList(PyObject* val, bool strict, bool& ok) {
517 QStringList PythonQtConv::PyObjToStringList(PyObject* val, bool strict, bool& ok) {
518 QStringList v;
518 QStringList v;
519 ok = false;
519 ok = false;
520 // if we are strict, we do not want to convert a string to a stringlist
520 // if we are strict, we do not want to convert a string to a stringlist
521 // (strings in python are detected to be sequences)
521 // (strings in python are detected to be sequences)
522 if (strict &&
522 if (strict &&
523 (val->ob_type == &PyString_Type ||
523 (val->ob_type == &PyString_Type ||
524 PyUnicode_Check(val))) {
524 PyUnicode_Check(val))) {
525 ok = false;
525 ok = false;
526 return v;
526 return v;
527 }
527 }
528 if (PySequence_Check(val)) {
528 if (PySequence_Check(val)) {
529 int count = PySequence_Size(val);
529 int count = PySequence_Size(val);
530 for (int i = 0;i<count;i++) {
530 for (int i = 0;i<count;i++) {
531 PyObject* value = PySequence_GetItem(val,i);
531 PyObject* value = PySequence_GetItem(val,i);
532 v.append(PyObjGetString(value,false,ok));
532 v.append(PyObjGetString(value,false,ok));
533 }
533 }
534 ok = true;
534 ok = true;
535 }
535 }
536 return v;
536 return v;
537 }
537 }
538
538
539 QString PythonQtConv::PyObjGetRepresentation(PyObject* val)
539 QString PythonQtConv::PyObjGetRepresentation(PyObject* val)
540 {
540 {
541 QString r;
541 QString r;
542 PyObject* str = PyObject_Repr(val);
542 PyObject* str = PyObject_Repr(val);
543 if (str) {
543 if (str) {
544 r = QString(PyString_AS_STRING(str));
544 r = QString(PyString_AS_STRING(str));
545 Py_DECREF(str);
545 Py_DECREF(str);
546 }
546 }
547 return r;
547 return r;
548 }
548 }
549
549
550 QString PythonQtConv::PyObjGetString(PyObject* val, bool strict, bool& ok) {
550 QString PythonQtConv::PyObjGetString(PyObject* val, bool strict, bool& ok) {
551 QString r;
551 QString r;
552 ok = true;
552 ok = true;
553 if (val->ob_type == &PyString_Type) {
553 if (val->ob_type == &PyString_Type) {
554 r = QString(PyString_AS_STRING(val));
554 r = QString(PyString_AS_STRING(val));
555 } else if (PyUnicode_Check(val)) {
555 } else if (PyUnicode_Check(val)) {
556 #ifdef WIN32
556 #ifdef WIN32
557 r = QString::fromUtf16(PyUnicode_AS_UNICODE(val));
557 r = QString::fromUtf16(PyUnicode_AS_UNICODE(val));
558 #else
558 #else
559 PyObject *ptmp = PyUnicode_AsUTF8String(val);
559 PyObject *ptmp = PyUnicode_AsUTF8String(val);
560 if(ptmp) {
560 if(ptmp) {
561 r = QString::fromUtf8(PyString_AS_STRING(ptmp));
561 r = QString::fromUtf8(PyString_AS_STRING(ptmp));
562 Py_DECREF(ptmp);
562 Py_DECREF(ptmp);
563 }
563 }
564 #endif
564 #endif
565 } else if (!strict) {
565 } else if (!strict) {
566 // EXTRA: could also use _Unicode, but why should we?
566 // EXTRA: could also use _Unicode, but why should we?
567 PyObject* str = PyObject_Str(val);
567 PyObject* str = PyObject_Str(val);
568 if (str) {
568 if (str) {
569 r = QString(PyString_AS_STRING(str));
569 r = QString(PyString_AS_STRING(str));
570 Py_DECREF(str);
570 Py_DECREF(str);
571 } else {
571 } else {
572 ok = false;
572 ok = false;
573 }
573 }
574 } else {
574 } else {
575 ok = false;
575 ok = false;
576 }
576 }
577 return r;
577 return r;
578 }
578 }
579
579
580 QByteArray PythonQtConv::PyObjGetBytes(PyObject* val, bool /*strict*/, bool& ok) {
580 QByteArray PythonQtConv::PyObjGetBytes(PyObject* val, bool /*strict*/, bool& ok) {
581 QByteArray r;
581 QByteArray r;
582 ok = true;
582 ok = true;
583 if (val->ob_type == &PyString_Type) {
583 if (val->ob_type == &PyString_Type) {
584 long size = PyString_GET_SIZE(val);
584 long size = PyString_GET_SIZE(val);
585 r = QByteArray(PyString_AS_STRING(val), size);
585 r = QByteArray(PyString_AS_STRING(val), size);
586 } else {
586 } else {
587 ok = false;
587 ok = false;
588 }
588 }
589 return r;
589 return r;
590 }
590 }
591
591
592 bool PythonQtConv::PyObjGetBool(PyObject* val, bool strict, bool &ok) {
592 bool PythonQtConv::PyObjGetBool(PyObject* val, bool strict, bool &ok) {
593 bool d = false;
593 bool d = false;
594 ok = false;
594 ok = false;
595 if (val == Py_False) {
595 if (val == Py_False) {
596 d = false;
596 d = false;
597 ok = true;
597 ok = true;
598 } else if (val == Py_True) {
598 } else if (val == Py_True) {
599 d = true;
599 d = true;
600 ok = true;
600 ok = true;
601 } else if (!strict) {
601 } else if (!strict) {
602 d = PyObjGetInt(val, false, ok)!=0;
602 d = PyObjGetInt(val, false, ok)!=0;
603 ok = true;
603 ok = true;
604 }
604 }
605 return d;
605 return d;
606 }
606 }
607
607
608 int PythonQtConv::PyObjGetInt(PyObject* val, bool strict, bool &ok) {
608 int PythonQtConv::PyObjGetInt(PyObject* val, bool strict, bool &ok) {
609 int d = 0;
609 int d = 0;
610 ok = true;
610 ok = true;
611 if (val->ob_type == &PyInt_Type) {
611 if (val->ob_type == &PyInt_Type) {
612 d = PyInt_AS_LONG(val);
612 d = PyInt_AS_LONG(val);
613 } else if (!strict) {
613 } else if (!strict) {
614 if (val->ob_type == &PyFloat_Type) {
614 if (val->ob_type == &PyFloat_Type) {
615 d = floor(PyFloat_AS_DOUBLE(val));
615 d = floor(PyFloat_AS_DOUBLE(val));
616 } else if (val->ob_type == &PyLong_Type) {
616 } else if (val->ob_type == &PyLong_Type) {
617 // handle error on overflow!
617 // handle error on overflow!
618 d = PyLong_AsLong(val);
618 d = PyLong_AsLong(val);
619 } else if (val == Py_False) {
619 } else if (val == Py_False) {
620 d = 0;
620 d = 0;
621 } else if (val == Py_True) {
621 } else if (val == Py_True) {
622 d = 1;
622 d = 1;
623 } else {
623 } else {
624 ok = false;
624 ok = false;
625 }
625 }
626 } else {
626 } else {
627 ok = false;
627 ok = false;
628 }
628 }
629 return d;
629 return d;
630 }
630 }
631
631
632 qint64 PythonQtConv::PyObjGetLongLong(PyObject* val, bool strict, bool &ok) {
632 qint64 PythonQtConv::PyObjGetLongLong(PyObject* val, bool strict, bool &ok) {
633 qint64 d = 0;
633 qint64 d = 0;
634 ok = true;
634 ok = true;
635 if (val->ob_type == &PyInt_Type) {
635 if (val->ob_type == &PyInt_Type) {
636 d = PyInt_AS_LONG(val);
636 d = PyInt_AS_LONG(val);
637 } else if (val->ob_type == &PyLong_Type) {
637 } else if (val->ob_type == &PyLong_Type) {
638 d = PyLong_AsLongLong(val);
638 d = PyLong_AsLongLong(val);
639 } else if (!strict) {
639 } else if (!strict) {
640 if (val->ob_type == &PyFloat_Type) {
640 if (val->ob_type == &PyFloat_Type) {
641 d = floor(PyFloat_AS_DOUBLE(val));
641 d = floor(PyFloat_AS_DOUBLE(val));
642 } else if (val == Py_False) {
642 } else if (val == Py_False) {
643 d = 0;
643 d = 0;
644 } else if (val == Py_True) {
644 } else if (val == Py_True) {
645 d = 1;
645 d = 1;
646 } else {
646 } else {
647 ok = false;
647 ok = false;
648 }
648 }
649 } else {
649 } else {
650 ok = false;
650 ok = false;
651 }
651 }
652 return d;
652 return d;
653 }
653 }
654
654
655 quint64 PythonQtConv::PyObjGetULongLong(PyObject* val, bool strict, bool &ok) {
655 quint64 PythonQtConv::PyObjGetULongLong(PyObject* val, bool strict, bool &ok) {
656 quint64 d = 0;
656 quint64 d = 0;
657 ok = true;
657 ok = true;
658 if (val->ob_type == &PyInt_Type) {
658 if (val->ob_type == &PyInt_Type) {
659 d = PyInt_AS_LONG(val);
659 d = PyInt_AS_LONG(val);
660 } else if (val->ob_type == &PyLong_Type) {
660 } else if (val->ob_type == &PyLong_Type) {
661 d = PyLong_AsLongLong(val);
661 d = PyLong_AsLongLong(val);
662 } else if (!strict) {
662 } else if (!strict) {
663 if (val->ob_type == &PyFloat_Type) {
663 if (val->ob_type == &PyFloat_Type) {
664 d = floor(PyFloat_AS_DOUBLE(val));
664 d = floor(PyFloat_AS_DOUBLE(val));
665 } else if (val == Py_False) {
665 } else if (val == Py_False) {
666 d = 0;
666 d = 0;
667 } else if (val == Py_True) {
667 } else if (val == Py_True) {
668 d = 1;
668 d = 1;
669 } else {
669 } else {
670 ok = false;
670 ok = false;
671 }
671 }
672 } else {
672 } else {
673 ok = false;
673 ok = false;
674 }
674 }
675 return d;
675 return d;
676 }
676 }
677
677
678 double PythonQtConv::PyObjGetDouble(PyObject* val, bool strict, bool &ok) {
678 double PythonQtConv::PyObjGetDouble(PyObject* val, bool strict, bool &ok) {
679 double d = 0;
679 double d = 0;
680 ok = true;
680 ok = true;
681 if (val->ob_type == &PyFloat_Type) {
681 if (val->ob_type == &PyFloat_Type) {
682 d = PyFloat_AS_DOUBLE(val);
682 d = PyFloat_AS_DOUBLE(val);
683 } else if (!strict) {
683 } else if (!strict) {
684 if (val->ob_type == &PyInt_Type) {
684 if (val->ob_type == &PyInt_Type) {
685 d = PyInt_AS_LONG(val);
685 d = PyInt_AS_LONG(val);
686 } else if (val->ob_type == &PyLong_Type) {
686 } else if (val->ob_type == &PyLong_Type) {
687 d = PyLong_AsLong(val);
687 d = PyLong_AsLong(val);
688 } else if (val == Py_False) {
688 } else if (val == Py_False) {
689 d = 0;
689 d = 0;
690 } else if (val == Py_True) {
690 } else if (val == Py_True) {
691 d = 1;
691 d = 1;
692 } else {
692 } else {
693 ok = false;
693 ok = false;
694 }
694 }
695 } else {
695 } else {
696 ok = false;
696 ok = false;
697 }
697 }
698 return d;
698 return d;
699 }
699 }
700
700
701 QVariant PythonQtConv::PyObjToQVariant(PyObject* val, int type)
701 QVariant PythonQtConv::PyObjToQVariant(PyObject* val, int type)
702 {
702 {
703 QVariant v;
703 QVariant v;
704 bool ok = true;
704 bool ok = true;
705
705
706 if (type==-1) {
706 if (type==-1) {
707 // no special type requested
707 // no special type requested
708 if (val->ob_type==&PyString_Type || val->ob_type==&PyUnicode_Type) {
708 if (val->ob_type==&PyString_Type || val->ob_type==&PyUnicode_Type) {
709 type = QVariant::String;
709 type = QVariant::String;
710 } else if (val->ob_type==&PyInt_Type) {
710 } else if (val->ob_type==&PyInt_Type) {
711 type = QVariant::Int;
711 type = QVariant::Int;
712 } else if (val->ob_type==&PyLong_Type) {
712 } else if (val->ob_type==&PyLong_Type) {
713 type = QVariant::LongLong;
713 type = QVariant::LongLong;
714 } else if (val->ob_type==&PyFloat_Type) {
714 } else if (val->ob_type==&PyFloat_Type) {
715 type = QVariant::Double;
715 type = QVariant::Double;
716 } else if (val == Py_False || val == Py_True) {
716 } else if (val == Py_False || val == Py_True) {
717 type = QVariant::Bool;
717 type = QVariant::Bool;
718 } else if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) {
718 } else if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) {
719 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
719 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
720 // c++ wrapper, check if the class names of the c++ objects match
720 // c++ wrapper, check if the class names of the c++ objects match
721 if (wrap->classInfo()->isCPPWrapper()) {
721 if (wrap->classInfo()->isCPPWrapper()) {
722 if (wrap->classInfo()->metaTypeId()>0) {
722 if (wrap->classInfo()->metaTypeId()>0) {
723 // construct a new variant from the C++ object if it has a meta type (this will COPY the object!)
723 // construct a new variant from the C++ object if it has a meta type (this will COPY the object!)
724 v = QVariant(wrap->classInfo()->metaTypeId(), wrap->_wrappedPtr);
724 v = QVariant(wrap->classInfo()->metaTypeId(), wrap->_wrappedPtr);
725 } else {
725 } else {
726 // TODOXXX we could as well check if there is a registered meta type for "classname*", so that we may pass
726 // TODOXXX we could as well check if there is a registered meta type for "classname*", so that we may pass
727 // the pointer here...
727 // the pointer here...
728 // is this worth anything? we loose the knowledge of the cpp object type
728 // is this worth anything? we loose the knowledge of the cpp object type
729 v = qVariantFromValue(wrap->_wrappedPtr);
729 v = qVariantFromValue(wrap->_wrappedPtr);
730 }
730 }
731 } else {
731 } else {
732 // this gives us a QObject pointer
732 // this gives us a QObject pointer
733 QObject* myObject = wrap->_obj;
733 QObject* myObject = wrap->_obj;
734 v = qVariantFromValue(myObject);
734 v = qVariantFromValue(myObject);
735 }
735 }
736 return v;
736 return v;
737 } else if (val->ob_type==&PyDict_Type) {
737 } else if (val->ob_type==&PyDict_Type) {
738 type = QVariant::Map;
738 type = QVariant::Map;
739 } else if (val->ob_type==&PyList_Type || val->ob_type==&PyTuple_Type || PySequence_Check(val)) {
739 } else if (val->ob_type==&PyList_Type || val->ob_type==&PyTuple_Type || PySequence_Check(val)) {
740 type = QVariant::List;
740 type = QVariant::List;
741 } else if (val == Py_None) {
741 } else if (val == Py_None) {
742 // none is invalid
742 // none is invalid
743 type = QVariant::Invalid;
743 type = QVariant::Invalid;
744 } else {
744 } else {
745 // this used to be:
745 // this used to be:
746 // type = QVariant::String;
746 // type = QVariant::String;
747 // but now we want to transport the Python Objects directly:
747 // but now we want to transport the Python Objects directly:
748 PythonQtObjectPtr o(val);
748 PythonQtObjectPtr o(val);
749 v = qVariantFromValue(o);
749 v = qVariantFromValue(o);
750 return v;
750 return v;
751 }
751 }
752 }
752 }
753 // special type request:
753 // special type request:
754 switch (type) {
754 switch (type) {
755 case QVariant::Invalid:
755 case QVariant::Invalid:
756 return v;
756 return v;
757 break;
757 break;
758 case QVariant::Int:
758 case QVariant::Int:
759 {
759 {
760 int d = PyObjGetInt(val, false, ok);
760 int d = PyObjGetInt(val, false, ok);
761 if (ok) return QVariant(d);
761 if (ok) return QVariant(d);
762 }
762 }
763 break;
763 break;
764 case QVariant::UInt:
764 case QVariant::UInt:
765 {
765 {
766 int d = PyObjGetInt(val, false,ok);
766 int d = PyObjGetInt(val, false,ok);
767 if (ok) v = QVariant((unsigned int)d);
767 if (ok) v = QVariant((unsigned int)d);
768 }
768 }
769 break;
769 break;
770 case QVariant::Bool:
770 case QVariant::Bool:
771 {
771 {
772 int d = PyObjGetBool(val,false,ok);
772 int d = PyObjGetBool(val,false,ok);
773 if (ok) v = QVariant((bool)(d!=0));
773 if (ok) v = QVariant((bool)(d!=0));
774 }
774 }
775 break;
775 break;
776 case QVariant::Double:
776 case QVariant::Double:
777 {
777 {
778 double d = PyObjGetDouble(val,false,ok);
778 double d = PyObjGetDouble(val,false,ok);
779 if (ok) v = QVariant(d);
779 if (ok) v = QVariant(d);
780 break;
780 break;
781 }
781 }
782 case QMetaType::Float:
782 case QMetaType::Float:
783 {
783 {
784 float d = (float) PyObjGetDouble(val,false,ok);
784 float d = (float) PyObjGetDouble(val,false,ok);
785 if (ok) v = qVariantFromValue(d);
785 if (ok) v = qVariantFromValue(d);
786 break;
786 break;
787 }
787 }
788 case QMetaType::Long:
788 case QMetaType::Long:
789 {
789 {
790 long d = (long) PyObjGetLongLong(val,false,ok);
790 long d = (long) PyObjGetLongLong(val,false,ok);
791 if (ok) v = qVariantFromValue(d);
791 if (ok) v = qVariantFromValue(d);
792 break;
792 break;
793 }
793 }
794 case QMetaType::ULong:
794 case QMetaType::ULong:
795 {
795 {
796 unsigned long d = (unsigned long) PyObjGetLongLong(val,false,ok);
796 unsigned long d = (unsigned long) PyObjGetLongLong(val,false,ok);
797 if (ok) v = qVariantFromValue(d);
797 if (ok) v = qVariantFromValue(d);
798 break;
798 break;
799 }
799 }
800 case QMetaType::Short:
800 case QMetaType::Short:
801 {
801 {
802 short d = (short) PyObjGetInt(val,false,ok);
802 short d = (short) PyObjGetInt(val,false,ok);
803 if (ok) v = qVariantFromValue(d);
803 if (ok) v = qVariantFromValue(d);
804 break;
804 break;
805 }
805 }
806 case QMetaType::UShort:
806 case QMetaType::UShort:
807 {
807 {
808 unsigned short d = (unsigned short) PyObjGetInt(val,false,ok);
808 unsigned short d = (unsigned short) PyObjGetInt(val,false,ok);
809 if (ok) v = qVariantFromValue(d);
809 if (ok) v = qVariantFromValue(d);
810 break;
810 break;
811 }
811 }
812 case QMetaType::Char:
812 case QMetaType::Char:
813 {
813 {
814 char d = (char) PyObjGetInt(val,false,ok);
814 char d = (char) PyObjGetInt(val,false,ok);
815 if (ok) v = qVariantFromValue(d);
815 if (ok) v = qVariantFromValue(d);
816 break;
816 break;
817 }
817 }
818 case QMetaType::UChar:
818 case QMetaType::UChar:
819 {
819 {
820 unsigned char d = (unsigned char) PyObjGetInt(val,false,ok);
820 unsigned char d = (unsigned char) PyObjGetInt(val,false,ok);
821 if (ok) v = qVariantFromValue(d);
821 if (ok) v = qVariantFromValue(d);
822 break;
822 break;
823 }
823 }
824
824
825 case QVariant::ByteArray:
825 case QVariant::ByteArray:
826 case QVariant::String:
826 case QVariant::String:
827 {
827 {
828 bool ok;
828 bool ok;
829 v = QVariant(PyObjGetString(val, false, ok));
829 v = QVariant(PyObjGetString(val, false, ok));
830 }
830 }
831 break;
831 break;
832
832
833 // these are important for MeVisLab
833 // these are important for MeVisLab
834 case QVariant::Map:
834 case QVariant::Map:
835 {
835 {
836 if (PyMapping_Check(val)) {
836 if (PyMapping_Check(val)) {
837 QMap<QString,QVariant> map;
837 QMap<QString,QVariant> map;
838 PyObject* items = PyMapping_Items(val);
838 PyObject* items = PyMapping_Items(val);
839 if (items) {
839 if (items) {
840 int count = PyList_Size(items);
840 int count = PyList_Size(items);
841 PyObject* value;
841 PyObject* value;
842 PyObject* key;
842 PyObject* key;
843 PyObject* tuple;
843 PyObject* tuple;
844 for (int i = 0;i<count;i++) {
844 for (int i = 0;i<count;i++) {
845 tuple = PyList_GetItem(items,i);
845 tuple = PyList_GetItem(items,i);
846 key = PyTuple_GetItem(tuple, 0);
846 key = PyTuple_GetItem(tuple, 0);
847 value = PyTuple_GetItem(tuple, 1);
847 value = PyTuple_GetItem(tuple, 1);
848 map.insert(PyObjGetString(key), PyObjToQVariant(value,-1));
848 map.insert(PyObjGetString(key), PyObjToQVariant(value,-1));
849 }
849 }
850 Py_DECREF(items);
850 Py_DECREF(items);
851 v = map;
851 v = map;
852 }
852 }
853 }
853 }
854 }
854 }
855 break;
855 break;
856 case QVariant::List:
856 case QVariant::List:
857 if (PySequence_Check(val)) {
857 if (PySequence_Check(val)) {
858 QVariantList list;
858 QVariantList list;
859 int count = PySequence_Size(val);
859 int count = PySequence_Size(val);
860 PyObject* value;
860 PyObject* value;
861 for (int i = 0;i<count;i++) {
861 for (int i = 0;i<count;i++) {
862 value = PySequence_GetItem(val,i);
862 value = PySequence_GetItem(val,i);
863 list.append(PyObjToQVariant(value, -1));
863 list.append(PyObjToQVariant(value, -1));
864 }
864 }
865 v = list;
865 v = list;
866 }
866 }
867 break;
867 break;
868 case QVariant::StringList:
868 case QVariant::StringList:
869 {
869 {
870 bool ok;
870 bool ok;
871 QStringList l = PyObjToStringList(val, false, ok);
871 QStringList l = PyObjToStringList(val, false, ok);
872 if (ok) {
872 if (ok) {
873 v = l;
873 v = l;
874 }
874 }
875 }
875 }
876 break;
876 break;
877
877
878 default:
878 default:
879 if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) {
879 if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) {
880 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
880 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
881 if (wrap->classInfo()->isCPPWrapper() && wrap->classInfo()->metaTypeId() == type) {
881 if (wrap->classInfo()->isCPPWrapper() && wrap->classInfo()->metaTypeId() == type) {
882 // construct a new variant from the C++ object if it has the same meta type
882 // construct a new variant from the C++ object if it has the same meta type
883 v = QVariant(type, wrap->_wrappedPtr);
883 v = QVariant(type, wrap->_wrappedPtr);
884 } else {
884 } else {
885 v = QVariant();
885 v = QVariant();
886 }
886 }
887 } else {
887 } else {
888 v = QVariant();
888 v = QVariant();
889 }
889 }
890 }
890 }
891 return v;
891 return v;
892 }
892 }
893
893
894 PyObject* PythonQtConv::QStringToPyObject(const QString& str)
894 PyObject* PythonQtConv::QStringToPyObject(const QString& str)
895 {
895 {
896 if (str.isNull()) {
896 if (str.isNull()) {
897 return PyString_FromString("");
897 return PyString_FromString("");
898 } else {
898 } else {
899 #ifdef WIN32
899 #ifdef WIN32
900 // return PyString_FromString(str.toLatin1().data());
900 // return PyString_FromString(str.toLatin1().data());
901 return PyUnicode_FromUnicode(str.utf16(), str.length());
901 return PyUnicode_FromUnicode(str.utf16(), str.length());
902 #else
902 #else
903 return PyUnicode_DecodeUTF16((const char*)str.utf16(), str.length()*2, NULL, NULL);
903 return PyUnicode_DecodeUTF16((const char*)str.utf16(), str.length()*2, NULL, NULL);
904 #endif
904 #endif
905 }
905 }
906 }
906 }
907
907
908 PyObject* PythonQtConv::QStringListToPyObject(const QStringList& list)
908 PyObject* PythonQtConv::QStringListToPyObject(const QStringList& list)
909 {
909 {
910 PyObject* result = PyTuple_New(list.count());
910 PyObject* result = PyTuple_New(list.count());
911 int i = 0;
911 int i = 0;
912 QString str;
912 QString str;
913 foreach (str, list) {
913 foreach (str, list) {
914 PyTuple_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(str));
914 PyTuple_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(str));
915 i++;
915 i++;
916 }
916 }
917 // why is the error state bad after this?
917 // why is the error state bad after this?
918 PyErr_Clear();
918 PyErr_Clear();
919 return result;
919 return result;
920 }
920 }
921
921
922 PyObject* PythonQtConv::QStringListToPyList(const QStringList& list)
922 PyObject* PythonQtConv::QStringListToPyList(const QStringList& list)
923 {
923 {
924 PyObject* result = PyList_New(list.count());
924 PyObject* result = PyList_New(list.count());
925 int i = 0;
925 int i = 0;
926 for (QStringList::ConstIterator it = list.begin(); it!=list.end(); ++it) {
926 for (QStringList::ConstIterator it = list.begin(); it!=list.end(); ++it) {
927 PyList_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(*it));
927 PyList_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(*it));
928 i++;
928 i++;
929 }
929 }
930 return result;
930 return result;
931 }
931 }
932
932
933 PyObject* PythonQtConv::QVariantToPyObject(const QVariant& v)
933 PyObject* PythonQtConv::QVariantToPyObject(const QVariant& v)
934 {
934 {
935 return ConvertQtValueToPythonInternal(v.userType(), (void*)v.constData());
935 return ConvertQtValueToPythonInternal(v.userType(), (void*)v.constData());
936 }
936 }
937
937
938 PyObject* PythonQtConv::QVariantMapToPyObject(const QVariantMap& m) {
938 PyObject* PythonQtConv::QVariantMapToPyObject(const QVariantMap& m) {
939 PyObject* result = PyDict_New();
939 PyObject* result = PyDict_New();
940 QVariantMap::const_iterator t = m.constBegin();
940 QVariantMap::const_iterator t = m.constBegin();
941 PyObject* key;
941 PyObject* key;
942 PyObject* val;
942 PyObject* val;
943 for (;t!=m.end();t++) {
943 for (;t!=m.end();t++) {
944 key = QStringToPyObject(t.key());
944 key = QStringToPyObject(t.key());
945 val = QVariantToPyObject(t.value());
945 val = QVariantToPyObject(t.value());
946 PyDict_SetItem(result, key, val);
946 PyDict_SetItem(result, key, val);
947 Py_DECREF(key);
947 Py_DECREF(key);
948 Py_DECREF(val);
948 Py_DECREF(val);
949 }
949 }
950 return result;
950 return result;
951 }
951 }
952
952
953 PyObject* PythonQtConv::QVariantListToPyObject(const QVariantList& l) {
953 PyObject* PythonQtConv::QVariantListToPyObject(const QVariantList& l) {
954 PyObject* result = PyTuple_New(l.count());
954 PyObject* result = PyTuple_New(l.count());
955 int i = 0;
955 int i = 0;
956 QVariant v;
956 QVariant v;
957 foreach (v, l) {
957 foreach (v, l) {
958 PyTuple_SET_ITEM(result, i, PythonQtConv::QVariantToPyObject(v));
958 PyTuple_SET_ITEM(result, i, PythonQtConv::QVariantToPyObject(v));
959 i++;
959 i++;
960 }
960 }
961 // why is the error state bad after this?
961 // why is the error state bad after this?
962 PyErr_Clear();
962 PyErr_Clear();
963 return result;
963 return result;
964 }
964 }
965
965
966 PyObject* PythonQtConv::ConvertQListOfPointerTypeToPythonList(QList<void*>* list, const QByteArray& typeName)
966 PyObject* PythonQtConv::ConvertQListOfPointerTypeToPythonList(QList<void*>* list, const QByteArray& typeName)
967 {
967 {
968 PyObject* result = PyTuple_New(list->count());
968 PyObject* result = PyTuple_New(list->count());
969 int i = 0;
969 int i = 0;
970 foreach (void* value, *list) {
970 foreach (void* value, *list) {
971 PyTuple_SET_ITEM(result, i, PythonQt::priv()->wrapPtr(value, typeName));
971 PyTuple_SET_ITEM(result, i, PythonQt::priv()->wrapPtr(value, typeName));
972 i++;
972 i++;
973 }
973 }
974 return result;
974 return result;
975 }
975 }
976
976
977 bool PythonQtConv::ConvertPythonListToQListOfPointerType(PyObject* obj, QList<void*>* list, const QByteArray& type, bool /*strict*/)
977 bool PythonQtConv::ConvertPythonListToQListOfPointerType(PyObject* obj, QList<void*>* list, const QByteArray& type, bool /*strict*/)
978 {
978 {
979 bool result = false;
979 bool result = false;
980 if (PySequence_Check(obj)) {
980 if (PySequence_Check(obj)) {
981 result = true;
981 result = true;
982 int count = PySequence_Size(obj);
982 int count = PySequence_Size(obj);
983 PyObject* value;
983 PyObject* value;
984 for (int i = 0;i<count;i++) {
984 for (int i = 0;i<count;i++) {
985 value = PySequence_GetItem(obj,i);
985 value = PySequence_GetItem(obj,i);
986 if (PyObject_TypeCheck(value, &PythonQtInstanceWrapper_Type)) {
986 if (PyObject_TypeCheck(value, &PythonQtInstanceWrapper_Type)) {
987 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)value;
987 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)value;
988 bool ok;
988 bool ok;
989 void* object = castWrapperTo(wrap, type, ok);
989 void* object = castWrapperTo(wrap, type, ok);
990 if (ok) {
990 if (ok) {
991 list->append(object);
991 list->append(object);
992 } else {
992 } else {
993 result = false;
993 result = false;
994 break;
994 break;
995 }
995 }
996 }
996 }
997 }
997 }
998 }
998 }
999 return result;
999 return result;
1000 }
1000 }
1001
1001
1002 int PythonQtConv::getInnerTemplateMetaType(const QByteArray& typeName)
1002 int PythonQtConv::getInnerTemplateMetaType(const QByteArray& typeName)
1003 {
1003 {
1004 int idx = typeName.indexOf("<");
1004 int idx = typeName.indexOf("<");
1005 if (idx>0) {
1005 if (idx>0) {
1006 int idx2 = typeName.indexOf(">");
1006 int idx2 = typeName.indexOf(">");
1007 if (idx2>0) {
1007 if (idx2>0) {
1008 QByteArray innerType = typeName.mid(idx+1,idx2-idx-1);
1008 QByteArray innerType = typeName.mid(idx+1,idx2-idx-1);
1009 return QMetaType::type(innerType.constData());
1009 return QMetaType::type(innerType.constData());
1010 }
1010 }
1011 }
1011 }
1012 return QMetaType::Void;
1012 return QMetaType::Void;
1013 }
1013 }
1014
1014
1015
1015
1016
1016
1017 QString PythonQtConv::qVariantToString(const QVariant& v) {
1017 QString PythonQtConv::qVariantToString(const QVariant& v) {
1018 return CPPObjectToString(v.userType(), v.constData());
1018 return CPPObjectToString(v.userType(), v.constData());
1019 }
1019 }
1020
1020
1021 QString PythonQtConv::CPPObjectToString(int type, const void* data) {
1021 QString PythonQtConv::CPPObjectToString(int type, const void* data) {
1022 QString r;
1022 QString r;
1023 switch (type) {
1023 switch (type) {
1024 case QVariant::Size: {
1024 case QVariant::Size: {
1025 const QSize* s = static_cast<const QSize*>(data);
1025 const QSize* s = static_cast<const QSize*>(data);
1026 r = QString::number(s->width()) + ", " + QString::number(s->height());
1026 r = QString::number(s->width()) + ", " + QString::number(s->height());
1027 }
1027 }
1028 break;
1028 break;
1029 case QVariant::SizeF: {
1029 case QVariant::SizeF: {
1030 const QSizeF* s = static_cast<const QSizeF*>(data);
1030 const QSizeF* s = static_cast<const QSizeF*>(data);
1031 r = QString::number(s->width()) + ", " + QString::number(s->height());
1031 r = QString::number(s->width()) + ", " + QString::number(s->height());
1032 }
1032 }
1033 break;
1033 break;
1034 case QVariant::Point: {
1034 case QVariant::Point: {
1035 const QPoint* s = static_cast<const QPoint*>(data);
1035 const QPoint* s = static_cast<const QPoint*>(data);
1036 r = QString::number(s->x()) + ", " + QString::number(s->y());
1036 r = QString::number(s->x()) + ", " + QString::number(s->y());
1037 }
1037 }
1038 break;
1038 break;
1039 case QVariant::PointF: {
1039 case QVariant::PointF: {
1040 const QPointF* s = static_cast<const QPointF*>(data);
1040 const QPointF* s = static_cast<const QPointF*>(data);
1041 r = QString::number(s->x()) + ", " + QString::number(s->y());
1041 r = QString::number(s->x()) + ", " + QString::number(s->y());
1042 }
1042 }
1043 break;
1043 break;
1044 case QVariant::Rect: {
1044 case QVariant::Rect: {
1045 const QRect* s = static_cast<const QRect*>(data);
1045 const QRect* s = static_cast<const QRect*>(data);
1046 r = QString::number(s->x()) + ", " + QString::number(s->y());
1046 r = QString::number(s->x()) + ", " + QString::number(s->y());
1047 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1047 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1048 }
1048 }
1049 break;
1049 break;
1050 case QVariant::RectF: {
1050 case QVariant::RectF: {
1051 const QRectF* s = static_cast<const QRectF*>(data);
1051 const QRectF* s = static_cast<const QRectF*>(data);
1052 r = QString::number(s->x()) + ", " + QString::number(s->y());
1052 r = QString::number(s->x()) + ", " + QString::number(s->y());
1053 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1053 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1054 }
1054 }
1055 break;
1055 break;
1056 case QVariant::Date: {
1056 case QVariant::Date: {
1057 const QDate* s = static_cast<const QDate*>(data);
1057 const QDate* s = static_cast<const QDate*>(data);
1058 r = s->toString(Qt::ISODate);
1058 r = s->toString(Qt::ISODate);
1059 }
1059 }
1060 break;
1060 break;
1061 case QVariant::DateTime: {
1061 case QVariant::DateTime: {
1062 const QDateTime* s = static_cast<const QDateTime*>(data);
1062 const QDateTime* s = static_cast<const QDateTime*>(data);
1063 r = s->toString(Qt::ISODate);
1063 r = s->toString(Qt::ISODate);
1064 }
1064 }
1065 break;
1065 break;
1066 case QVariant::Time: {
1066 case QVariant::Time: {
1067 const QTime* s = static_cast<const QTime*>(data);
1067 const QTime* s = static_cast<const QTime*>(data);
1068 r = s->toString(Qt::ISODate);
1068 r = s->toString(Qt::ISODate);
1069 }
1069 }
1070 break;
1070 break;
1071 case QVariant::Pixmap:
1071 case QVariant::Pixmap:
1072 {
1072 {
1073 const QPixmap* s = static_cast<const QPixmap*>(data);
1073 const QPixmap* s = static_cast<const QPixmap*>(data);
1074 r = QString("Pixmap ") + QString::number(s->width()) + ", " + QString::number(s->height());
1074 r = QString("Pixmap ") + QString::number(s->width()) + ", " + QString::number(s->height());
1075 }
1075 }
1076 break;
1076 break;
1077 case QVariant::Image:
1077 case QVariant::Image:
1078 {
1078 {
1079 const QImage* s = static_cast<const QImage*>(data);
1079 const QImage* s = static_cast<const QImage*>(data);
1080 r = QString("Image ") + QString::number(s->width()) + ", " + QString::number(s->height());
1080 r = QString("Image ") + QString::number(s->width()) + ", " + QString::number(s->height());
1081 }
1081 }
1082 break;
1082 break;
1083 case QVariant::Url:
1083 case QVariant::Url:
1084 {
1084 {
1085 const QUrl* s = static_cast<const QUrl*>(data);
1085 const QUrl* s = static_cast<const QUrl*>(data);
1086 r = s->toString();
1086 r = s->toString();
1087 }
1087 }
1088 break;
1088 break;
1089 //TODO: add more printing for other variant types
1089 //TODO: add more printing for other variant types
1090 default:
1090 default:
1091 // this creates a copy, but that should not be expensive for typical simple variants
1091 // this creates a copy, but that should not be expensive for typical simple variants
1092 // (but we do not want to do this for our won user types!
1092 // (but we do not want to do this for our won user types!
1093 if (type>0 && type < (int)QVariant::UserType) {
1093 if (type>0 && type < (int)QVariant::UserType) {
1094 QVariant v(type, data);
1094 QVariant v(type, data);
1095 r = v.toString();
1095 r = v.toString();
1096 }
1096 }
1097 }
1097 }
1098 return r;
1098 return r;
1099 }
1099 }
@@ -1,495 +1,498
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 if (returnValueParam.typeId != QMetaType::Void) {
83 // extra handling of enum return value
84 if (!returnValueParam.isPointer && returnValueParam.typeId == PythonQtMethodInfo::Unknown) {
85 returnValueIsEnum = PythonQtClassInfo::hasEnum(returnValueParam.name, classInfo);
86 if (returnValueIsEnum) {
87 // create enum return value
88 PythonQtValueStorage_ADD_VALUE(PythonQtConv::global_valueStorage, long, 0, argList[0]);
89 }
90 }
91 if (argList[0]==NULL) {
92 // create empty default value for the return value
93 if (!directReturnValuePointer) {
94 // create empty default value for the return value
95 argList[0] = PythonQtConv::CreateQtReturnValue(returnValueParam);
96 } else {
97 // we can use our pointer directly!
98 argList[0] = directReturnValuePointer;
99 }
100 }
101 }
102
103 bool ok = true;
82 bool ok = true;
104 bool skipFirst = false;
83 bool skipFirst = false;
105 if (info->isInstanceDecorator()) {
84 if (info->isInstanceDecorator()) {
106 skipFirst = true;
85 skipFirst = true;
107
86
108 // 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
109 void* arg1 = firstArgument;
88 void* arg1 = firstArgument;
110 if (!arg1) {
89 if (!arg1) {
111 arg1 = objectToCall;
90 arg1 = objectToCall;
112 }
91 }
113 if (arg1) {
92 if (arg1) {
114 // upcast to correct parent class
93 // upcast to correct parent class
115 arg1 = ((char*)arg1)+info->upcastingOffset();
94 arg1 = ((char*)arg1)+info->upcastingOffset();
116 }
95 }
117
96
118 argList[1] = &arg1;
97 argList[1] = &arg1;
119 if (ok) {
98 if (ok) {
120 for (int i = 2; i<argc && ok; i++) {
99 for (int i = 2; i<argc && ok; i++) {
121 const PythonQtSlotInfo::ParameterInfo& param = params.at(i);
100 const PythonQtSlotInfo::ParameterInfo& param = params.at(i);
122 //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;
123 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);
124 if (argList[i]==NULL) {
103 if (argList[i]==NULL) {
125 ok = false;
104 ok = false;
126 break;
105 break;
127 }
106 }
128 }
107 }
129 }
108 }
130 } else {
109 } else {
131 for (int i = 1; i<argc && ok; i++) {
110 for (int i = 1; i<argc && ok; i++) {
132 const PythonQtSlotInfo::ParameterInfo& param = params.at(i);
111 const PythonQtSlotInfo::ParameterInfo& param = params.at(i);
133 //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;
134 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);
135 if (argList[i]==NULL) {
114 if (argList[i]==NULL) {
136 ok = false;
115 ok = false;
137 break;
116 break;
138 }
117 }
139 }
118 }
140 }
119 }
141
120
142 if (ok) {
121 if (ok) {
122 // parameters are ok, now create the qt return value which is assigned to by metacall
123 if (returnValueParam.typeId != QMetaType::Void) {
124 // extra handling of enum return value
125 if (!returnValueParam.isPointer && returnValueParam.typeId == PythonQtMethodInfo::Unknown) {
126 returnValueIsEnum = PythonQtClassInfo::hasEnum(returnValueParam.name, classInfo);
127 if (returnValueIsEnum) {
128 // create enum return value
129 PythonQtValueStorage_ADD_VALUE(PythonQtConv::global_valueStorage, long, 0, argList[0]);
130 }
131 }
132 if (argList[0]==NULL) {
133 // create empty default value for the return value
134 if (!directReturnValuePointer) {
135 // create empty default value for the return value
136 argList[0] = PythonQtConv::CreateQtReturnValue(returnValueParam);
137 } else {
138 // we can use our pointer directly!
139 argList[0] = directReturnValuePointer;
140 }
141 }
142 }
143
144 // invoke the slot via metacall
143 (info->decorator()?info->decorator():objectToCall)->qt_metacall(QMetaObject::InvokeMetaMethod, info->slotIndex(), argList);
145 (info->decorator()?info->decorator():objectToCall)->qt_metacall(QMetaObject::InvokeMetaMethod, info->slotIndex(), argList);
144
146
147 // handle the return value (which in most cases still needs to be converted to a Python object)
145 if (argList[0] || returnValueParam.typeId == QMetaType::Void) {
148 if (argList[0] || returnValueParam.typeId == QMetaType::Void) {
146 if (directReturnValuePointer) {
149 if (directReturnValuePointer) {
147 result = NULL;
150 result = NULL;
148 } else {
151 } else {
149 if (!returnValueIsEnum) {
152 if (!returnValueIsEnum) {
150 result = PythonQtConv::ConvertQtValueToPython(returnValueParam, argList[0]);
153 result = PythonQtConv::ConvertQtValueToPython(returnValueParam, argList[0]);
151 } else {
154 } else {
152 result = PyInt_FromLong(*((unsigned int*)argList[0]));
155 result = PyInt_FromLong(*((unsigned int*)argList[0]));
153 }
156 }
154 }
157 }
155 } else {
158 } else {
156 QString e = QString("Called ") + info->fullSignature() + ", return type is ignored because it is unknown to PythonQt.";
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().";
157 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
160 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
158 result = NULL;
161 result = NULL;
159 }
162 }
160 }
163 }
161 recursiveEntry--;
164 recursiveEntry--;
162
165
163 // reset the parameter storage position to the stored pos to "pop" the parameter stack
166 // reset the parameter storage position to the stored pos to "pop" the parameter stack
164 PythonQtConv::global_valueStorage.setPos(globalValueStoragePos);
167 PythonQtConv::global_valueStorage.setPos(globalValueStoragePos);
165 PythonQtConv::global_ptrStorage.setPos(globalPtrStoragePos);
168 PythonQtConv::global_ptrStorage.setPos(globalPtrStoragePos);
166 PythonQtConv::global_variantStorage.setPos(globalVariantStoragePos);
169 PythonQtConv::global_variantStorage.setPos(globalVariantStoragePos);
167
170
168 *pythonReturnValue = result;
171 *pythonReturnValue = result;
169 // NOTE: it is important to only return here, otherwise the stack will not be popped!!!
172 // NOTE: it is important to only return here, otherwise the stack will not be popped!!!
170 return result || (directReturnValuePointer && *directReturnValuePointer);
173 return result || (directReturnValuePointer && *directReturnValuePointer);
171 }
174 }
172
175
173 //-----------------------------------------------------------------------------------
176 //-----------------------------------------------------------------------------------
174
177
175 static PythonQtSlotFunctionObject *pythonqtslot_free_list = NULL;
178 static PythonQtSlotFunctionObject *pythonqtslot_free_list = NULL;
176
179
177 PyObject *PythonQtSlotFunction_Call(PyObject *func, PyObject *args, PyObject *kw)
180 PyObject *PythonQtSlotFunction_Call(PyObject *func, PyObject *args, PyObject *kw)
178 {
181 {
179 PythonQtSlotFunctionObject* f = (PythonQtSlotFunctionObject*)func;
182 PythonQtSlotFunctionObject* f = (PythonQtSlotFunctionObject*)func;
180 PythonQtSlotInfo* info = f->m_ml;
183 PythonQtSlotInfo* info = f->m_ml;
181 if (PyObject_TypeCheck(f->m_self, &PythonQtInstanceWrapper_Type)) {
184 if (PyObject_TypeCheck(f->m_self, &PythonQtInstanceWrapper_Type)) {
182 PythonQtInstanceWrapper* self = (PythonQtInstanceWrapper*) f->m_self;
185 PythonQtInstanceWrapper* self = (PythonQtInstanceWrapper*) f->m_self;
183 return PythonQtSlotFunction_CallImpl(self->classInfo(), self->_obj, info, args, kw, self->_wrappedPtr);
186 return PythonQtSlotFunction_CallImpl(self->classInfo(), self->_obj, info, args, kw, self->_wrappedPtr);
184 } else if (f->m_self->ob_type == &PythonQtClassWrapper_Type) {
187 } else if (f->m_self->ob_type == &PythonQtClassWrapper_Type) {
185 PythonQtClassWrapper* type = (PythonQtClassWrapper*) f->m_self;
188 PythonQtClassWrapper* type = (PythonQtClassWrapper*) f->m_self;
186 if (info->isClassDecorator()) {
189 if (info->isClassDecorator()) {
187 return PythonQtSlotFunction_CallImpl(type->classInfo(), NULL, info, args, kw);
190 return PythonQtSlotFunction_CallImpl(type->classInfo(), NULL, info, args, kw);
188 } else {
191 } else {
189 // otherwise, it is an unbound call and we have an instanceDecorator or normal slot...
192 // otherwise, it is an unbound call and we have an instanceDecorator or normal slot...
190 Py_ssize_t argc = PyTuple_Size(args);
193 Py_ssize_t argc = PyTuple_Size(args);
191 if (argc>0) {
194 if (argc>0) {
192 PyObject* firstArg = PyTuple_GET_ITEM(args, 0);
195 PyObject* firstArg = PyTuple_GET_ITEM(args, 0);
193 if (PyObject_TypeCheck(firstArg, (PyTypeObject*)&PythonQtInstanceWrapper_Type)
196 if (PyObject_TypeCheck(firstArg, (PyTypeObject*)&PythonQtInstanceWrapper_Type)
194 && ((PythonQtInstanceWrapper*)firstArg)->classInfo()->inherits(type->classInfo())) {
197 && ((PythonQtInstanceWrapper*)firstArg)->classInfo()->inherits(type->classInfo())) {
195 PythonQtInstanceWrapper* self = (PythonQtInstanceWrapper*)firstArg;
198 PythonQtInstanceWrapper* self = (PythonQtInstanceWrapper*)firstArg;
196 // strip the first argument...
199 // strip the first argument...
197 PyObject* newargs = PyTuple_GetSlice(args, 1, argc);
200 PyObject* newargs = PyTuple_GetSlice(args, 1, argc);
198 PyObject* result = PythonQtSlotFunction_CallImpl(self->classInfo(), self->_obj, info, newargs, kw, self->_wrappedPtr);
201 PyObject* result = PythonQtSlotFunction_CallImpl(self->classInfo(), self->_obj, info, newargs, kw, self->_wrappedPtr);
199 Py_DECREF(newargs);
202 Py_DECREF(newargs);
200 return result;
203 return result;
201 } else {
204 } else {
202 // first arg is not of correct type!
205 // first arg is not of correct type!
203 QString error = "slot " + info->fullSignature() + " requires " + type->classInfo()->className() + " instance as first argument, got " + firstArg->ob_type->tp_name;
206 QString error = "slot " + info->fullSignature() + " requires " + type->classInfo()->className() + " instance as first argument, got " + firstArg->ob_type->tp_name;
204 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
207 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
205 return NULL;
208 return NULL;
206 }
209 }
207 } else {
210 } else {
208 // wrong number of args
211 // wrong number of args
209 QString error = "slot " + info->fullSignature() + " requires " + type->classInfo()->className() + " instance as first argument.";
212 QString error = "slot " + info->fullSignature() + " requires " + type->classInfo()->className() + " instance as first argument.";
210 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
213 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
211 return NULL;
214 return NULL;
212 }
215 }
213 }
216 }
214 }
217 }
215 return NULL;
218 return NULL;
216 }
219 }
217
220
218 PyObject *PythonQtSlotFunction_CallImpl(PythonQtClassInfo* classInfo, QObject* objectToCall, PythonQtSlotInfo* info, PyObject *args, PyObject * /*kw*/, void* firstArg, void** directReturnValuePointer)
221 PyObject *PythonQtSlotFunction_CallImpl(PythonQtClassInfo* classInfo, QObject* objectToCall, PythonQtSlotInfo* info, PyObject *args, PyObject * /*kw*/, void* firstArg, void** directReturnValuePointer)
219 {
222 {
220 int argc = PyTuple_Size(args);
223 int argc = PyTuple_Size(args);
221
224
222 #ifdef PYTHONQT_DEBUG
225 #ifdef PYTHONQT_DEBUG
223 std::cout << "called " << info->metaMethod()->typeName() << " " << info->metaMethod()->signature() << std::endl;
226 std::cout << "called " << info->metaMethod()->typeName() << " " << info->metaMethod()->signature() << std::endl;
224 #endif
227 #endif
225
228
226 PyObject* r = NULL;
229 PyObject* r = NULL;
227 bool ok = false;
230 bool ok = false;
228 if (directReturnValuePointer) {
231 if (directReturnValuePointer) {
229 *directReturnValuePointer = NULL;
232 *directReturnValuePointer = NULL;
230 }
233 }
231 if (info->nextInfo()) {
234 if (info->nextInfo()) {
232 // overloaded slot call, try on all slots with strict conversion first
235 // overloaded slot call, try on all slots with strict conversion first
233 bool strict = true;
236 bool strict = true;
234 PythonQtSlotInfo* i = info;
237 PythonQtSlotInfo* i = info;
235 while (i) {
238 while (i) {
236 bool skipFirst = i->isInstanceDecorator();
239 bool skipFirst = i->isInstanceDecorator();
237 if (i->parameterCount()-1-(skipFirst?1:0) == argc) {
240 if (i->parameterCount()-1-(skipFirst?1:0) == argc) {
238 PyErr_Clear();
241 PyErr_Clear();
239 ok = PythonQtCallSlot(classInfo, objectToCall, args, strict, i, firstArg, &r, directReturnValuePointer);
242 ok = PythonQtCallSlot(classInfo, objectToCall, args, strict, i, firstArg, &r, directReturnValuePointer);
240 if (PyErr_Occurred() || ok) break;
243 if (PyErr_Occurred() || ok) break;
241 }
244 }
242 i = i->nextInfo();
245 i = i->nextInfo();
243 if (!i) {
246 if (!i) {
244 if (strict) {
247 if (strict) {
245 // one more run without being strict
248 // one more run without being strict
246 strict = false;
249 strict = false;
247 i = info;
250 i = info;
248 }
251 }
249 }
252 }
250 }
253 }
251 if (!ok && !PyErr_Occurred()) {
254 if (!ok && !PyErr_Occurred()) {
252 QString e = QString("Could not find matching overload for given arguments:\n" + PythonQtConv::PyObjGetString(args) + "\n The following slots are available:\n");
255 QString e = QString("Could not find matching overload for given arguments:\n" + PythonQtConv::PyObjGetString(args) + "\n The following slots are available:\n");
253 PythonQtSlotInfo* i = info;
256 PythonQtSlotInfo* i = info;
254 while (i) {
257 while (i) {
255 e += QString(i->fullSignature()) + "\n";
258 e += QString(i->fullSignature()) + "\n";
256 i = i->nextInfo();
259 i = i->nextInfo();
257 }
260 }
258 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
261 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
259 }
262 }
260 } else {
263 } else {
261 // simple (non-overloaded) slot call
264 // simple (non-overloaded) slot call
262 bool skipFirst = info->isInstanceDecorator();
265 bool skipFirst = info->isInstanceDecorator();
263 if (info->parameterCount()-1-(skipFirst?1:0) == argc) {
266 if (info->parameterCount()-1-(skipFirst?1:0) == argc) {
264 PyErr_Clear();
267 PyErr_Clear();
265 ok = PythonQtCallSlot(classInfo, objectToCall, args, false, info, firstArg, &r, directReturnValuePointer);
268 ok = PythonQtCallSlot(classInfo, objectToCall, args, false, info, firstArg, &r, directReturnValuePointer);
266 if (!ok && !PyErr_Occurred()) {
269 if (!ok && !PyErr_Occurred()) {
267 QString e = QString("Called ") + info->fullSignature() + " with wrong arguments: " + PythonQtConv::PyObjGetString(args);
270 QString e = QString("Called ") + info->fullSignature() + " with wrong arguments: " + PythonQtConv::PyObjGetString(args);
268 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
271 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
269 }
272 }
270 } else {
273 } else {
271 QString e = QString("Called ") + info->fullSignature() + " with wrong number of arguments: " + PythonQtConv::PyObjGetString(args);
274 QString e = QString("Called ") + info->fullSignature() + " with wrong number of arguments: " + PythonQtConv::PyObjGetString(args);
272 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
275 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
273 }
276 }
274 }
277 }
275
278
276 return r;
279 return r;
277 }
280 }
278
281
279 PyObject *
282 PyObject *
280 PythonQtSlotFunction_New(PythonQtSlotInfo *ml, PyObject *self, PyObject *module)
283 PythonQtSlotFunction_New(PythonQtSlotInfo *ml, PyObject *self, PyObject *module)
281 {
284 {
282 PythonQtSlotFunctionObject *op;
285 PythonQtSlotFunctionObject *op;
283 op = pythonqtslot_free_list;
286 op = pythonqtslot_free_list;
284 if (op != NULL) {
287 if (op != NULL) {
285 pythonqtslot_free_list = (PythonQtSlotFunctionObject *)(op->m_self);
288 pythonqtslot_free_list = (PythonQtSlotFunctionObject *)(op->m_self);
286 PyObject_INIT(op, &PythonQtSlotFunction_Type);
289 PyObject_INIT(op, &PythonQtSlotFunction_Type);
287 }
290 }
288 else {
291 else {
289 op = PyObject_GC_New(PythonQtSlotFunctionObject, &PythonQtSlotFunction_Type);
292 op = PyObject_GC_New(PythonQtSlotFunctionObject, &PythonQtSlotFunction_Type);
290 if (op == NULL)
293 if (op == NULL)
291 return NULL;
294 return NULL;
292 }
295 }
293 op->m_ml = ml;
296 op->m_ml = ml;
294 Py_XINCREF(self);
297 Py_XINCREF(self);
295 op->m_self = self;
298 op->m_self = self;
296 Py_XINCREF(module);
299 Py_XINCREF(module);
297 op->m_module = module;
300 op->m_module = module;
298 PyObject_GC_Track(op);
301 PyObject_GC_Track(op);
299 return (PyObject *)op;
302 return (PyObject *)op;
300 }
303 }
301
304
302 PythonQtSlotInfo*
305 PythonQtSlotInfo*
303 PythonQtSlotFunction_GetSlotInfo(PyObject *op)
306 PythonQtSlotFunction_GetSlotInfo(PyObject *op)
304 {
307 {
305 if (!PythonQtSlotFunction_Check(op)) {
308 if (!PythonQtSlotFunction_Check(op)) {
306 PyErr_BadInternalCall();
309 PyErr_BadInternalCall();
307 return NULL;
310 return NULL;
308 }
311 }
309 return ((PythonQtSlotFunctionObject *)op) -> m_ml;
312 return ((PythonQtSlotFunctionObject *)op) -> m_ml;
310 }
313 }
311
314
312 PyObject *
315 PyObject *
313 PythonQtSlotFunction_GetSelf(PyObject *op)
316 PythonQtSlotFunction_GetSelf(PyObject *op)
314 {
317 {
315 if (!PythonQtSlotFunction_Check(op)) {
318 if (!PythonQtSlotFunction_Check(op)) {
316 PyErr_BadInternalCall();
319 PyErr_BadInternalCall();
317 return NULL;
320 return NULL;
318 }
321 }
319 return ((PythonQtSlotFunctionObject *)op) -> m_self;
322 return ((PythonQtSlotFunctionObject *)op) -> m_self;
320 }
323 }
321
324
322 /* Methods (the standard built-in methods, that is) */
325 /* Methods (the standard built-in methods, that is) */
323
326
324 static void
327 static void
325 meth_dealloc(PythonQtSlotFunctionObject *m)
328 meth_dealloc(PythonQtSlotFunctionObject *m)
326 {
329 {
327 PyObject_GC_UnTrack(m);
330 PyObject_GC_UnTrack(m);
328 Py_XDECREF(m->m_self);
331 Py_XDECREF(m->m_self);
329 Py_XDECREF(m->m_module);
332 Py_XDECREF(m->m_module);
330 m->m_self = (PyObject *)pythonqtslot_free_list;
333 m->m_self = (PyObject *)pythonqtslot_free_list;
331 pythonqtslot_free_list = m;
334 pythonqtslot_free_list = m;
332 }
335 }
333
336
334 static PyObject *
337 static PyObject *
335 meth_get__doc__(PythonQtSlotFunctionObject * /*m*/, void * /*closure*/)
338 meth_get__doc__(PythonQtSlotFunctionObject * /*m*/, void * /*closure*/)
336 {
339 {
337 Py_INCREF(Py_None);
340 Py_INCREF(Py_None);
338 return Py_None;
341 return Py_None;
339 }
342 }
340
343
341 static PyObject *
344 static PyObject *
342 meth_get__name__(PythonQtSlotFunctionObject *m, void * /*closure*/)
345 meth_get__name__(PythonQtSlotFunctionObject *m, void * /*closure*/)
343 {
346 {
344 return PyString_FromString(m->m_ml->metaMethod()->signature());
347 return PyString_FromString(m->m_ml->metaMethod()->signature());
345 }
348 }
346
349
347 static int
350 static int
348 meth_traverse(PythonQtSlotFunctionObject *m, visitproc visit, void *arg)
351 meth_traverse(PythonQtSlotFunctionObject *m, visitproc visit, void *arg)
349 {
352 {
350 int err;
353 int err;
351 if (m->m_self != NULL) {
354 if (m->m_self != NULL) {
352 err = visit(m->m_self, arg);
355 err = visit(m->m_self, arg);
353 if (err)
356 if (err)
354 return err;
357 return err;
355 }
358 }
356 if (m->m_module != NULL) {
359 if (m->m_module != NULL) {
357 err = visit(m->m_module, arg);
360 err = visit(m->m_module, arg);
358 if (err)
361 if (err)
359 return err;
362 return err;
360 }
363 }
361 return 0;
364 return 0;
362 }
365 }
363
366
364 static PyObject *
367 static PyObject *
365 meth_get__self__(PythonQtSlotFunctionObject *m, void * /*closure*/)
368 meth_get__self__(PythonQtSlotFunctionObject *m, void * /*closure*/)
366 {
369 {
367 PyObject *self;
370 PyObject *self;
368 if (PyEval_GetRestricted()) {
371 if (PyEval_GetRestricted()) {
369 PyErr_SetString(PyExc_RuntimeError,
372 PyErr_SetString(PyExc_RuntimeError,
370 "method.__self__ not accessible in restricted mode");
373 "method.__self__ not accessible in restricted mode");
371 return NULL;
374 return NULL;
372 }
375 }
373 self = m->m_self;
376 self = m->m_self;
374 if (self == NULL)
377 if (self == NULL)
375 self = Py_None;
378 self = Py_None;
376 Py_INCREF(self);
379 Py_INCREF(self);
377 return self;
380 return self;
378 }
381 }
379
382
380 static PyGetSetDef meth_getsets [] = {
383 static PyGetSetDef meth_getsets [] = {
381 {"__doc__", (getter)meth_get__doc__, NULL, NULL},
384 {"__doc__", (getter)meth_get__doc__, NULL, NULL},
382 {"__name__", (getter)meth_get__name__, NULL, NULL},
385 {"__name__", (getter)meth_get__name__, NULL, NULL},
383 {"__self__", (getter)meth_get__self__, NULL, NULL},
386 {"__self__", (getter)meth_get__self__, NULL, NULL},
384 {NULL, NULL, NULL,NULL},
387 {NULL, NULL, NULL,NULL},
385 };
388 };
386
389
387 #if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 6
390 #if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 6
388 #define PY_WRITE_RESTRICTED WRITE_RESTRICTED
391 #define PY_WRITE_RESTRICTED WRITE_RESTRICTED
389 #endif
392 #endif
390
393
391 #define OFF(x) offsetof(PythonQtSlotFunctionObject, x)
394 #define OFF(x) offsetof(PythonQtSlotFunctionObject, x)
392
395
393 static PyMemberDef meth_members[] = {
396 static PyMemberDef meth_members[] = {
394 {"__module__", T_OBJECT, OFF(m_module), PY_WRITE_RESTRICTED},
397 {"__module__", T_OBJECT, OFF(m_module), PY_WRITE_RESTRICTED},
395 {NULL}
398 {NULL}
396 };
399 };
397
400
398 static PyObject *
401 static PyObject *
399 meth_repr(PythonQtSlotFunctionObject *f)
402 meth_repr(PythonQtSlotFunctionObject *f)
400 {
403 {
401 if (f->m_self->ob_type == &PythonQtClassWrapper_Type) {
404 if (f->m_self->ob_type == &PythonQtClassWrapper_Type) {
402 PythonQtClassWrapper* self = (PythonQtClassWrapper*) f->m_self;
405 PythonQtClassWrapper* self = (PythonQtClassWrapper*) f->m_self;
403 return PyString_FromFormat("<unbound qt slot %s of %s type>",
406 return PyString_FromFormat("<unbound qt slot %s of %s type>",
404 f->m_ml->slotName().data(),
407 f->m_ml->slotName().data(),
405 self->classInfo()->className());
408 self->classInfo()->className());
406 } else {
409 } else {
407 return PyString_FromFormat("<qt slot %s of %s instance at %p>",
410 return PyString_FromFormat("<qt slot %s of %s instance at %p>",
408 f->m_ml->slotName().data(),
411 f->m_ml->slotName().data(),
409 f->m_self->ob_type->tp_name,
412 f->m_self->ob_type->tp_name,
410 f->m_self);
413 f->m_self);
411 }
414 }
412 }
415 }
413
416
414 static int
417 static int
415 meth_compare(PythonQtSlotFunctionObject *a, PythonQtSlotFunctionObject *b)
418 meth_compare(PythonQtSlotFunctionObject *a, PythonQtSlotFunctionObject *b)
416 {
419 {
417 if (a->m_self != b->m_self)
420 if (a->m_self != b->m_self)
418 return (a->m_self < b->m_self) ? -1 : 1;
421 return (a->m_self < b->m_self) ? -1 : 1;
419 if (a->m_ml == b->m_ml)
422 if (a->m_ml == b->m_ml)
420 return 0;
423 return 0;
421 if (strcmp(a->m_ml->metaMethod()->signature(), b->m_ml->metaMethod()->signature()) < 0)
424 if (strcmp(a->m_ml->metaMethod()->signature(), b->m_ml->metaMethod()->signature()) < 0)
422 return -1;
425 return -1;
423 else
426 else
424 return 1;
427 return 1;
425 }
428 }
426
429
427 static long
430 static long
428 meth_hash(PythonQtSlotFunctionObject *a)
431 meth_hash(PythonQtSlotFunctionObject *a)
429 {
432 {
430 long x,y;
433 long x,y;
431 if (a->m_self == NULL)
434 if (a->m_self == NULL)
432 x = 0;
435 x = 0;
433 else {
436 else {
434 x = PyObject_Hash(a->m_self);
437 x = PyObject_Hash(a->m_self);
435 if (x == -1)
438 if (x == -1)
436 return -1;
439 return -1;
437 }
440 }
438 y = _Py_HashPointer((void*)(a->m_ml));
441 y = _Py_HashPointer((void*)(a->m_ml));
439 if (y == -1)
442 if (y == -1)
440 return -1;
443 return -1;
441 x ^= y;
444 x ^= y;
442 if (x == -1)
445 if (x == -1)
443 x = -2;
446 x = -2;
444 return x;
447 return x;
445 }
448 }
446
449
447
450
448 PyTypeObject PythonQtSlotFunction_Type = {
451 PyTypeObject PythonQtSlotFunction_Type = {
449 PyObject_HEAD_INIT(&PyType_Type)
452 PyObject_HEAD_INIT(&PyType_Type)
450 0,
453 0,
451 "builtin_qt_slot",
454 "builtin_qt_slot",
452 sizeof(PythonQtSlotFunctionObject),
455 sizeof(PythonQtSlotFunctionObject),
453 0,
456 0,
454 (destructor)meth_dealloc, /* tp_dealloc */
457 (destructor)meth_dealloc, /* tp_dealloc */
455 0, /* tp_print */
458 0, /* tp_print */
456 0, /* tp_getattr */
459 0, /* tp_getattr */
457 0, /* tp_setattr */
460 0, /* tp_setattr */
458 (cmpfunc)meth_compare, /* tp_compare */
461 (cmpfunc)meth_compare, /* tp_compare */
459 (reprfunc)meth_repr, /* tp_repr */
462 (reprfunc)meth_repr, /* tp_repr */
460 0, /* tp_as_number */
463 0, /* tp_as_number */
461 0, /* tp_as_sequence */
464 0, /* tp_as_sequence */
462 0, /* tp_as_mapping */
465 0, /* tp_as_mapping */
463 (hashfunc)meth_hash, /* tp_hash */
466 (hashfunc)meth_hash, /* tp_hash */
464 PythonQtSlotFunction_Call, /* tp_call */
467 PythonQtSlotFunction_Call, /* tp_call */
465 0, /* tp_str */
468 0, /* tp_str */
466 PyObject_GenericGetAttr, /* tp_getattro */
469 PyObject_GenericGetAttr, /* tp_getattro */
467 0, /* tp_setattro */
470 0, /* tp_setattro */
468 0, /* tp_as_buffer */
471 0, /* tp_as_buffer */
469 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
472 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
470 0, /* tp_doc */
473 0, /* tp_doc */
471 (traverseproc)meth_traverse, /* tp_traverse */
474 (traverseproc)meth_traverse, /* tp_traverse */
472 0, /* tp_clear */
475 0, /* tp_clear */
473 0, /* tp_richcompare */
476 0, /* tp_richcompare */
474 0, /* tp_weaklistoffset */
477 0, /* tp_weaklistoffset */
475 0, /* tp_iter */
478 0, /* tp_iter */
476 0, /* tp_iternext */
479 0, /* tp_iternext */
477 0, /* tp_methods */
480 0, /* tp_methods */
478 meth_members, /* tp_members */
481 meth_members, /* tp_members */
479 meth_getsets, /* tp_getset */
482 meth_getsets, /* tp_getset */
480 0, /* tp_base */
483 0, /* tp_base */
481 0, /* tp_dict */
484 0, /* tp_dict */
482 };
485 };
483
486
484 /* Clear out the free list */
487 /* Clear out the free list */
485
488
486 void
489 void
487 PythonQtSlotFunction_Fini(void)
490 PythonQtSlotFunction_Fini(void)
488 {
491 {
489 while (pythonqtslot_free_list) {
492 while (pythonqtslot_free_list) {
490 PythonQtSlotFunctionObject *v = pythonqtslot_free_list;
493 PythonQtSlotFunctionObject *v = pythonqtslot_free_list;
491 pythonqtslot_free_list = (PythonQtSlotFunctionObject *)(v->m_self);
494 pythonqtslot_free_list = (PythonQtSlotFunctionObject *)(v->m_self);
492 PyObject_GC_Del(v);
495 PyObject_GC_Del(v);
493 }
496 }
494 }
497 }
495
498
General Comments 0
You need to be logged in to leave comments. Login now