swig/Source/Modules/python.cxx
Dave Beazley 7f26e39937 Added patch 701860.
git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk/SWIG@4586 626c5289-ae23-0410-ae9c-e8d60b6d4f22
2003-03-20 18:59:01 +00:00

2205 lines
69 KiB
C++

/* -----------------------------------------------------------------------------
* python.cxx
*
* Python module.
*
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
*
* Copyright (C) 1999-2000. The University of Chicago
* See the file LICENSE for information on usage and redistribution.
* ----------------------------------------------------------------------------- */
char cvsroot_python_cxx[] = "$Header$";
#include "swigmod.h"
#ifndef MACSWIG
#include "swigconfig.h"
#endif
#include <ctype.h>
/**********************************************************************************
*
* TYPE UTILITY FUNCTIONS
*
* These ultimately belong elsewhere, but for now I'm leaving them here to
* make it easier to keep an eye on them during testing. Not all of these may
* be necessary, and some may duplicate existing functionality in SWIG. --MR
*
**********************************************************************************/
/* Swig_csuperclass_call()
*
* Generates a fully qualified method call, including the full parameter list.
* e.g. "base::method(i, j)"
*
*/
String *Swig_csuperclass_call(String* base, String* method, ParmList* l) {
String *call = NewString("");
Parm *p;
if (base) {
Printf(call, "%s::", base);
}
Printf(call, "%s(", method);
for (p=l; p; p = nextSibling(p)) {
String *pname = Getattr(p, "name");
if (p != l) Printf(call, ", ");
Printv(call, pname, NIL);
}
Printf(call, ")");
return call;
}
/* Swig_class_declaration()
*
* Generate the start of a class/struct declaration.
* e.g. "class myclass"
*
*/
String *Swig_class_declaration(Node *n, String *name) {
if (!name) {
name = Getattr(n, "sym:name");
}
String *result = NewString("");
String *kind = Getattr(n, "kind");
Printf(result, "%s %s", kind, name);
return result;
}
String *Swig_class_name(Node *n) {
String *name;
name = Copy(Getattr(n, "sym:name"));
return name;
}
/* Swig_director_declaration()
*
* Generate the full director class declaration, complete with base classes.
* e.g. "class __DIRECTOR__myclass: public myclass, public __DIRECTOR__ {"
*
*/
String *Swig_director_declaration(Node *n) {
String* classname = Swig_class_name(n);
String *directorname = NewStringf("__DIRECTOR__%s", classname);
String *base = Getattr(n, "classtype");
String *declaration = Swig_class_declaration(n, directorname);
Printf(declaration, ": public %s, public __DIRECTOR__ {\n", base);
Delete(classname);
Delete(directorname);
return declaration;
}
String *
Swig_method_call(String_or_char *name, ParmList *parms) {
String *func;
int i = 0;
int comma = 0;
Parm *p = parms;
SwigType *pt;
String *nname;
func = NewString("");
nname = SwigType_namestr(name);
Printf(func,"%s(", nname);
while (p) {
String *pname;
pt = Getattr(p,"type");
if ((SwigType_type(pt) != T_VOID)) {
if (comma) Printf(func,",");
pname = Getattr(p, "name");
Printf(func,"%s", pname);
comma = 1;
i++;
}
p = nextSibling(p);
}
Printf(func,")");
return func;
}
/* method_decl
*
* Misnamed and misappropriated! Taken from SWIG's type string manipulation utilities
* and modified to generate full (or partial) type qualifiers for method declarations,
* local variable declarations, and return value casting. More importantly, it merges
* parameter type information with actual parameter names to produce a complete method
* declaration that fully mirrors the original method declaration.
*
* There is almost certainly a saner way to do this.
*
* This function needs to be cleaned up and possibly split into several smaller
* functions. For instance, attaching default names to parameters should be done in a
* separate function.
*
*/
String *method_decl(SwigType *s, const String_or_char *id, List *args, int strip, int values) {
String *result;
List *elements;
String *element = 0, *nextelement;
int is_const = 0;
int nelements, i;
int is_func = 0;
int arg_idx = 0;
if (id) {
result = NewString(Char(id));
} else {
result = NewString("");
}
elements = SwigType_split(s);
nelements = Len(elements);
if (nelements > 0) {
element = Getitem(elements, 0);
}
for (i = 0; i < nelements; i++) {
if (i < (nelements - 1)) {
nextelement = Getitem(elements, i+1);
} else {
nextelement = 0;
}
if (SwigType_isqualifier(element)) {
int skip = 0;
DOH *q = 0;
if (!strip) {
q = SwigType_parm(element);
if (!Cmp(q, "const")) {
is_const = 1;
is_func = SwigType_isfunction(nextelement);
if (is_func) skip = 1;
skip = 1;
}
if (!skip) {
Insert(result,0," ");
Insert(result,0,q);
}
Delete(q);
}
} else if (SwigType_ispointer(element)) {
Insert(result,0,"*");
if ((nextelement) && ((SwigType_isfunction(nextelement) || (SwigType_isarray(nextelement))))) {
Insert(result,0,"(");
Append(result,")");
}
} else if (SwigType_ismemberpointer(element)) {
String *q;
q = SwigType_parm(element);
Insert(result,0,"::*");
Insert(result,0,q);
if ((nextelement) && ((SwigType_isfunction(nextelement) || (SwigType_isarray(nextelement))))) {
Insert(result,0,"(");
Append(result,")");
}
Delete(q);
}
else if (SwigType_isreference(element)) {
Insert(result,0,"&");
} else if (SwigType_isarray(element)) {
DOH *size;
Append(result,"[");
size = SwigType_parm(element);
Append(result,size);
Append(result,"]");
Delete(size);
} else if (SwigType_isfunction(element)) {
Parm *parm;
String *p;
Append(result,"(");
parm = args;
while (parm != 0) {
String *type = Getattr(parm, "type");
String* name = Getattr(parm, "name");
if (!name && Cmp(type, "void")) {
name = NewString("");
Printf(name, "arg%d", arg_idx++);
Setattr(parm, "name", name);
}
if (!name) {
name = NewString("");
}
p = SwigType_str(type, name);
Append(result,p);
String* value = Getattr(parm, "value");
if (values && (value != 0)) {
Printf(result, " = %s", value);
}
parm = nextSibling(parm);
if (parm != 0) Append(result,", ");
}
Append(result,")");
} else {
if (Strcmp(element,"v(...)") == 0) {
Insert(result,0,"...");
} else {
String *bs = SwigType_namestr(element);
Insert(result,0," ");
Insert(result,0,bs);
Delete(bs);
}
}
element = nextelement;
}
Delete(elements);
if (is_const) {
if (is_func) {
Append(result, " ");
Append(result, "const");
} else {
Insert(result, 0, "const ");
}
}
Chop(result);
return result;
}
/**********************************************************************************
*
* END OF TYPE UTILITY FUNCTIONS
*
**********************************************************************************/
#define PYSHADOW_MEMBER 0x2
static String *const_code = 0;
static String *shadow_methods = 0;
static String *module = 0;
static String *mainmodule = 0;
static String *interface = 0;
static String *global_name = 0;
static int shadow = 1;
static int use_kw = 0;
static File *f_runtime = 0;
static File *f_runtime_h = 0;
static File *f_header = 0;
static File *f_wrappers = 0;
static File *f_directors = 0;
static File *f_directors_h = 0;
static File *f_init = 0;
static File *f_shadow = 0;
static File *f_shadow_stubs = 0;
static String *methods;
static String *class_name;
static String *shadow_indent = 0;
static int in_class = 0;
static int classic = 0;
/* C++ Support + Shadow Classes */
static int have_constructor;
static int have_repr;
static String *real_classname;
static const char *usage = (char *)"\
Python Options (available with -python)\n\
-ldflags - Print runtime libraries to link with\n\
-globals name - Set name used to access C global variable ('cvar' by default).\n\
-interface name - Set the lib name\n\
-keyword - Use keyword arguments\n\
-classic - Use classic classes only\n\
-noexcept - No automatic exception handling.\n\
-noproxy - Don't generate proxy classes. \n\n";
class PYTHON : public Language {
public:
/* ------------------------------------------------------------
* main()
* ------------------------------------------------------------ */
virtual void main(int argc, char *argv[]) {
SWIG_library_directory("python");
for (int i = 1; i < argc; i++) {
if (argv[i]) {
if(strcmp(argv[i],"-interface") == 0) {
if (argv[i+1]) {
interface = NewString(argv[i+1]);
Swig_mark_arg(i);
Swig_mark_arg(i+1);
i++;
} else {
Swig_arg_error();
}
/* end added */
} else if (strcmp(argv[i],"-globals") == 0) {
if (argv[i+1]) {
global_name = NewString(argv[i+1]);
Swig_mark_arg(i);
Swig_mark_arg(i+1);
i++;
} else {
Swig_arg_error();
}
} else if ((strcmp(argv[i],"-shadow") == 0) || ((strcmp(argv[i],"-proxy") == 0))) {
shadow = 1;
Swig_mark_arg(i);
} else if ((strcmp(argv[i],"-noproxy") == 0)) {
shadow = 0;
Swig_mark_arg(i);
} else if (strcmp(argv[i],"-keyword") == 0) {
use_kw = 1;
Swig_mark_arg(i);
} else if (strcmp(argv[i],"-classic") == 0) {
classic = 1;
Swig_mark_arg(i);
} else if (strcmp(argv[i],"-help") == 0) {
fputs(usage,stderr);
} else if (strcmp (argv[i], "-ldflags") == 0) {
printf("%s\n", SWIG_PYTHON_RUNTIME);
SWIG_exit (EXIT_SUCCESS);
}
}
}
if (!global_name) global_name = NewString("cvar");
Preprocessor_define("SWIGPYTHON 1", 0);
SWIG_typemap_lang("python");
SWIG_config_file("python.swg");
allow_overloading();
}
/* ------------------------------------------------------------
* top()
* ------------------------------------------------------------ */
virtual int top(Node *n) {
/* check if directors are enabled for this module. note: this
* is a "master" switch, without which no director code will be
* emitted. %feature("director") statements are also required
* to enable directors for individual classes or methods.
*
* use %module(directors="1") modulename at the start of the
* interface file to enable director generation.
*/
{
Node *module = Getattr(n, "module");
if (module) {
Node *options = Getattr(module, "options");
if (options) {
if (Getattr(options, "directors")) {
allow_directors();
}
}
}
}
/* Set comparison with none for ConstructorToFunction */
SetNoneComparison( NewString( "$arg != Py_None" ) );
/* Initialize all of the output files */
String *outfile = Getattr(n,"outfile");
String *outfile_h = Getattr(n, "outfile_h");
f_runtime = NewFile(outfile,"w");
if (!f_runtime) {
Printf(stderr,"*** Can't open '%s'\n", outfile);
SWIG_exit(EXIT_FAILURE);
}
if (directorsEnabled()) {
f_runtime_h = NewFile(outfile_h,"w");
if (!f_runtime_h) {
Printf(stderr,"*** Can't open '%s'\n", outfile_h);
SWIG_exit(EXIT_FAILURE);
}
}
f_init = NewString("");
f_header = NewString("");
f_wrappers = NewString("");
f_directors_h = NewString("");
f_directors = NewString("");
/* Register file targets with the SWIG file handler */
Swig_register_filebyname("header",f_header);
Swig_register_filebyname("wrapper",f_wrappers);
Swig_register_filebyname("runtime",f_runtime);
Swig_register_filebyname("init",f_init);
Swig_register_filebyname("director",f_directors);
Swig_register_filebyname("director_h",f_directors_h);
const_code = NewString("");
shadow_methods = NewString("");
methods = NewString("");
Swig_banner(f_runtime);
Printf(f_runtime,"#define SWIGPYTHON\n");
if (NoInclude)
Printf(f_runtime,"#define SWIG_NOINCLUDE\n");
if (directorsEnabled()) {
Printf(f_runtime,"#define SWIG_DIRECTORS\n");
}
/* Set module name */
module = Copy(Getattr(n,"name"));
mainmodule = Getattr(n,"name");
if (directorsEnabled()) {
Swig_banner(f_directors_h);
Printf(f_directors_h, "#ifndef __%s_WRAP_H__\n", module);
Printf(f_directors_h, "#define __%s_WRAP_H__\n\n", module);
Printf(f_directors_h, "class __DIRECTOR__;\n\n");
Swig_insert_file("director.swg", f_directors);
Printf(f_directors, "\n\n");
Printf(f_directors, "/* ---------------------------------------------------\n");
Printf(f_directors, " * C++ director class methods\n");
Printf(f_directors, " * --------------------------------------------------- */\n\n");
Printf(f_directors, "#include \"%s\"\n\n", outfile_h);
}
char filen[256];
/* If shadow classing is enabled, we're going to change the module name to "_module" */
if (shadow) {
sprintf(filen,"%s%s.py", Swig_file_dirname(outfile), Char(module));
// If we don't have an interface then change the module name X to _X
if (interface) module = interface;
else Insert(module,0,"_");
if ((f_shadow = NewFile(filen,"w")) == 0) {
Printf(stderr,"Unable to open %s\n", filen);
SWIG_exit (EXIT_FAILURE);
}
f_shadow_stubs = NewString("");
Swig_register_filebyname("shadow",f_shadow);
Swig_register_filebyname("python",f_shadow);
Printv(f_shadow,
"# This file was created automatically by SWIG.\n",
"# Don't modify this file, modify the SWIG interface instead.\n",
"# This file is compatible with both classic and new-style classes.\n",
NIL);
Printf(f_shadow,"import %s\n", module);
// Python-2.2 object hack
Printv(f_shadow,
"def _swig_setattr(self,class_type,name,value):\n",
tab4, "if (name == \"this\"):\n",
tab4, tab4, "if isinstance(value, class_type):\n",
tab4, tab8, "self.__dict__[name] = value.this\n",
tab4, tab8, "if hasattr(value,\"thisown\"): self.__dict__[\"thisown\"] = value.thisown\n",
tab4, tab8, "del value.thisown\n",
tab4, tab8, "return\n",
// tab8, "if (name == \"this\") or (name == \"thisown\"): self.__dict__[name] = value; return\n",
tab4, "method = class_type.__swig_setmethods__.get(name,None)\n",
tab4, "if method: return method(self,value)\n",
tab4, "self.__dict__[name] = value\n\n",
NIL);
Printv(f_shadow,
"def _swig_getattr(self,class_type,name):\n",
tab4, "method = class_type.__swig_getmethods__.get(name,None)\n",
tab4, "if method: return method(self)\n",
tab4, "raise AttributeError,name\n\n",
NIL);
if (!classic) {
Printv(f_shadow,
"import types\n",
"try:\n",
" _object = types.ObjectType\n",
" _newclass = 1\n",
"except AttributeError:\n",
" class _object : pass\n",
" _newclass = 0\n",
"\n\n",
NIL);
}
if (directorsEnabled()) {
// Try loading weakref.proxy, which is only available in Python 2.1 and higher
Printv(f_shadow,
"try:\n",
tab4, "from weakref import proxy as weakref_proxy\n",
"except:\n",
tab4, "weakref_proxy = lambda x: x\n",
"\n\n",
NIL);
}
// Include some information in the code
Printf(f_header,"\n/*-----------------------------------------------\n @(target):= %s.so\n\
------------------------------------------------*/\n", module);
}
Printf(f_header,"#define SWIG_init init%s\n\n", module);
Printf(f_header,"#define SWIG_name \"%s\"\n", module);
Printf(f_wrappers,"#ifdef __cplusplus\n");
Printf(f_wrappers,"extern \"C\" {\n");
Printf(f_wrappers,"#endif\n");
Printf(const_code,"static swig_const_info swig_const_table[] = {\n");
Printf(methods,"static PyMethodDef SwigMethods[] = {\n");
/* emit code */
Language::top(n);
/* Close language module */
Printf(methods,"\t { NULL, NULL }\n");
Printf(methods,"};\n");
Printf(f_wrappers,"%s\n",methods);
SwigType_emit_type_table(f_runtime,f_wrappers);
Printf(const_code, "{0}};\n");
Printf(f_wrappers,"%s\n",const_code);
Printf(f_init,"}\n");
Printf(f_wrappers,"#ifdef __cplusplus\n");
Printf(f_wrappers,"}\n");
Printf(f_wrappers,"#endif\n");
if (shadow) {
Printv(f_shadow, f_shadow_stubs, "\n",NIL);
Close(f_shadow);
Delete(f_shadow);
}
/* Close all of the files */
Dump(f_header,f_runtime);
if (directorsEnabled()) {
Dump(f_directors, f_runtime);
Dump(f_directors_h, f_runtime_h);
Printf(f_runtime_h, "\n");
Printf(f_runtime_h, "#endif /* __%s_WRAP_H__ */\n", module);
Close(f_runtime_h);
}
Dump(f_wrappers,f_runtime);
Wrapper_pretty_print(f_init,f_runtime);
Delete(f_header);
Delete(f_wrappers);
Delete(f_init);
Delete(f_directors);
Delete(f_directors_h);
Close(f_runtime);
return SWIG_OK;
}
/* ------------------------------------------------------------
* importDirective()
* ------------------------------------------------------------ */
virtual int importDirective(Node *n) {
if (shadow) {
String *modname = Getattr(n,"module");
if (modname) {
Printf(f_shadow,"import %s\n", modname);
}
}
return Language::importDirective(n);
}
/* ------------------------------------------------------------
* add_method()
* ------------------------------------------------------------ */
void add_method(String *name, String *function, int kw) {
if (!kw)
Printf(methods,"\t { (char *)\"%s\", %s, METH_VARARGS },\n", name, function);
else
Printf(methods,"\t { (char *)\"%s\", (PyCFunction) %s, METH_VARARGS | METH_KEYWORDS },\n", name, function);
}
/* ------------------------------------------------------------
* functionWrapper()
* ------------------------------------------------------------ */
virtual int functionWrapper(Node *n) {
String *name = Getattr(n,"name");
String *iname = Getattr(n,"sym:name");
SwigType *d = Getattr(n,"type");
ParmList *l = Getattr(n,"parms");
Node *parent = Getattr(n,"parentNode");
Parm *p;
int i;
char wname[256];
char source[64];
Wrapper *f;
String *parse_args;
String *arglist;
String *get_pointers;
String *cleanup;
String *outarg;
String *kwargs;
String *tm;
String *overname = 0;
int num_required;
int num_arguments;
int varargs = 0;
int allow_kwargs = (use_kw || Getattr(n,"feature:kwargs")) ? 1 : 0;
/* member of a director class? */
int director = Swig_directormethod(n);
int directorbase = Swig_directorbase(n);
Node *classNode = Swig_methodclass(n);
String *nodeType = Getattr(n, "nodeType");
int constructor = (!Cmp(nodeType, "constructor"));
String *storage = Getattr(n,"storage");
int isVirtual = (Cmp(storage,"virtual") == 0);
if (Getattr(n,"sym:overloaded")) {
overname = Getattr(n,"sym:overname");
} else {
if (!addSymbol(iname,n)) return SWIG_ERROR;
}
f = NewWrapper();
parse_args = NewString("");
arglist = NewString("");
get_pointers = NewString("");
cleanup = NewString("");
outarg = NewString("");
kwargs = NewString("");
Wrapper_add_local(f,"resultobj", "PyObject *resultobj");
/* Write code to extract function parameters. */
emit_args(d, l, f);
/* Attach the standard typemaps */
emit_attach_parmmaps(l,f);
Setattr(n,"wrap:parms",l);
/* Get number of required and total arguments */
num_arguments = emit_num_arguments(l);
num_required = emit_num_required(l);
varargs = emit_isvarargs(l);
strcpy(wname,Char(Swig_name_wrapper(iname)));
if (overname) {
strcat(wname,Char(overname));
}
if (!allow_kwargs || Getattr(n,"sym:overloaded")) {
if (!varargs) {
Printv(f->def,
"static PyObject *", wname,
"(PyObject *self, PyObject *args) {",
NIL);
} else {
Printv(f->def,
"static PyObject *", wname, "__varargs__",
"(PyObject *self, PyObject *args, PyObject *varargs) {",
NIL);
}
if (allow_kwargs) {
Swig_warning(WARN_LANG_OVERLOAD_KEYWORD, input_file, line_number,
"Can't use keyword arguments with overloaded functions.\n");
allow_kwargs = 0;
}
} else {
if (varargs) {
Swig_warning(WARN_LANG_VARARGS_KEYWORD, input_file, line_number,
"Can't wrap varargs with keyword arguments enabled\n");
varargs = 0;
}
Printv(f->def,
"static PyObject *", wname,
"(PyObject *self, PyObject *args, PyObject *kwargs) {",
NIL);
}
if (!allow_kwargs) {
Printf(parse_args," if(!PyArg_ParseTuple(args,(char *)\"");
} else {
Printf(parse_args," if(!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)\"");
Printf(arglist,",kwnames");
}
/* Generate code for argument marshalling */
Printf(kwargs,"{ ");
for (i = 0, p=l; i < num_arguments; i++) {
while (checkAttribute(p,"tmap:in:numinputs","0")) {
p = Getattr(p,"tmap:in:next");
}
SwigType *pt = Getattr(p,"type");
String *pn = Getattr(p,"name");
String *ln = Getattr(p,"lname");
sprintf(source,"obj%d",i);
Putc(',',arglist);
if (i == num_required) Putc('|', parse_args); /* Optional argument separator */
/* Keyword argument handling */
if (Len(pn)) {
Printf(kwargs,"\"%s\",", pn);
} else {
Printf(kwargs,"\"arg%d\",", i+1);
}
/* Look for an input typemap */
if ((tm = Getattr(p,"tmap:in"))) {
String *parse = Getattr(p,"tmap:in:parse");
if (!parse) {
Replaceall(tm,"$source",source);
Replaceall(tm,"$target",ln);
Replaceall(tm,"$input", source);
Setattr(p,"emit:input", source); /* Save the location of the object */
if (Getattr(p,"wrap:disown") || (Getattr(p,"tmap:in:disown"))) {
Replaceall(tm,"$disown","SWIG_POINTER_DISOWN");
} else {
Replaceall(tm,"$disown","0");
}
Putc('O',parse_args);
Wrapper_add_localv(f, source, "PyObject *",source, "= 0", NIL);
Printf(arglist,"&%s",source);
if (i >= num_required)
Printv(get_pointers, "if (", source, ") {\n", NIL);
Printv(get_pointers,tm,"\n", NIL);
if (i >= num_required)
Printv(get_pointers, "}\n", NIL);
} else {
Printf(parse_args,"%s",parse);
Printf(arglist,"&%s", ln);
}
p = Getattr(p,"tmap:in:next");
continue;
} else {
Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number,
"Unable to use type %s as a function argument.\n",SwigType_str(pt,0));
break;
}
p = nextSibling(p);
}
/* finish argument marshalling */
Printf(kwargs," NULL }");
if (allow_kwargs) {
Printv(f->locals,tab4, "char *kwnames[] = ", kwargs, ";\n", NIL);
}
Printf(parse_args,":%s\"", iname);
Printv(parse_args,
arglist, ")) goto fail;\n",
NIL);
/* Now piece together the first part of the wrapper function */
Printv(f->code, parse_args, get_pointers, NIL);
/* Check for trailing varargs */
if (varargs) {
if (p && (tm = Getattr(p,"tmap:in"))) {
Replaceall(tm,"$input", "varargs");
Printv(f->code,tm,"\n",NIL);
}
}
/* Insert constraint checking code */
for (p = l; p;) {
if ((tm = Getattr(p,"tmap:check"))) {
Replaceall(tm,"$target",Getattr(p,"lname"));
Printv(f->code,tm,"\n",NIL);
p = Getattr(p,"tmap:check:next");
} else {
p = nextSibling(p);
}
}
/* Insert cleanup code */
for (p = l; p;) {
if ((tm = Getattr(p,"tmap:freearg"))) {
Replaceall(tm,"$source",Getattr(p,"lname"));
Printv(cleanup,tm,"\n",NIL);
p = Getattr(p,"tmap:freearg:next");
} else {
p = nextSibling(p);
}
}
/* Insert argument output code */
for (p = l; p;) {
if ((tm = Getattr(p,"tmap:argout"))) {
Replaceall(tm,"$source",Getattr(p,"lname"));
Replaceall(tm,"$target","resultobj");
Replaceall(tm,"$arg",Getattr(p,"emit:input"));
Replaceall(tm,"$input",Getattr(p,"emit:input"));
Printv(outarg,tm,"\n",NIL);
p = Getattr(p,"tmap:argout:next");
} else {
p = nextSibling(p);
}
}
/* if the object is a director, and the method call originated from its
* underlying python object, resolve the call by going up the c++
* inheritance chain. otherwise try to resolve the method in python.
* without this check an infinite loop is set up between the director and
* shadow class method calls.
*/
// NOTE: this code should only be inserted if this class is the
// base class of a director class. however, in general we haven't
// yet analyzed all classes derived from this one to see if they are
// directors. furthermore, this class may be used as the base of
// a director class defined in a completely different module at a
// later time, so this test must be included whether or not directorbase
// is true. we do skip this code if directors have not been enabled
// at the command line to preserve source-level compatibility with
// non-polymorphic swig. also, if this wrapper is for a smart-pointer
// method, there is no need to perform the test since the calling object
// (the smart-pointer) and the director object (the "pointee") are
// distinct.
if (directorsEnabled()) {
if (!is_smart_pointer()) {
if (/*directorbase &&*/ !constructor && isVirtual) {
Wrapper_add_local(f, "director", "__DIRECTOR__ *director = 0");
Printf(f->code, "director = dynamic_cast<__DIRECTOR__*>(arg1);\n");
Printf(f->code, "if (director && (director->__get_self()==obj0)) director->__set_up();\n");
}
}
}
/* for constructor, determine if Python class has been subclassed.
* if so, create a director instance. otherwise, just create a normal instance.
*/
/* MOVED TO Swig_ConstructorToFunction() */
/*
if (constructor && (Getattr(n, "wrap:self") != 0)) {
Wrapper_add_local(f, "subclassed", "int subclassed = 0");
Printf(f->code, "subclassed = (arg1 != Py_None);\n");
}
*/
/* Emit the function call */
emit_action(n,f);
/* This part below still needs cleanup */
/* Return the function value */
if ((tm = Swig_typemap_lookup_new("out",n,"result",0))) {
Replaceall(tm,"$source", "result");
Replaceall(tm,"$target", "resultobj");
Replaceall(tm,"$result", "resultobj");
if (Getattr(n,"feature:new")) {
Replaceall(tm,"$owner","1");
} else {
Replaceall(tm,"$owner","0");
}
// FIXME: this will not try to unwrap directors returned as non-director
// base class pointers!
/* New addition to unwrap director return values so that the original
* python object is returned instead.
*/
int unwrap = 0;
String *decl = Getattr(n, "decl");
int is_pointer = SwigType_ispointer_return(decl);
int is_reference = SwigType_isreference_return(decl);
if (is_pointer || is_reference) {
String *type = Getattr(n, "type");
//Node *classNode = Swig_methodclass(n);
//Node *module = Getattr(classNode, "module");
Node *module = Getattr(parent, "module");
Node *target = Swig_directormap(module, type);
if (target) unwrap = 1;
}
if (unwrap) {
Wrapper_add_local(f, "resultdirector", "__DIRECTOR__ *resultdirector = 0");
Printf(f->code, "resultdirector = dynamic_cast<__DIRECTOR__*>(result);\n");
Printf(f->code, "if (resultdirector) {\n");
Printf(f->code, " resultobj = resultdirector->__get_self();\n");
Printf(f->code, " Py_INCREF(resultobj);\n");
Printf(f->code, "} else {\n");
Printf(f->code,"%s\n", tm);
Printf(f->code, "}\n");
} else {
Printf(f->code,"%s\n", tm);
}
} else {
Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number,
"Unable to use return type %s in function %s.\n", SwigType_str(d,0), name);
}
/* Output argument output code */
Printv(f->code,outarg,NIL);
/* Output cleanup code */
Printv(f->code,cleanup,NIL);
/* Look to see if there is any newfree cleanup code */
if (Getattr(n,"feature:new")) {
if ((tm = Swig_typemap_lookup_new("newfree",n,"result",0))) {
Replaceall(tm,"$source","result");
Printf(f->code,"%s\n",tm);
}
}
/* See if there is any return cleanup code */
if ((tm = Swig_typemap_lookup_new("ret", n, "result", 0))) {
Replaceall(tm,"$source","result");
Printf(f->code,"%s\n",tm);
}
Printf(f->code," return resultobj;\n");
/* Error handling code */
Printf(f->code,"fail:\n");
Printv(f->code,cleanup,NIL);
Printf(f->code,"return NULL;\n");
Printf(f->code,"}\n");
/* Substitute the cleanup code */
Replaceall(f->code,"$cleanup",cleanup);
/* Substitute the function name */
Replaceall(f->code,"$symname",iname);
Replaceall(f->code,"$result","resultobj");
/* Dump the function out */
Wrapper_print(f,f_wrappers);
/* If varargs. Need to emit a varargs stub */
if (varargs) {
DelWrapper(f);
f = NewWrapper();
Printv(f->def,
"static PyObject *", wname,
"(PyObject *self, PyObject *args) {",
NIL);
Wrapper_add_local(f,"resultobj", "PyObject *resultobj");
Wrapper_add_local(f,"varargs", "PyObject *varargs");
Wrapper_add_local(f,"newargs", "PyObject *newargs");
Printf(f->code,"newargs = PyTuple_GetSlice(args,0,%d);\n", num_arguments);
Printf(f->code,"varargs = PyTuple_GetSlice(args,%d,PyTuple_Size(args)+1);\n", num_arguments);
Printf(f->code,"resultobj = %s__varargs__(self,newargs,varargs);\n", wname);
Printf(f->code,"Py_XDECREF(newargs);\n");
Printf(f->code,"Py_XDECREF(varargs);\n");
Printf(f->code,"return resultobj;\n");
Printf(f->code,"}\n");
Wrapper_print(f,f_wrappers);
}
Setattr(n,"wrap:name", wname);
/* Now register the function with the interpreter. */
if (!Getattr(n,"sym:overloaded")) {
add_method(iname, wname, allow_kwargs);
/* Create a shadow for this function (if enabled and not in a member function) */
if ((shadow) && (!(shadow & PYSHADOW_MEMBER))) {
if (in_class) {
Printv(f_shadow_stubs,iname, " = ", module, ".", iname, "\n\n", NIL);
} else {
Printv(f_shadow,iname, " = ", module, ".", iname, "\n\n", NIL);
}
}
} else {
if (!Getattr(n,"sym:nextSibling")) {
dispatchFunction(n);
}
}
Delete(parse_args);
Delete(arglist);
Delete(get_pointers);
Delete(cleanup);
Delete(outarg);
Delete(kwargs);
DelWrapper(f);
return SWIG_OK;
}
/* ------------------------------------------------------------
* dispatchFunction()
* ------------------------------------------------------------ */
void dispatchFunction(Node *n) {
/* Last node in overloaded chain */
int maxargs;
String *tmp = NewString("");
String *dispatch = Swig_overload_dispatch(n,"return %s(self,args);",&maxargs);
/* Generate a dispatch wrapper for all overloaded functions */
Wrapper *f = NewWrapper();
String *symname = Getattr(n,"sym:name");
String *wname = Swig_name_wrapper(symname);
Printv(f->def,
"static PyObject *", wname,
"(PyObject *self, PyObject *args) {",
NIL);
Wrapper_add_local(f,"argc","int argc");
Printf(tmp,"PyObject *argv[%d]", maxargs+1);
Wrapper_add_local(f,"argv",tmp);
Wrapper_add_local(f,"ii","int ii");
Printf(f->code,"argc = PyObject_Length(args);\n");
Printf(f->code,"for (ii = 0; (ii < argc) && (ii < %d); ii++) {\n",maxargs);
Printf(f->code,"argv[ii] = PyTuple_GetItem(args,ii);\n");
Printf(f->code,"}\n");
Replaceall(dispatch,"$args","self,args");
Printv(f->code,dispatch,"\n",NIL);
Printf(f->code,"PyErr_SetString(PyExc_TypeError,\"No matching function for overloaded '%s'\");\n", symname);
Printf(f->code,"return NULL;\n");
Printv(f->code,"}\n",NIL);
Wrapper_print(f,f_wrappers);
add_method(symname,wname,0);
/* Create a shadow for this function (if enabled and not in a member function) */
if ((shadow) && (!(shadow & PYSHADOW_MEMBER))) {
Printv(f_shadow_stubs,symname, " = ", module, ".", symname, "\n\n", NIL);
}
DelWrapper(f);
Delete(dispatch);
Delete(tmp);
Delete(wname);
}
/* ------------------------------------------------------------
* variableWrapper()
* ------------------------------------------------------------ */
virtual int variableWrapper(Node *n) {
String *name = Getattr(n,"name");
String *iname = Getattr(n,"sym:name");
SwigType *t = Getattr(n,"type");
String *wname;
static int have_globals = 0;
String *tm;
Wrapper *getf, *setf;
if (!addSymbol(iname,n)) return SWIG_ERROR;
getf = NewWrapper();
setf = NewWrapper();
/* If this is our first call, add the globals variable to the
Python dictionary. */
if (!have_globals) {
Printf(f_init,"\t PyDict_SetItemString(d,(char*)\"%s\", SWIG_globals);\n",global_name);
have_globals=1;
if ((shadow) && (!(shadow & PYSHADOW_MEMBER))) {
Printf(f_shadow_stubs,"%s = %s.%s\n", global_name, module, global_name);
}
}
if ((shadow) && (SwigType_isconst(t))) {
if (!in_class) {
Printf(f_shadow_stubs,"%s = %s.%s\n", iname, global_name, iname);
}
}
wname = Swig_name_wrapper(iname);
/* Create a function for setting the value of the variable */
Printf(setf->def,"static int %s_set(PyObject *_val) {", wname);
if (!Getattr(n,"feature:immutable")) {
if ((tm = Swig_typemap_lookup_new("varin",n,name,0))) {
Replaceall(tm,"$source","_val");
Replaceall(tm,"$target",name);
Replaceall(tm,"$input","_val");
Printf(setf->code,"%s\n",tm);
Delete(tm);
} else {
Swig_warning(WARN_TYPEMAP_VARIN_UNDEF, input_file, line_number,
"Unable to set variable of type %s.\n", SwigType_str(t,0));
}
Printf(setf->code," return 0;\n");
} else {
/* Is a readonly variable. Issue an error */
Printv(setf->code,
tab4, "PyErr_SetString(PyExc_TypeError,\"Variable ", iname,
" is read-only.\");\n",
tab4, "return 1;\n",
NIL);
}
Printf(setf->code,"}\n");
Wrapper_print(setf,f_wrappers);
/* Create a function for getting the value of a variable */
Printf(getf->def,"static PyObject *%s_get() {", wname);
Wrapper_add_local(getf,"pyobj", "PyObject *pyobj");
if ((tm = Swig_typemap_lookup_new("varout",n,name,0))) {
Replaceall(tm,"$source",name);
Replaceall(tm,"$target","pyobj");
Replaceall(tm,"$result","pyobj");
Printf(getf->code,"%s\n", tm);
} else {
Swig_warning(WARN_TYPEMAP_VAROUT_UNDEF, input_file, line_number,
"Unable to link with type %s\n", SwigType_str(t,0));
}
Printf(getf->code," return pyobj;\n}\n");
Wrapper_print(getf,f_wrappers);
/* Now add this to the variable linking mechanism */
Printf(f_init,"\t SWIG_addvarlink(SWIG_globals,(char*)\"%s\",%s_get, %s_set);\n", iname, wname, wname);
DelWrapper(setf);
DelWrapper(getf);
return SWIG_OK;
}
/* ------------------------------------------------------------
* constantWrapper()
* ------------------------------------------------------------ */
virtual int constantWrapper(Node *n) {
String *name = Getattr(n,"name");
String *iname = Getattr(n,"sym:name");
SwigType *type = Getattr(n,"type");
String *value = Getattr(n,"value");
String *tm;
int have_tm = 0;
if (!addSymbol(iname,n)) return SWIG_ERROR;
/* Special hook for member pointer */
if (SwigType_type(type) == T_MPOINTER) {
String *wname = Swig_name_wrapper(iname);
Printf(f_header, "static %s = %s;\n", SwigType_str(type,wname), value);
value = wname;
}
if ((tm = Swig_typemap_lookup_new("consttab",n,name,0))) {
Replaceall(tm,"$source",value);
Replaceall(tm,"$target",name);
Replaceall(tm,"$value", value);
Printf(const_code,"%s,\n", tm);
have_tm = 1;
}
if ((tm = Swig_typemap_lookup_new("constcode", n, name, 0))) {
Replaceall(tm,"$source",value);
Replaceall(tm,"$target",name);
Replaceall(tm,"$value",value);
Printf(f_init, "%s\n", tm);
have_tm = 1;
}
if (!have_tm) {
Swig_warning(WARN_TYPEMAP_CONST_UNDEF, input_file, line_number,
"Unsupported constant value.\n");
return SWIG_NOWRAP;
}
if ((shadow) && (!(shadow & PYSHADOW_MEMBER))) {
if (!in_class) {
Printv(f_shadow,iname, " = ", module, ".", iname, "\n", NIL);
} else {
Printv(f_shadow_stubs,iname, " = ", module, ".", iname, "\n", NIL);
}
}
return SWIG_OK;
}
/* ------------------------------------------------------------
* nativeWrapper()
* ------------------------------------------------------------ */
virtual int nativeWrapper(Node *n) {
String *name = Getattr(n,"sym:name");
String *wrapname = Getattr(n,"wrap:name");
if (!addSymbol(wrapname,n)) return SWIG_ERROR;
add_method(name, wrapname,0);
if (shadow) {
Printv(f_shadow_stubs, name, " = ", module, ".", name, "\n\n", NIL);
}
return SWIG_OK;
}
/*************************************************************************************
* BEGIN C++ Director Class modifications
************************************************************************************/
/* C++/Python polymorphism demo code, copyright (C) 2002 Mark Rose <mrose@stm.lbl.gov>
*
* TODO
*
* Move some boilerplate code generation to Swig_...() functions.
*
*/
/* ---------------------------------------------------------------
* classDirectorMethod()
*
* Emit a virtual director method to pass a method call on to the
* underlying Python object.
*
* --------------------------------------------------------------- */
int classDirectorMethod(Node *n, Node *parent, String *super) {
int is_void = 0;
int is_pointer = 0;
String *decl;
String *type;
String *name;
String *classname;
String *declaration;
ParmList *l;
Wrapper *w;
String *tm;
String *wrap_args;
String *return_type;
String *value = Getattr(n, "value");
String *storage = Getattr(n,"storage");
bool pure_virtual = false;
int status = SWIG_OK;
int idx;
if (Cmp(storage,"virtual") == 0) {
if (Cmp(value,"0") == 0) {
pure_virtual = true;
}
}
classname = Getattr(parent, "sym:name");
type = Getattr(n, "type");
name = Getattr(n, "name");
w = NewWrapper();
declaration = NewString("");
/* determine if the method returns a pointer */
decl = Getattr(n, "decl");
is_pointer = SwigType_ispointer_return(decl);
is_void = (!Cmp(type, "void") && !is_pointer);
/* form complete return type */
return_type = Copy(type);
{
SwigType *t = Copy(decl);
SwigType *f = 0;
f = SwigType_pop_function(t);
SwigType_push(return_type, t);
Delete(f);
Delete(t);
}
/* virtual method definition */
l = Getattr(n, "parms");
String *target;
String *pclassname = NewStringf("__DIRECTOR__%s", classname);
String *qualified_name = NewStringf("%s::%s", pclassname, name);
target = method_decl(decl, qualified_name, l, 0, 0);
String *rtype = SwigType_str(type, 0);
Printf(w->def, "%s %s {", rtype, target);
Delete(qualified_name);
Delete(target);
/* header declaration */
target = method_decl(decl, name, l, 0, 1);
Printf(declaration, " virtual %s %s;\n", rtype, target);
Delete(target);
/* attach typemaps to arguments (C/C++ -> Python) */
String *arglist = NewString("");
String* parse_args = NewString("");
Swig_typemap_attach_parms("in", l, w);
Swig_typemap_attach_parms("inv", l, w);
Swig_typemap_attach_parms("outv", l, w);
Swig_typemap_attach_parms("argoutv", l, w);
Parm* p;
int num_arguments = emit_num_arguments(l);
int i;
char source[256];
wrap_args = NewString("");
int outputs = 0;
if (!is_void) outputs++;
/* build argument list and type conversion string */
for (i=0, idx=0, p = l; i < num_arguments; i++) {
while (Getattr(p, "tmap:ignore")) {
p = Getattr(p, "tmap:ignore:next");
}
if (Getattr(p, "tmap:argoutv") != 0) outputs++;
String* pname = Getattr(p, "name");
String* ptype = Getattr(p, "type");
Putc(',',arglist);
if ((tm = Getattr(p, "tmap:inv")) != 0) {
String* parse = Getattr(p, "tmap:inv:parse");
if (!parse) {
sprintf(source, "obj%d", idx++);
Replaceall(tm, "$input", source);
Replaceall(tm, "$owner", "0");
Printv(wrap_args, tm, "\n", NIL);
Wrapper_add_localv(w, source, "PyObject *", source, "= 0", NIL);
Printv(arglist, source, NIL);
Putc('O', parse_args);
} else {
Printf(parse_args, "%s", parse);
Replaceall(tm, "$input", pname);
Replaceall(tm, "$owner", "0");
if (Len(tm) == 0) Append(tm, pname);
Printf(arglist, "%s", tm);
}
p = Getattr(p, "tmap:inv:next");
continue;
} else
if (Cmp(ptype, "void")) {
/* special handling for pointers to other C++ director classes.
* ideally this would be left to a typemap, but there is currently no
* way to selectively apply the dynamic_cast<> to classes that have
* directors. in other words, the type "__DIRECTOR__$1_lname" only exists
* for classes with directors. we avoid the problem here by checking
* module.wrap::directormap, but it's not clear how to get a typemap to
* do something similar. perhaps a new default typemap (in addition
* to SWIGTYPE) called DIRECTORTYPE?
*/
if (SwigType_ispointer(ptype) || SwigType_isreference(ptype)) {
String *base = SwigType_base(ptype);
Node *module = Getattr(parent, "module");
Node *target = Swig_directormap(module, ptype);
sprintf(source, "obj%d", idx++);
String *nonconst = 0;
/* strip pointer/reference --- should move to Swig/stype.c */
String *nptype = NewString(Char(ptype)+2);
/* name as pointer */
String *ppname = Copy(pname);
if (SwigType_isreference(ptype)) {
Insert(ppname,0,"&");
}
/* if necessary, cast away const since Python doesn't support it! */
if (SwigType_isconst(nptype)) {
nonconst = NewStringf("nc_tmp_%s", pname);
String *nonconst_i = NewStringf("= const_cast<%s>(%s)", SwigType_lstr(ptype, 0), ppname);
Wrapper_add_localv(w, nonconst, SwigType_lstr(ptype, 0), nonconst, nonconst_i, NIL);
Delete(nonconst_i);
Swig_warning(WARN_LANG_DISCARD_CONST, input_file, line_number,
"Target language argument '%s' discards const in director method %s::%s.\n", SwigType_str(ptype, pname), classname, name);
} else {
nonconst = Copy(ppname);
}
Delete(nptype);
Delete(ppname);
String *mangle = SwigType_manglestr(ptype);
if (target) {
String *director = NewStringf("director_%s", mangle);
Wrapper_add_localv(w, director, "__DIRECTOR__ *", director, "= 0", NIL);
Wrapper_add_localv(w, source, "PyObject *", source, "= 0", NIL);
Printf(wrap_args, "%s = dynamic_cast<__DIRECTOR__*>(%s);\n", director, nonconst);
Printf(wrap_args, "if (!%s) {\n", director);
Printf(wrap_args, "%s = SWIG_NewPointerObj(%s, SWIGTYPE%s, 0);\n", source, nonconst, mangle);
Printf(wrap_args, "} else {\n");
Printf(wrap_args, "%s = %s->__get_self();\n", source, director);
Printf(wrap_args, "Py_INCREF(%s);\n", source);
Printf(wrap_args, "}\n");
Printf(wrap_args, "assert(%s);\n", source);
Delete(director);
Printv(arglist, source, NIL);
} else {
Wrapper_add_localv(w, source, "PyObject *", source, "= 0", NIL);
Printf(wrap_args, "%s = SWIG_NewPointerObj(%s, SWIGTYPE%s, 0);\n",
source, nonconst, mangle);
//Printf(wrap_args, "%s = SWIG_NewPointerObj(%s, SWIGTYPE_p_%s, 0);\n",
// source, nonconst, base);
Printv(arglist, source, NIL);
}
Putc('O', parse_args);
Delete(mangle);
Delete(nonconst);
} else {
Swig_warning(WARN_TYPEMAP_INV_UNDEF, input_file, line_number,
"Unable to use type %s as a function argument in director method %s::%s (skipping method).\n", SwigType_str(ptype, 0), classname, name);
status = SWIG_NOWRAP;
break;
}
}
p = nextSibling(p);
}
/* declare method return value
* if the return value is a reference or const reference, a specialized typemap must
* handle it, including declaration of c_result ($result).
*/
if (!is_void) {
Wrapper_add_localv(w, "c_result", SwigType_lstr(return_type, "c_result"), NIL);
}
/* declare Python return value */
Wrapper_add_local(w, "result", "PyObject *result");
/* direct call to superclass if _up is set */
Printf(w->code, "if (__get_up()) {\n");
if (pure_virtual) {
Printf(w->code, "throw SWIG_DIRECTOR_PURE_VIRTUAL_EXCEPTION();\n");
} else {
if (is_void) {
Printf(w->code, "%s;\n", Swig_method_call(super,l));
Printf(w->code, "return;\n");
} else {
Printf(w->code, "return %s;\n", Swig_method_call(super,l));
}
}
Printf(w->code, "}\n");
/* check that have a wrapped Python object */
Printv(w->code, "assert(__get_self());\n", NIL);
/* wrap complex arguments to PyObjects */
Printv(w->code, wrap_args, NIL);
/* pass the method call on to the Python object */
if (Len(parse_args) > 0) {
Printf(w->code, "result = PyObject_CallMethod(__get_self(), \"%s\", \"%s\" %s);\n", name, parse_args, arglist);
} else {
Printf(w->code, "result = PyObject_CallMethod(__get_self(), \"%s\", NULL);\n", name);
}
/* exception handling */
tm = Swig_typemap_lookup_new("director:except", n, "result", 0);
if (!tm) {
tm = Getattr(n, "feature:director:except");
}
if ((tm) && Len(tm) && (Strcmp(tm, "1") != 0)) {
Printf(w->code, "if (result == NULL) {\n");
Printf(w->code, " PyObject *error = PyErr_Occurred();\n");
Replaceall(tm, "$error", "error");
Printv(w->code, Str(tm), "\n", NIL);
Printf(w->code, "}\n");
}
/*
* Python method may return a simple object, or a tuple.
* for in/out aruments, we have to extract the appropriate PyObjects from the tuple,
* then marshal everything back to C/C++ (return value and output arguments).
*
*/
/* marshal return value and other outputs (if any) from PyObject to C/C++ type */
String* cleanup = NewString("");
String* outarg = NewString("");
if (outputs > 1) {
Wrapper_add_local(w, "output", "PyObject *output");
Printf(w->code, "if (!PyTuple_Check(result)) {\n");
Printf(w->code, "throw SWIG_DIRECTOR_TYPE_MISMATCH(\"Python method failed to return a tuple.\");\n");
Printf(w->code, "}\n");
}
idx = 0;
/* marshal return value */
if (!is_void) {
/* this seems really silly. the node's type excludes qualifier/pointer/reference markers,
* which have to be retrieved from the decl field to construct return_type. but the typemap
* lookup routine uses the node's type, so we have to swap in and out the correct type.
* it's not just me, similar silliness also occurs in Language::cDeclaration().
*/
Setattr(n, "type", return_type);
tm = Swig_typemap_lookup_new("outv", n, "result", w);
Setattr(n, "type", type);
if (tm == 0) {
String *name = NewString("result");
tm = Swig_typemap_search("outv", return_type, name, NULL);
Delete(name);
}
if (tm != 0) {
if (outputs > 1) {
Printf(w->code, "output = PyTuple_GetItem(result, %d);\n", idx++);
Replaceall(tm, "$input", "output");
} else {
Replaceall(tm, "$input", "result");
}
/* TODO check this */
if (Getattr(n,"wrap:disown")) {
Replaceall(tm,"$disown","SWIG_POINTER_DISOWN");
} else {
Replaceall(tm,"$disown","0");
}
Replaceall(tm, "$result", "c_result");
Printv(w->code, tm, "\n", NIL);
} else {
Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number,
"Unable to return type %s in director method %s::%s (skipping method).\n", SwigType_str(return_type, 0), classname, name);
status = SWIG_ERROR;
}
}
/* marshal outputs */
for (p = l; p; ) {
if ((tm = Getattr(p, "tmap:argoutv")) != 0) {
if (outputs > 1) {
Printf(w->code, "output = PyTuple_GetItem(result, %d);\n", idx++);
Replaceall(tm, "$input", "output");
} else {
Replaceall(tm, "$input", "result");
}
Replaceall(tm, "$result", Getattr(p, "name"));
Printv(w->code, tm, "\n", NIL);
p = Getattr(p, "tmap:argoutv:next");
} else {
p = nextSibling(p);
}
}
Printf(w->code, "Py_XDECREF(result);\n");
/* any existing helper functions to handle this? */
if (!is_void) {
if (!SwigType_isreference(return_type)) {
Printf(w->code, "return c_result;\n");
} else {
Printf(w->code, "return *c_result;\n");
}
}
Printf(w->code, "}\n");
/* emit the director method */
if (status == SWIG_OK) {
Wrapper_print(w, f_directors);
Printv(f_directors_h, declaration, NIL);
}
/* clean up */
Delete(wrap_args);
Delete(parse_args);
Delete(arglist);
Delete(rtype);
Delete(return_type);
Delete(pclassname);
Delete(cleanup);
Delete(outarg);
DelWrapper(w);
return status;
}
/* ------------------------------------------------------------
* classDirectorConstructor()
* ------------------------------------------------------------ */
int classDirectorConstructor(Node *n) {
Node *parent = Getattr(n, "parentNode");
String *sub = NewString("");
String *decl = Getattr(n, "decl");
String *supername = Swig_class_name(parent);
String *classname = NewString("");
Printf(classname, "__DIRECTOR__%s", supername);
/* insert self and __disown parameters */
Parm *p, *ip;
ParmList *superparms = Getattr(n, "parms");
ParmList *parms = CopyParmList(superparms);
String *type = NewString("PyObject");
SwigType_add_pointer(type);
p = NewParm(type, NewString("self"));
set_nextSibling(p, parms);
parms = p;
for (ip = parms; nextSibling(ip); ) ip = nextSibling(ip);
p = NewParm(NewString("int"), NewString("__disown"));
Setattr(p, "value", "1");
set_nextSibling(ip, p);
/* constructor */
{
Wrapper *w = NewWrapper();
String *call;
String *basetype = Getattr(parent, "classtype");
String *target = method_decl(decl, classname, parms, 0, 0);
call = Swig_csuperclass_call(0, basetype, superparms);
Printf(w->def, "%s::%s: %s, __DIRECTOR__(self, __disown) { }", classname, target, call);
Delete(target);
Wrapper_print(w, f_directors);
Delete(call);
DelWrapper(w);
}
/* constructor header */
{
String *target = method_decl(decl, classname, parms, 0, 1);
Printf(f_directors_h, " %s;\n", target);
Delete(target);
}
Delete(sub);
Delete(classname);
Delete(supername);
Delete(parms);
return Language::classDirectorConstructor(n);
}
/* ------------------------------------------------------------
* classDirectorDefaultConstructor()
* ------------------------------------------------------------ */
int classDirectorDefaultConstructor(Node *n) {
String *classname;
classname = Swig_class_name(n);
{
Wrapper *w = NewWrapper();
Printf(w->def, "__DIRECTOR__%s::__DIRECTOR__%s(PyObject* self, int __disown): __DIRECTOR__(self, __disown) { }", classname, classname);
Wrapper_print(w, f_directors);
DelWrapper(w);
}
Printf(f_directors_h, " __DIRECTOR__%s(PyObject* self, int __disown = 1);\n", classname);
Delete(classname);
return Language::classDirectorDefaultConstructor(n);
}
/* ------------------------------------------------------------
* classDirectorInit()
* ------------------------------------------------------------ */
int classDirectorInit(Node *n) {
String *declaration = Swig_director_declaration(n);
Printf(f_directors_h, "\n");
Printf(f_directors_h, "%s\n", declaration);
Printf(f_directors_h, "public:\n");
Delete(declaration);
return Language::classDirectorInit(n);
}
/* ------------------------------------------------------------
* classDirectorEnd()
* ------------------------------------------------------------ */
int classDirectorEnd(Node *n) {
Printf(f_directors_h, "};\n\n");
return Language::classDirectorEnd(n);
}
/* ------------------------------------------------------------
* classDirectorDisown()
* ------------------------------------------------------------ */
int classDirectorDisown(Node *n) {
int result;
int oldshadow = shadow;
/* disable shadowing */
if (shadow) shadow = shadow | PYSHADOW_MEMBER;
result = Language::classDirectorDisown(n);
shadow = oldshadow;
if (shadow) {
String *symname = Getattr(n,"sym:name");
String *mrename = Swig_name_disown(symname); //Getattr(n, "name"));
Printv(f_shadow, tab4, "def __disown__(self):\n", NIL);
Printv(f_shadow, tab8, "self.thisown = 0\n", NIL);
Printv(f_shadow, tab8, module, ".", mrename,"(self)\n", NIL);
Printv(f_shadow, tab8, "return weakref_proxy(self)\n", NIL);
Delete(mrename);
}
return result;
}
/*************************************************************************************
* END of C++ Director Class modifications
************************************************************************************/
/* ------------------------------------------------------------
* classDeclaration()
* ------------------------------------------------------------ */
virtual int classDeclaration(Node *n) {
String *importname;
Node *mod;
if (shadow) {
mod = Getattr(n,"module");
if (mod) {
String *modname = Getattr(mod,"name");
if (Strcmp(modname,mainmodule) != 0) {
importname = NewStringf("%s.%s", modname, Getattr(n,"sym:name"));
} else {
importname = NewString(Getattr(n,"sym:name"));
}
Setattr(n,"python:proxy",importname);
}
}
return Language::classDeclaration(n);
}
/* ------------------------------------------------------------
* classHandler()
* ------------------------------------------------------------ */
virtual int classHandler(Node *n) {
int oldclassic = classic;
if (shadow) {
/* Create new strings for building up a wrapper function */
have_constructor = 0;
have_repr = 0;
if (Getattr(n,"cplus:exceptionclass")) {
classic = 1;
}
if (Getattr(n,"feature:classic")) classic = 1;
shadow_indent = (String *) tab4;
class_name = Getattr(n,"sym:name");
real_classname = Getattr(n,"name");
if (!addSymbol(class_name,n)) return SWIG_ERROR;
/* Handle inheritance */
String *base_class = NewString("");
List *baselist = Getattr(n,"bases");
if (baselist && Len(baselist)) {
Node *base = Firstitem(baselist);
while (base) {
String *bname = Getattr(base, "python:proxy");
if (!bname) {
base = Nextitem(baselist);
continue;
}
Printv(base_class,bname,NIL);
base = Nextitem(baselist);
if (base) {
Putc(',',base_class);
}
}
}
Printv(f_shadow,"class ", class_name, NIL);
if (Len(base_class)) {
Printf(f_shadow,"(%s)", base_class);
} else {
if (!classic) {
Printf(f_shadow,"(_object)");
}
}
Printf(f_shadow,":\n");
Printv(f_shadow,tab4,"__swig_setmethods__ = {}\n",NIL);
if (Len(base_class)) {
Printf(f_shadow,"%sfor _s in [%s]: __swig_setmethods__.update(_s.__swig_setmethods__)\n",tab4,base_class);
}
Printv(f_shadow,
tab4, "__setattr__ = lambda self, name, value: _swig_setattr(self, ", class_name, ", name, value)\n",
NIL);
Printv(f_shadow,tab4,"__swig_getmethods__ = {}\n",NIL);
if (Len(base_class)) {
Printf(f_shadow,"%sfor _s in [%s]: __swig_getmethods__.update(_s.__swig_getmethods__)\n",tab4,base_class);
}
Printv(f_shadow,
tab4, "__getattr__ = lambda self, name: _swig_getattr(self, ", class_name, ", name)\n",
NIL);
}
/* Emit all of the members */
in_class = 1;
Language::classHandler(n);
in_class = 0;
/* Complete the class */
if (shadow) {
/* Generate a class registration function */
{
SwigType *ct = NewStringf("p.%s", real_classname);
SwigType_remember(ct);
Printv(f_wrappers,
"static PyObject * ", class_name, "_swigregister(PyObject *self, PyObject *args) {\n",
tab4, "PyObject *obj;\n",
tab4, "if (!PyArg_ParseTuple(args,(char*)\"O\", &obj)) return NULL;\n",
tab4, "SWIG_TypeClientData(SWIGTYPE", SwigType_manglestr(ct),", obj);\n",
tab4, "Py_INCREF(obj);\n",
tab4, "return Py_BuildValue((char *)\"\");\n",
"}\n",NIL);
String *cname = NewStringf("%s_swigregister", class_name);
add_method(cname, cname, 0);
Delete(cname);
Delete(ct);
}
if (!have_constructor) {
Printv(f_shadow,tab4,"def __init__(self): raise RuntimeError, \"No constructor defined\"\n",NIL);
}
if (!have_repr) {
/* Supply a repr method for this class */
Printv(f_shadow,
tab4, "def __repr__(self):\n",
tab8, "return \"<C ", class_name," instance at %s>\" % (self.this,)\n",
NIL);
}
/* Now build the real class with a normal constructor */
Printv(f_shadow,
"\nclass ", class_name, "Ptr(", class_name, "):\n",
tab4, "def __init__(self,this):\n",
tab8, "_swig_setattr(self, ", class_name, ", 'this', this)\n",
tab8, "if not hasattr(self,\"thisown\"): _swig_setattr(self, ", class_name, ", 'thisown', 0)\n",
// tab8,"try: self.this = this.this; self.thisown = getattr(this,'thisown',0); this.thisown=0\n",
// tab8,"except AttributeError: self.this = this\n"
tab8, "_swig_setattr(self, ", class_name, ",self.__class__,", class_name, ")\n",
NIL);
Printf(f_shadow,"%s.%s_swigregister(%sPtr)\n", module, class_name, class_name,0);
shadow_indent = 0;
Printf(f_shadow,"%s\n", f_shadow_stubs);
Clear(f_shadow_stubs);
}
classic = oldclassic;
return SWIG_OK;
}
/* ------------------------------------------------------------
* memberfunctionHandler()
* ------------------------------------------------------------ */
virtual int memberfunctionHandler(Node *n) {
String *symname = Getattr(n,"sym:name");
int oldshadow;
/* Create the default member function */
oldshadow = shadow; /* Disable shadowing when wrapping member functions */
if (shadow) shadow = shadow | PYSHADOW_MEMBER;
Language::memberfunctionHandler(n);
shadow = oldshadow;
if (!Getattr(n,"sym:nextSibling")) {
if (shadow) {
int allow_kwargs = (use_kw || Getattr(n,"feature:kwargs")) ? 1 : 0;
if (Strcmp(symname,"__repr__") == 0)
have_repr = 1;
if (Getattr(n,"feature:shadow")) {
String *pycode = pythoncode(Getattr(n,"feature:shadow"),tab4);
Printv(f_shadow,pycode,"\n",NIL);
} else {
if (allow_kwargs && !Getattr(n,"sym:overloaded")) {
Printv(f_shadow,tab4, "def ", symname, "(*args, **kwargs): ", NIL);
Printv(f_shadow, "return apply(", module, ".", Swig_name_member(class_name,symname), ",args, kwargs)\n", NIL);
} else {
Printv(f_shadow, tab4, "def ", symname, "(*args): ", NIL);
Printv(f_shadow, "return apply(", module, ".", Swig_name_member(class_name,symname), ",args)\n",NIL);
}
}
}
}
return SWIG_OK;
}
/* ------------------------------------------------------------
* staticmemberfunctionHandler()
* ------------------------------------------------------------ */
virtual int staticmemberfunctionHandler(Node *n) {
String *symname = Getattr(n,"sym:name");
Language::staticmemberfunctionHandler(n);
if (shadow) {
Printv(f_shadow, tab4, "__swig_getmethods__[\"", symname, "\"] = lambda x: ", module, ".", Swig_name_member(class_name, symname), "\n", NIL);
if (!classic) {
Printv(f_shadow, tab4, "if _newclass:", symname, " = staticmethod(", module, ".",
Swig_name_member(class_name, symname), ")\n", NIL);
}
}
return SWIG_OK;
}
/* ------------------------------------------------------------
* constructorDeclaration()
* ------------------------------------------------------------ */
virtual int constructorHandler(Node *n) {
String *symname = Getattr(n,"sym:name");
int oldshadow = shadow;
int use_director = Swig_directorclass(n);
/*
* If we wrapping the constructor of a C++ director class, prepend a new parameter
* to receive the scripting language object (e.g. 'self')
*
*/
Swig_save("python:constructorHandler",n,"parms",NIL);
if (use_director) {
Parm *parms = Getattr(n, "parms");
Parm *self;
String *name = NewString("self");
String *type = NewString("PyObject");
SwigType_add_pointer(type);
self = NewParm(type, name);
Delete(type);
Delete(name);
Setattr(self, "lname", "O");
if (parms) set_nextSibling(self, parms);
Setattr(n, "parms", self);
Setattr(n, "wrap:self", "1");
Delete(self);
}
if (shadow) shadow = shadow | PYSHADOW_MEMBER;
Language::constructorHandler(n);
shadow = oldshadow;
Delattr(n, "wrap:self");
Swig_restore(n);
if (!Getattr(n,"sym:nextSibling")) {
if (shadow) {
int allow_kwargs = (use_kw || Getattr(n,"feature:kwargs")) ? 1 : 0;
if (!have_constructor) {
if (Getattr(n,"feature:shadow")) {
String *pycode = pythoncode(Getattr(n,"feature:shadow"),tab4);
Printv(f_shadow,pycode,"\n",NIL);
} else {
String *pass_self = NewString("");
Node *parent = Swig_methodclass(n);
String *classname = Swig_class_name(parent);
String *rclassname = Swig_class_name(getCurrentClass());
assert(rclassname);
if (use_director) {
Printv(pass_self, tab8, NIL);
Printf(pass_self, "if self.__class__ == %s:\n", classname);
Printv(pass_self, tab8, tab4, "args = (None,) + args\n",
tab8, "else:\n",
tab8, tab4, "args = (self,) + args\n",
NIL);
}
if ((allow_kwargs) && (!Getattr(n,"sym:overloaded"))) {
Printv(f_shadow, tab4, "def __init__(self,*args,**kwargs):\n", NIL);
Printv(f_shadow, pass_self, NIL);
Printv(f_shadow, tab8, "_swig_setattr(self, ", rclassname, ", 'this', apply(", module, ".", Swig_name_construct(symname), ",args, kwargs))\n", NIL);
} else {
Printv(f_shadow, tab4, "def __init__(self,*args):\n",NIL);
Printv(f_shadow, pass_self, NIL);
Printv(f_shadow, tab8, "_swig_setattr(self, ", rclassname, ", 'this', apply(", module, ".", Swig_name_construct(symname), ",args))\n", NIL);
}
Printv(f_shadow,
tab8, "_swig_setattr(self, ", rclassname, ", 'thisown', 1)\n",
NIL);
Delete(pass_self);
}
have_constructor = 1;
} else {
/* Hmmm. We seem to be creating a different constructor. We're just going to create a
function for it. */
if (Getattr(n,"feature:shadow")) {
String *pycode = pythoncode(Getattr(n,"feature:shadow"),"");
Printv(f_shadow_stubs,pycode,"\n",NIL);
} else {
if ((allow_kwargs) && (!Getattr(n,"sym:overloaded")))
Printv(f_shadow_stubs, "def ", symname, "(*args,**kwargs):\n", NIL);
else
Printv(f_shadow_stubs, "def ", symname, "(*args):\n", NIL);
Printv(f_shadow_stubs, tab4, "val = apply(", NIL);
if ((allow_kwargs) && (!Getattr(n,"sym:overloaded")))
Printv(f_shadow_stubs, module, ".", Swig_name_construct(symname), ",args,kwargs)\n", NIL);
else
Printv(f_shadow_stubs, module, ".", Swig_name_construct(symname), ",args)\n", NIL);
Printv(f_shadow_stubs,tab4, "val.thisown = 1\n",
tab4, "return val\n\n", NIL);
}
}
}
}
return SWIG_OK;
}
/* ------------------------------------------------------------
* destructorHandler()
* ------------------------------------------------------------ */
virtual int destructorHandler(Node *n) {
String *symname = Getattr(n,"sym:name");
int oldshadow = shadow;
if (shadow) shadow = shadow | PYSHADOW_MEMBER;
Language::destructorHandler(n);
shadow = oldshadow;
if (shadow) {
Printv(f_shadow, tab4, "def __del__(self, destroy= ", module, ".", Swig_name_destroy(symname), "):\n", NIL);
Printv(f_shadow, tab8, "try:\n", NIL);
Printv(f_shadow, tab4, tab8, "if self.thisown: destroy(self)\n", NIL);
Printv(f_shadow, tab8, "except: pass\n", NIL);
}
return SWIG_OK;
}
/* ------------------------------------------------------------
* membervariableHandler()
* ------------------------------------------------------------ */
virtual int membervariableHandler(Node *n) {
String *symname = Getattr(n,"sym:name");
int oldshadow = shadow;
if (shadow) shadow = shadow | PYSHADOW_MEMBER;
Language::membervariableHandler(n);
shadow = oldshadow;
if (shadow) {
int immutable = 0;
if (!Getattr(n,"feature:immutable")) {
Printv(f_shadow, tab4, "__swig_setmethods__[\"", symname, "\"] = ", module, ".", Swig_name_set(Swig_name_member(class_name,symname)), "\n", NIL);
} else {
immutable = 1;
}
Printv(f_shadow, tab4, "__swig_getmethods__[\"", symname, "\"] = ", module, ".", Swig_name_get(Swig_name_member(class_name,symname)),"\n", NIL);
if (!classic) {
if (immutable) {
Printv(f_shadow,tab4,"if _newclass:", symname," = property(", module, ".",
Swig_name_get(Swig_name_member(class_name,symname)),")\n", NIL);
} else {
Printv(f_shadow,tab4,"if _newclass:", symname," = property(",
module, ".", Swig_name_get(Swig_name_member(class_name,symname)),",",
module, ".", Swig_name_set(Swig_name_member(class_name,symname)),")\n", NIL);
}
}
}
return SWIG_OK;
}
/* ------------------------------------------------------------
* staticmembervariableHandler()
* ------------------------------------------------------------ */
virtual int staticmembervariableHandler(Node *n) {
String *symname;
SwigType *t;
Language::staticmembervariableHandler(n);
if (shadow) {
t = Getattr(n,"type");
symname = Getattr(n,"sym:name");
if (SwigType_isconst(t) && !Getattr(n, "value")) {
Printf(f_shadow,"%s%s = %s.%s.%s\n", tab4, symname, module, global_name, Swig_name_member(class_name,symname));
}
}
return SWIG_OK;
}
/* ------------------------------------------------------------
* memberconstantHandler()
* ------------------------------------------------------------ */
virtual int memberconstantHandler(Node *n) {
String *symname = Getattr(n,"sym:name");
int oldshadow = shadow;
if (shadow) shadow = shadow | PYSHADOW_MEMBER;
Language::memberconstantHandler(n);
shadow = oldshadow;
if (shadow) {
Printv(f_shadow, tab4, symname, " = ", module, ".", Swig_name_member(class_name,symname), "\n", NIL);
}
return SWIG_OK;
}
/* ------------------------------------------------------------
* pythoncode() - Output python code into the shadow file
* ------------------------------------------------------------ */
String *pythoncode(String *code, const String *indent) {
String *out = NewString("");
String *temp;
char *t;
if (!indent) indent = "";
temp = NewString(code);
t = Char(temp);
if (*t == '{') {
Delitem(temp,0);
Delitem(temp,DOH_END);
}
/* Split the input text into lines */
List *clist = DohSplit(temp,'\n',-1);
Delete(temp);
int initial = 0;
String *s;
/* Get the initial indentation */
for (s = Firstitem(clist); s; s = Nextitem(clist)) {
if (Len(s)) {
char *c = Char(s);
while (*c) {
if (!isspace(*c)) break;
initial++;
c++;
}
if (*c && !isspace(*c)) break;
else {
initial = 0;
}
}
}
while (s) {
if (Len(s) > initial) {
char *c = Char(s);
c += initial;
Printv(out,indent,c,"\n",NIL);
} else {
Printv(out,"\n",NIL);
}
s = Nextitem(clist);
}
Delete(clist);
return out;
}
/* ------------------------------------------------------------
* insertDirective()
*
* Hook for %insert directive. We're going to look for special %shadow inserts
* as a special case so we can do indenting correctly
* ------------------------------------------------------------ */
virtual int insertDirective(Node *n) {
String *code = Getattr(n,"code");
String *section = Getattr(n,"section");
if ((!ImportMode) && ((Cmp(section,"python") == 0) || (Cmp(section,"shadow") == 0))) {
if (shadow) {
String *pycode = pythoncode(code,shadow_indent);
Printv(f_shadow, pycode, "\n", NIL);
Delete(pycode);
}
} else {
Language::insertDirective(n);
}
return SWIG_OK;
}
};
/* -----------------------------------------------------------------------------
* swig_python() - Instantiate module
* ----------------------------------------------------------------------------- */
extern "C" Language *
swig_python(void) {
return new PYTHON();
}