##// END OF EJS Templates
improved code generation for virtual functions to support overriding getter slots that are named as properties...
florianlink -
r199:1f55453df6ee
parent child
Show More
@@ -1,330 +1,332
1 1 /****************************************************************************
2 2 **
3 3 ** Copyright (C) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
4 4 ** All rights reserved.
5 5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 6 **
7 7 ** This file is part of the Qt Script Generator project on Qt Labs.
8 8 **
9 9 ** $QT_BEGIN_LICENSE:LGPL$
10 10 ** No Commercial Usage
11 11 ** This file contains pre-release code and may not be distributed.
12 12 ** You may use this file in accordance with the terms and conditions
13 13 ** contained in the Technology Preview License Agreement accompanying
14 14 ** this package.
15 15 **
16 16 ** GNU Lesser General Public License Usage
17 17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 18 ** General Public License version 2.1 as published by the Free Software
19 19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 20 ** packaging of this file. Please review the following information to
21 21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23 23 **
24 24 ** In addition, as a special exception, Nokia gives you certain additional
25 25 ** rights. These rights are described in the Nokia Qt LGPL Exception
26 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27 27 **
28 28 ** If you have questions regarding the use of this file, please contact
29 29 ** Nokia at qt-info@nokia.com.
30 30 **
31 31 **
32 32 **
33 33 **
34 34 **
35 35 **
36 36 **
37 37 **
38 38 ** $QT_END_LICENSE$
39 39 **
40 40 ****************************************************************************/
41 41
42 42 #include "shellimplgenerator.h"
43 43 #include "reporthandler.h"
44 44 #include "fileout.h"
45 45 #include <iostream>
46 46
47 47 extern void declareFunctionMetaTypes(QTextStream &stream,
48 48 const AbstractMetaFunctionList &functions,
49 49 QSet<QString> &registeredTypeNames);
50 50
51 51 QString ShellImplGenerator::fileNameForClass(const AbstractMetaClass *meta_class) const
52 52 {
53 53 return QString("PythonQtWrapper_%1.cpp").arg(meta_class->name());
54 54 }
55 55
56 56 static bool include_less_than(const Include &a, const Include &b)
57 57 {
58 58 return a.name < b.name;
59 59 }
60 60
61 61 static void writeHelperCode(QTextStream &s, const AbstractMetaClass *)
62 62 {
63 63 }
64 64
65 65
66 66
67 67 void ShellImplGenerator::write(QTextStream &s, const AbstractMetaClass *meta_class)
68 68 {
69 69 QString builtIn = ShellGenerator::isBuiltIn(meta_class->name())?"_builtin":"";
70 70 QString pro_file_name = meta_class->package().replace(".", "_") + builtIn + "/" + meta_class->package().replace(".", "_") + builtIn + ".pri";
71 71 priGenerator->addSource(pro_file_name, fileNameForClass(meta_class));
72 72
73 73 s << "#include \"PythonQtWrapper_" << meta_class->name() << ".h\"" << endl << endl;
74 74
75 75 s << "#include <PythonQtSignalReceiver.h>" << endl;
76 76 s << "#include <PythonQtMethodInfo.h>" << endl;
77 77 s << "#include <PythonQtConversion.h>" << endl;
78 78
79 79 //if (!meta_class->generateShellClass())
80 80 // return;
81 81
82 82 IncludeList list = meta_class->typeEntry()->extraIncludes();
83 83 qSort(list.begin(), list.end());
84 84 foreach (const Include &inc, list) {
85 85 ShellGenerator::writeInclude(s, inc);
86 86 }
87 87 s << endl;
88 88
89 89 writeHelperCode(s, meta_class);
90 90
91 91 // find constructors
92 92 AbstractMetaFunctionList ctors;
93 93 ctors = meta_class->queryFunctions(AbstractMetaClass::Constructors
94 94 | AbstractMetaClass::WasVisible
95 95 | AbstractMetaClass::NotRemovedFromTargetLang);
96 96 // find member functions
97 97 AbstractMetaFunctionList functions = getFunctionsToWrap(meta_class);
98 98
99 99 // write metatype declarations
100 100 {
101 101 // QSet<QString> registeredTypeNames = m_qmetatype_declared_typenames;
102 102 // declareFunctionMetaTypes(s, functions, registeredTypeNames);
103 103 // s << endl;
104 104 }
105 105 if (meta_class->qualifiedCppName().contains("Ssl")) {
106 106 s << "#ifndef QT_NO_OPENSSL" << endl;
107 107 }
108 108
109 109 if (meta_class->generateShellClass()) {
110 110
111 111 s << shellClassName(meta_class) << "::~" << shellClassName(meta_class) << "() {" << endl;
112 112 s << " PythonQtPrivate* priv = PythonQt::priv();" << endl;
113 113 s << " if (priv) { priv->shellClassDeleted(this); }" << endl;
114 114 s << "}" << endl;
115 115
116 116 AbstractMetaFunctionList virtualsForShell = getVirtualFunctionsForShell(meta_class);
117 117 foreach (const AbstractMetaFunction *fun, virtualsForShell) {
118 118 bool hasReturnValue = (fun->type());
119 119 writeFunctionSignature(s, fun, meta_class, QString(),
120 120 Option(OriginalName | ShowStatic | UnderscoreSpaces),
121 121 "PythonQtShell_");
122 122 s << endl << "{" << endl;
123 123
124 124 Option typeOptions = Option(OriginalName | UnderscoreSpaces | SkipName);
125 125 AbstractMetaArgumentList args = fun->arguments();
126 126
127 127 s << "if (_wrapper) {" << endl;
128 s << " PyObject* obj = PyObject_GetAttrString((PyObject*)_wrapper, \"" << fun->name() << "\");" << endl;
129 s << " PyErr_Clear();" << endl;
130 s << " if (obj && !PythonQtSlotFunction_Check(obj)) {" << endl;
128 s << " static PyObject* name = PyString_FromString(\"" << fun->name() << "\");" << endl;
129 s << " PyObject* obj = PyBaseObject_Type.tp_getattro((PyObject*)_wrapper, name);" << endl;
130 s << " if (obj) {" << endl;
131 131 s << " static const char* argumentList[] ={\"";
132 132 if (hasReturnValue) {
133 133 // write the arguments, return type first
134 134 writeTypeInfo(s, fun->type(), typeOptions);
135 135 }
136 136 s << "\"";
137 137 for (int i = 0; i < args.size(); ++i) {
138 138 s << " , \"";
139 139 writeTypeInfo(s, args.at(i)->type(), typeOptions);
140 140 s << "\"";
141 141 }
142 142 s << "};" << endl;
143 143 s << " static const PythonQtMethodInfo* methodInfo = PythonQtMethodInfo::getCachedMethodInfoFromArgumentList(" << QString::number(args.size()+1) << ", argumentList);" << endl;
144 144
145 145 if (hasReturnValue) {
146 146 s << " ";
147 147 writeTypeInfo(s, fun->type(), typeOptions);
148 148 s << " returnValue;" << endl;
149 149 // TODO: POD init to default is missing...
150 150 }
151 151 s << " void* args[" << QString::number(args.size()+1) << "] = {NULL";
152 152 for (int i = 0; i < args.size(); ++i) {
153 153 s << ", (void*)&" << args.at(i)->argumentName();
154 154 }
155 155 s << "};" << endl;
156 156
157 157 s << " PyObject* result = PythonQtSignalTarget::call(obj, methodInfo, args, true);" << endl;
158 158 if (hasReturnValue) {
159 159 s << " if (result) {" << endl;
160 160 s << " args[0] = PythonQtConv::ConvertPythonToQt(methodInfo->parameters().at(0), result, false, NULL, &returnValue);" << endl;
161 161 s << " if (args[0]!=&returnValue) {" << endl;
162 162 s << " if (args[0]==NULL) {" << endl;
163 163 s << " PythonQt::priv()->handleVirtualOverloadReturnError(\"" << fun->name() << "\", methodInfo, result);" << endl;
164 164 s << " } else {" << endl;
165 165 s << " returnValue = *((";
166 166 writeTypeInfo(s, fun->type(), typeOptions);
167 167 s << "*)args[0]);" << endl;
168 168 s << " }" << endl;
169 169 s << " }" << endl;
170 170 s << " }" << endl;
171 171 }
172 172 s << " if (result) { Py_DECREF(result); } " << endl;
173 173 s << " Py_DECREF(obj);" << endl;
174 174 if (hasReturnValue) {
175 175 s << " return returnValue;" << endl;
176 176 } else {
177 177 s << " return;" << endl;
178 178 }
179 s << " } else {" << endl;
180 s << " PyErr_Clear();" << endl;
179 181 s << " }" << endl;
180 182 s << "}" << endl;
181 183
182 184 s << " ";
183 185 if (fun->isAbstract()) {
184 186 if (fun->type()) {
185 187 // return empty default object
186 188 s << "return ";
187 189 if (fun->type()->indirections()>0) {
188 190 s << "0;";
189 191 } else {
190 192 writeTypeInfo(s, fun->type(), typeOptions);
191 193 s << "();";
192 194 }
193 195 }
194 196 } else {
195 197 if (fun->type()) {
196 198 s << "return ";
197 199 }
198 200 s << meta_class->qualifiedCppName() << "::";
199 201 s << fun->originalName() << "(";
200 202 for (int i = 0; i < args.size(); ++i) {
201 203 if (i > 0)
202 204 s << ", ";
203 205 s << args.at(i)->argumentName();
204 206 }
205 207 s << ");";
206 208 }
207 209 s << endl << "}" << endl;
208 210 }
209 211 }
210 212
211 213 if (meta_class->generateShellClass() || !meta_class->isAbstract()) {
212 214
213 215 // write constructors
214 216 foreach (const AbstractMetaFunction *ctor, ctors) {
215 217 if (!ctor->isPublic() || ctor->isAbstract()) { continue; }
216 218
217 219 s << meta_class->qualifiedCppName() << "* ";
218 220 s << "PythonQtWrapper_" << meta_class->name() << "::";
219 221 writeFunctionSignature(s, ctor, 0, "new_", Option(OriginalName | ShowStatic));
220 222 s << endl;
221 223 s << "{ " << endl;
222 224 s << "return new " << (meta_class->generateShellClass()?shellClassName(meta_class):meta_class->qualifiedCppName()) << "(";
223 225 AbstractMetaArgumentList args = ctor->arguments();
224 226 for (int i = 0; i < args.size(); ++i) {
225 227 if (i > 0)
226 228 s << ", ";
227 229 s << args.at(i)->argumentName();
228 230 }
229 231 s << ");" << " }" << endl << endl;
230 232 }
231 233 }
232 234
233 235 QString wrappedObject = " (*theWrappedObject)";
234 236
235 237 // write member functions
236 238 for (int i = 0; i < functions.size(); ++i) {
237 239 AbstractMetaFunction *fun = functions.at(i);
238 240 bool needsWrapping = (!fun->isSlot() || fun->isVirtual());
239 241 if (!needsWrapping) {
240 242 continue;
241 243 }
242 244 writeFunctionSignature(s, fun, meta_class, QString(),
243 245 Option(ConvertReferenceToPtr | FirstArgIsWrappedObject | OriginalName | ShowStatic | UnderscoreSpaces),
244 246 "PythonQtWrapper_");
245 247 s << endl << "{" << endl;
246 248 s << " ";
247 249 if (ShellGenerator::isSpecialStreamingOperator(fun)) {
248 250 s << fun->arguments().at(0)->argumentName();
249 251 if (fun->originalName().startsWith("operator>>")) {
250 252 s << " >> ";
251 253 } else {
252 254 s << " << ";
253 255 }
254 256 s << wrappedObject;
255 257 } else {
256 258 QString scriptFunctionName = fun->originalName();
257 259 AbstractMetaArgumentList args = fun->arguments();
258 260 // call the C++ implementation
259 261 if (fun->type()) {
260 262 s << "return ";
261 263 // call the C++ implementation
262 264 if (fun->type()->isReference()) {
263 265 s << "&";
264 266 }
265 267 }
266 268 s << "(";
267 269 if (scriptFunctionName.startsWith("operator>>")) {
268 270 s << wrappedObject << " >>" << args.at(0)->argumentName();
269 271 } else if (scriptFunctionName.startsWith("operator<<")) {
270 272 s << wrappedObject << " <<" << args.at(0)->argumentName();
271 273 } else if (scriptFunctionName.startsWith("operator[]")) {
272 274 s << wrappedObject << "[" << args.at(0)->argumentName() << "]";
273 275 } else if (scriptFunctionName.startsWith("operator") && args.size()==1) {
274 276 QString op = scriptFunctionName.mid(8);
275 277 s << wrappedObject << op << " " << args.at(0)->argumentName();
276 278 } else {
277 279 if (fun->isStatic()) {
278 280 s << meta_class->qualifiedCppName() << "::";
279 281 } else {
280 282 if (!fun->isPublic() || fun->isVirtual()) {
281 283 s << " ((" << promoterClassName(meta_class) << "*)theWrappedObject)->promoted_";
282 284 } else {
283 285 s << " theWrappedObject->";
284 286 }
285 287 }
286 288 s << fun->originalName() << "(";
287 289 for (int i = 0; i < args.size(); ++i) {
288 290 if (i > 0)
289 291 s << ", ";
290 292 s << args.at(i)->argumentName();
291 293 }
292 294 s << ")";
293 295 }
294 296 s << ")";
295 297 }
296 298 s << ";" << endl;
297 299
298 300 s << "}" << endl << endl;
299 301 }
300 302
301 303 if (meta_class->hasDefaultToStringFunction()) {
302 304 s << "QString PythonQtWrapper_" << meta_class->name() << "::py_toString(" << meta_class->qualifiedCppName() << "* obj) { return obj->toString(); }" << endl;
303 305 } else if (meta_class->hasToStringCapability()) {
304 306 FunctionModelItem fun = meta_class->hasToStringCapability();
305 307 int indirections = fun->arguments().at(1)->type().indirections();
306 308 QString deref = QLatin1String(indirections == 0 ? "*" : "");
307 309 s << "QString PythonQtWrapper_" << meta_class->name() << "::py_toString(" << meta_class->qualifiedCppName() << "* obj) {" << endl;
308 310 s << " QString result;" << endl;
309 311 s << " QDebug d(&result);" << endl;
310 312 s << " d << " << deref << "obj;" << endl;
311 313 s << " return result;" << endl;
312 314 s << "}" << endl << endl;
313 315 }
314 316
315 317 writeInjectedCode(s, meta_class);
316 318
317 319 if (meta_class->qualifiedCppName().contains("Ssl")) {
318 320 s << "#endif" << endl;
319 321 }
320 322 }
321 323
322 324 void ShellImplGenerator::writeInjectedCode(QTextStream &s, const AbstractMetaClass *meta_class)
323 325 {
324 326 CodeSnipList code_snips = meta_class->typeEntry()->codeSnips();
325 327 foreach (const CodeSnip &cs, code_snips) {
326 328 if (cs.language == TypeSystem::PyWrapperCode) {
327 329 s << cs.code() << endl;
328 330 }
329 331 }
330 332 }
General Comments 0
You need to be logged in to leave comments. Login now