]> git.saurik.com Git - wxWidgets.git/blame - wxPython/wxSWIG/Modules/pycpp.cxx
RTTI simplifications
[wxWidgets.git] / wxPython / wxSWIG / Modules / pycpp.cxx
CommitLineData
c90f71dd
RD
1/*******************************************************************************
2 * Simplified Wrapper and Interface Generator (SWIG)
3 *
4 * Author : David Beazley
5 *
6 * Department of Computer Science
7 * University of Chicago
8 * 1100 E 58th Street
9 * Chicago, IL 60637
10 * beazley@cs.uchicago.edu
11 *
12 * Please read the file LICENSE for the copyright and terms by which SWIG
13 * can be used and distributed.
14 *******************************************************************************/
15
16/**********************************************************************
17 * $Header$
18 *
19 * pycpp.cxx
20 *
21 * This module contains code to generate Python shadow classes of C/C++
22 * objects.
23 **************************************************************************/
24
25
26#include "swig.h"
27#include "python.h"
28
29static String *setattr;
30static String *getattr;
31static String *pyclass;
32static String *construct;
33static String *cinit;
34static String *additional;
35static int have_constructor;
36static int have_destructor;
37static int have_getattr;
38static int have_setattr;
39static int have_repr;
40static char *class_name;
41static char *class_type;
42static char *real_classname;
43static String *base_class;
44static String base_getattr;
45static String base_setattr;
46static int class_renamed = 0;
47
48// --------------------------------------------------------------------------
49// PYTHON::cpp_open_class(char *classname, char *rname, char *ctype, int strip)
50//
51// Opens a new C++ class or structure.
52// --------------------------------------------------------------------------
53
54void PYTHON::cpp_open_class(char *classname, char *rname, char *ctype, int strip) {
55
56 char temp[256];
57
58 this->Language::cpp_open_class(classname, rname, ctype, strip);
59
60 if (shadow) {
61 /* Create new strings for building up a wrapper function */
62
63 setattr = new String();
64 getattr = new String();
65 pyclass = new String();
66 construct = new String();
67 cinit = new String();
68 additional= new String();
69 base_class = 0;
70 base_getattr = "";
71 base_setattr = "";
72
73
74 // *pyclass << "class " << rname << ":\n";
75 *setattr << tab4 << "def __setattr__(self,name,value):\n";
76 *getattr << tab4 << "def __getattr__(self,name):\n";
77 have_constructor = 0;
78 have_destructor = 0;
79 have_getattr = 0;
80 have_setattr = 0;
81 have_repr = 0;
82 if (rname) {
83 class_name = copy_string(rname);
84 class_renamed = 1;
85 } else {
86 class_name = copy_string(classname);
87 class_renamed = 0;
88 }
89 }
90
91 real_classname = copy_string(classname);
92 class_type = copy_string(ctype);
93
94 // Build up the hash table
95 hash.add(real_classname,copy_string(class_name));
96
97 sprintf(temp,"%s %s", class_type, real_classname);
98 hash.add(temp,copy_string(class_name));
99
100}
101
102// --------------------------------------------------------------------------
103// PYTHON::cpp_member_func(char *name, char *iname, DataType *t, ParmList *l)
104//
105// Creates a C++ member function
106// --------------------------------------------------------------------------
107
108void PYTHON::cpp_member_func(char *name, char *iname, DataType *t, ParmList *l) {
109
110 Parm *p;
111 int i;
112 char *realname;
113 int oldshadow;
114 int pcount;
115 int numopt;
116 int have_optional;
117
118 String cname = "python:";
119 String translate = "";
120
121 // Create the default member function
122
123 oldshadow = shadow; // Disable shadowing when wrapping member functions
124 if (shadow) shadow = shadow | PYSHADOW_MEMBER;
125 this->Language::cpp_member_func(name,iname,t,l);
126 shadow = oldshadow;
127 if (shadow) {
128 if (!iname)
129 realname = name;
130 else
131 realname = iname;
132
133 // Check to see if we've already seen this
134 cname << class_name << "::" << realname;
135 if (add_symbol(cname.get(), 0,0)) {
136 return; // Forget it, already saw it
137 }
138
139 if (strcmp(realname,"__repr__") == 0)
140 have_repr = 1;
141
142 // Now add it to the class
143
144 *pyclass << tab4 << "def " << realname << "(self, *_args, **_kwargs):\n";
145 // Create a doc string
146 if (docstring && doc_entry) {
147 *pyclass << tab8 << "\"\"\"" << add_docstring(doc_entry) << "\"\"\"\n";
148 }
1fded56b 149 *pyclass << tab8 << "val = " << module << "." << name_member(realname,class_name) << "(self, *_args, **_kwargs)\n";
c90f71dd
RD
150
151 // Check to see if the return type is an object
152 if ((hash.lookup(t->name)) && (t->is_pointer <= 1)) {
153 if (!typemap_check("out",typemap_lang,t,name_member(realname,class_name))) {
154 if (!have_output) {
155 *pyclass << tab8 << "if val: val = " << (char *) hash.lookup(t->name) << "Ptr(val) ";
156 if (((hash.lookup(t->name)) && (t->is_pointer < 1)) ||
157 ((hash.lookup(t->name)) && (t->is_pointer == 1) && NewObject))
158 *pyclass << "; val.thisown = 1\n";
159 else
160 *pyclass << "\n";
161 } else {
162 // Do nothing!
163 }
164 }
165 }
166 emitAddPragmas(*pyclass, realname, tab8);
167 *pyclass << tab8 << "return val\n";
168
169 // Change the usage string to reflect our shadow class
170 if (doc_entry) {
171 doc_entry->usage = "";
172 doc_entry->usage << usage_func(realname,t,l);
173 }
174 }
175}
176
177// -----------------------------------------------------------------------------
178// void PYTHON::cpp_constructor(char *name, char *iname, ParmList *l)
179//
180// Make a constructor for our class
181// -----------------------------------------------------------------------------
182
183void PYTHON::cpp_constructor(char *name, char *iname, ParmList *l) {
184 char *realname;
185 Parm *p;
186 int i;
187 int oldshadow = shadow;
188 String cname = "python:constructor:";
189 String translate = "";
190 int pcount, numopt;
191 int have_optional;
192
193 if (shadow) shadow = shadow | PYSHADOW_MEMBER;
194 this->Language::cpp_constructor(name,iname,l);
195 shadow = oldshadow;
196
197 if (shadow) {
198 if (iname)
199 realname = iname;
200 else {
201 if (class_renamed) realname = class_name;
202 else realname = class_name;
203 }
204
205 // Check to see if we've already seen this
206 cname << class_name << "::" << realname;
207 if (add_symbol(cname.get(), 0,0)) {
208 return; // Forget it, already seen it
209 }
210
211 if (!have_constructor) {
212
213 // Create a new constructor
214
215 *construct << tab4 << "def __init__(self,*_args,**_kwargs):\n";
216 if (docstring && doc_entry)
217 *construct << tab8 << "\"\"\"" << add_docstring(doc_entry) << "\"\"\"\n";
218
1fded56b 219 *construct << tab8 << "self.this = " << module << "." << name_construct(realname) << "(*_args,**_kwargs)\n";
c90f71dd
RD
220 *construct << tab8 << "self.thisown = 1\n";
221 emitAddPragmas(*construct,"__init__",tab8);
222 have_constructor = 1;
223 } else {
224
225 // Hmmm. We seem to be creating a different constructor. We're just going to create a
226 // function for it.
227
228 *additional << "def " << realname << "(*_args,**_kwargs):\n";
1fded56b
RD
229 *additional << tab4 << "val = " << class_name << "Ptr("
230 << module << "." << name_construct(realname) << "(*_args,**_kwargs))\n"
c90f71dd
RD
231 << tab4 << "val.thisown = 1\n";
232 emitAddPragmas(*additional, realname, tab4);
233 *additional << tab4 << "return val\n\n";
234 }
235 // Patch up the documentation entry
236 if (doc_entry) {
237 doc_entry->usage = "";
238 doc_entry->usage << usage_func(class_name,0,l);
239 }
240 }
241}
242
243// ------------------------------------------------------------------------------
244// void PYTHON::cpp_destructor(char *name, char *newname)
245//
246// Creates a destructor for this object
247// ------------------------------------------------------------------------------
248
249void PYTHON::cpp_destructor(char *name, char *newname) {
250 char *realname;
251 int oldshadow = shadow;
252
253 if (shadow) shadow = shadow | PYSHADOW_MEMBER;
254 this->Language::cpp_destructor(name,newname);
255 shadow = oldshadow;
256 if (shadow) {
257 if (newname) realname = newname;
258 else {
259 if (class_renamed) realname = class_name;
260 else realname = name;
261 }
262
1e4a197e
RD
263 char* dfname = name_destroy(realname);
264
265 *pyclass << tab4 << "def __del__(self, " << "delfunc=" << module<< "." << dfname << "):\n";
c90f71dd 266 emitAddPragmas(*pyclass,"__del__",tab8);
1e4a197e
RD
267 *pyclass << tab8 << "if self.thisown == 1:\n"
268 << tab8 << tab4 << "try:\n"
269 << tab8 << tab8 << "delfunc(self)\n"
270 << tab8 << tab4 << "except:\n"
271 << tab8 << tab8 << "pass\n";
c90f71dd
RD
272
273 have_destructor = 1;
274 if (doc_entry) {
275 doc_entry->usage = "";
276 doc_entry->usage << "del this";
277 }
278 }
279}
280
281// -------------------------------------------------------------------------------
282// PYTHON::cpp_close_class()
283//
284// Closes a Python class and writes out a wrapper
285// -------------------------------------------------------------------------------
286
287void PYTHON::cpp_close_class() {
288 String ptrclass;
289 String repr;
290
291 if (shadow) {
292
293 if (!have_constructor) {
294 // Build a constructor that takes a pointer to this kind of object
295 *construct << tab4 << "def __init__(self,this):\n";
296 *construct << tab8 << "self.this = this\n";
297 }
298
299 // First, build the pointer base class
300 if (base_class) {
301 ptrclass << "class " << class_name << "Ptr(" << *base_class << "):\n";
302 } else {
303 ptrclass << "class " << class_name << "Ptr :\n";
304 }
305
306 // *getattr << tab8 << "return self.__dict__[name]\n";
307 *getattr << tab8 << "raise AttributeError,name\n";
308 *setattr << tab8 << "self.__dict__[name] = value\n";
309
310 ptrclass << *cinit
311 << tab4 << "def __init__(self,this):\n"
312 << tab8 << "self.this = this\n"
313 << tab8 << "self.thisown = 0\n";
314
315 classes << ptrclass
316 << *pyclass;
317 if (have_setattr)
318 classes << *setattr;
319 if (have_getattr)
320 classes << *getattr;
321
322 if (!have_repr) {
323 // Supply a repr method for this class
324 repr << tab4 << "def __repr__(self):\n"
1fded56b 325 << tab8 << "return \"<%s.%s instance; proxy of C++ " << class_name <<" instance at %s>\" % (self.__class__.__module__, self.__class__.__name__, self.this)\n";
c90f71dd
RD
326
327 classes << repr;
328 emitAddPragmas(classes,"__class__",tab4);
329 }
330
331 // Now build the real class with a normal constructor
332
333 classes << "class " << class_name << "(" << class_name << "Ptr):\n";
334
335 if (docstring && doc_entry) {
336 classes << tab4 << "\"\"\"" << add_docstring(doc_entry) << "\"\"\"\n";
337 }
338
339 classes << *construct << "\n\n"
340 << "\n" << *additional << "\n";
341
342 delete pyclass;
343 delete setattr;
344 delete getattr;
345 delete additional;
346 }
347}
348
349void PYTHON::cpp_cleanup() { };
350
351void PYTHON::cpp_inherit(char **baseclass,int) {
352
353 char *bc;
354 int i = 0, first_base = 0;
355
356 if (!shadow) {
357 this->Language::cpp_inherit(baseclass);
358 return;
359 }
360
361 // We'll inherit variables and constants, but not methods
362
363 this->Language::cpp_inherit(baseclass, INHERIT_VAR);
364
365 if (!baseclass) return;
366 base_class = new String;
367
368 // Now tell the Python module that we're inheriting from a base class
369
370 while (baseclass[i]) {
371 bc = (char *) hash.lookup(baseclass[i]);
372 if (bc) {
373 if (first_base) *base_class << ",";
374 *base_class << bc << "Ptr";
375 first_base = 1;
376 }
377 i++;
378 }
379 if (!first_base) {
380 delete base_class;
381 base_class = 0;
382 }
383}
384
385// --------------------------------------------------------------------------------
386// PYTHON::cpp_variable(char *name, char *iname, DataType *t)
387//
388// Adds an instance member.
389// --------------------------------------------------------------------------------
390
391void PYTHON::cpp_variable(char *name, char *iname, DataType *t) {
392 char *realname;
393 int inhash = 0;
394 int oldshadow = shadow;
395 String cname = "python:";
396
397 if (shadow) shadow = shadow | PYSHADOW_MEMBER;
398 this->Language::cpp_variable(name,iname,t);
399 shadow = oldshadow;
400
401 if (shadow) {
402 have_getattr = 1;
403 have_setattr = 1;
404 if (!iname)
405 realname = name;
406 else
407 realname = iname;
408
409 // Check to see if we've already seen this
410
411 cname << class_name << "::" << realname;
412 if (add_symbol(cname.get(), 0,0)) {
413 return; // Forget it, already seen it
414 }
415
416 // Figure out if we've seen this datatype before
417
418 if ((hash.lookup(t->name)) && (t->is_pointer <= 1)) inhash = 1;
419
420 // Now write some code to set the variable
421 *setattr << tab8 << "if name == \"" << realname << "\" :\n";
422 if (inhash) {
423 *setattr << tab8 << tab4 << module << "." << name_set(name_member(realname,class_name)) << "(self,value.this)\n";
424 } else {
425 *setattr << tab8 << tab4 << module << "." << name_set(name_member(realname,class_name)) << "(self,value)\n";
426 }
427 *setattr << tab8 << tab4 << "return\n";
428
429 // Write some code to get the variable
430 *getattr << tab8 << "if name == \"" << realname << "\" : \n";
431 if (inhash) {
432 *getattr << tab8 << tab4 << "return " << (char *) hash.lookup(t->name) << "Ptr(" << module << "."
433 << name_get(name_member(realname,class_name)) << "(self))\n";
434 } else {
435 *getattr << tab8 << tab4 << "return " << module << "." << name_get(name_member(realname,class_name)) << "(self)\n";
436 }
437
438 // Patch up ye old documentation entry
439
440 if (doc_entry) {
441 doc_entry->usage = "";
442 doc_entry->usage << "self." << realname;
443 }
444 }
445}
446
447// --------------------------------------------------------------------------------
448// PYTHON::cpp_declare_const(char *name, char *iname, DataType *type, char *value)
449//
450// Add access to a C++ constant
451// --------------------------------------------------------------------------------
452
453void PYTHON::cpp_declare_const(char *name, char *iname, DataType *type, char *value) {
454 char *realname;
455 int oldshadow = shadow;
456 String cname = "python:";
457
458 if (shadow) shadow = shadow | PYSHADOW_MEMBER;
459 this->Language::cpp_declare_const(name,iname,type,value);
460 shadow = oldshadow;
461
462 if (shadow) {
463 if (!iname)
464 realname = name;
465 else
466 realname = iname;
467
468 // Check to see if we've already seen this
469
470 cname << class_name << "::" << realname;
471 if (add_symbol(cname.get(), 0,0)) {
472 return; // Forget it, already seen it
473 }
474
475 *cinit << tab4 << realname << " = " << module << "." << name_member(realname,class_name) << "\n";
476
477 if (doc_entry) {
478 doc_entry->usage = "";
479 doc_entry->usage << "self." << realname;
480 if (value) {
481 doc_entry->usage << " = " << value;
482 }
483 }
484 }
485}
486
487// --------------------------------------------------------------------------------
488// PYTHON::add_typedef(DataType *t, char *name)
489//
490// This is called whenever a typedef is encountered. When shadow classes are
491// used, this function lets us discovered hidden uses of a class. For example :
492//
493// struct FooBar {
494// ...
495// }
496//
497// typedef FooBar *FooBarPtr;
498//
499// --------------------------------------------------------------------------------
500
501void PYTHON::add_typedef(DataType *t, char *name) {
502
503 if (!shadow) return;
504
505 // First check to see if there aren't too many pointers
506
507 if (t->is_pointer > 1) return;
508
509 if (hash.lookup(name)) return; // Already added
510
511
512 // Now look up the datatype in our shadow class hash table
513
514 if (hash.lookup(t->name)) {
515
516 // Yep. This datatype is in the hash
517
518 // Put this types 'new' name into the hash
519
520 hash.add(name,copy_string((char *) hash.lookup(t->name)));
521 }
522}