swig/Source/Modules1.1/python.cxx
2000-07-24 04:01:26 +00:00

2121 lines
62 KiB
C++

/*******************************************************************************
* Simplified Wrapper and Interface Generator (SWIG)
*
* Author : David Beazley
*
* Department of Computer Science
* University of Chicago
* 1100 E 58th Street
* Chicago, IL 60637
* beazley@cs.uchicago.edu
*
* Please read the file LICENSE for the copyright and terms by which SWIG
* can be used and distributed.
*******************************************************************************/
static char cvsroot[] = "$Header$";
/**********************************************************************
* $Header$
*
* python.cxx
*
* Python module.
**************************************************************************/
#include "mod11.h"
#include "python.h"
struct Method { // Methods list. Needed to build methods
char *name; // Array at very end.
char *function;
int kw;
Method *next;
};
static Method *head = 0;
static DOHString *const_code = 0;
static DOHString *shadow_methods = 0;
static char *module = 0; // Module name
static char *path = (char*)"python"; // Pathname of where to look for library files
static char *global_name = (char*)"cvar"; // Name of global variables.
static int shadow = 0;
static int have_defarg = 0;
static int have_output;
static int use_kw = 0;
static int noopt = 1;
static FILE *f_shadow;
static DOHHash *hash;
static DOHHash *symbols;
static DOHString *classes;
static DOHString *func;
static DOHString *vars;
static DOHString *modinit;
static DOHString *modextern;
static char *import_file = 0;
static char *class_name;
static char *usage = (char *)"\
Python Options (available with -python)\n\
-globals name - Set name used to access C global variable ('cvar' by default).\n\
-module name - Set module name\n\
-keyword - Use keyword arguments\n\
-noopt - No optimized shadows (pre 1.5.2)\n\
-opt - Optimized shadow classes (1.5.2 or later)\n\
-shadow - Generate shadow classes. \n\n";
static DOHString *pragma_include = 0;
// ---------------------------------------------------------------------
// PYTHON::parse_args(int argc, char *argv[])
//
// ---------------------------------------------------------------------
void PYTHON::parse_args(int argc, char *argv[]) {
int i = 1;
sprintf(LibDir,"%s",path);
// Look for additional command line options.
for (i = 1; i < argc; i++) {
if (argv[i]) {
if(strcmp(argv[i],"-module") == 0) {
if (argv[i+1]) {
module = new char[strlen(argv[i+1])+2];
strcpy(module, argv[i+1]);
Swig_mark_arg(i);
Swig_mark_arg(i+1);
i+=1;
} else {
Swig_arg_error();
}
} else if (strcmp(argv[i],"-globals") == 0) {
if (argv[i+1]) {
global_name = new char[strlen(argv[i+1])+1];
strcpy(global_name, argv[i+1]);
Swig_mark_arg(i);
Swig_mark_arg(i+1);
i++;
} else {
Swig_arg_error();
}
} else if (strcmp(argv[i],"-shadow") == 0) {
shadow = 1;
Swig_mark_arg(i);
} else if (strcmp(argv[i],"-noopt") == 0) {
noopt = 1;
Swig_mark_arg(i);
} else if (strcmp(argv[i],"-opt") == 0) {
noopt = 0;
Swig_mark_arg(i);
} else if (strcmp(argv[i],"-keyword") == 0) {
use_kw = 1;
Swig_mark_arg(i);
} else if (strcmp(argv[i],"-help") == 0) {
fputs(usage,stderr);
}
}
}
// Create a symbol for this language
Preprocessor_define((void *) "SWIGPYTHON", 0);
// Set name of typemaps
typemap_lang = (char*)"python";
}
// ---------------------------------------------------------------------
// PYTHON::parse()
//
// Parse the interface file
// ---------------------------------------------------------------------
void
PYTHON::parse() {
printf("Generating wrappers for Python\n");
hash = NewHash();
symbols = NewHash();
const_code = NewString("");
shadow_methods = NewString("");
classes = NewString("");
func = NewString("");
vars = NewString("");
modinit = NewString("");
modextern = NewString("");
pragma_include = NewString("");
headers();
// Run the SWIG parser
yyparse();
}
// ---------------------------------------------------------------------
// PYTHON::set_module(char *mod_name, char **mod_list)
//
// Sets the module name.
// Does nothing if it's already set (so it can be overridden as a command
// line option).
//
//----------------------------------------------------------------------
void PYTHON::set_module(char *mod_name, char **mod_list) {
int i;
// If an "import" method has been set and we're in shadow class mode,
// output a python command to load the module
if (import_file) {
if (!(strcmp(import_file,input_file+strlen(input_file)-strlen(import_file)))) {
if (shadow) {
Printf(f_shadow,"\nfrom %s import *\n", mod_name);
}
free(import_file);
import_file = 0;
}
}
if (module) return;
module = new char[strlen(mod_name)+1];
strcpy(module,mod_name);
// If there was a mod_list specified, make this incredible hack
if (mod_list) {
Printf(modinit, "#define SWIGMODINIT ");
Printv(modextern,
"#ifdef __cplusplus\n",
"extern \"C\" {\n",
"#endif\n",
0);
i = 0;
while(mod_list[i]) {
Printv(modinit, "swig_add_module(\"", mod_list[i], "\",init", mod_list[i], "); \\\n", 0);
Printv(modextern, "extern void init", mod_list[i], "();\n", 0);
i++;
}
Printv(modextern,
"#ifdef __cplusplus\n",
"}\n",
"#endif\n",
0);
Printf(modinit,"/* End of extern module initialization */\n");
}
}
// ---------------------------------------------------------------------
// PYTHON::set_init(char *iname)
//
// Sets the initialization function name.
// Does nothing if it's already set
//
//----------------------------------------------------------------------
void PYTHON::set_init(char *iname) {
set_module(iname,0);
}
// ---------------------------------------------------------------------
// PYTHON::import(char *filename)
//
// Imports a SWIG module as a separate file.
//----------------------------------------------------------------------
void PYTHON::import(char *filename) {
if (import_file) free(import_file);
import_file = Swig_copy_string(filename);
}
// ----------------------------------------------------------------------
// PYTHON::add_method(char *name, char *function, int kw)
//
// Add some symbols to the methods table
// ----------------------------------------------------------------------
void PYTHON::add_method(char *name, char *function, int kw) {
Method *n;
n = new Method;
n->name = new char[strlen(name)+1];
strcpy(n->name,name);
n->function = new char[strlen(function)+1];
strcpy(n->function, function);
n->kw = kw;
n->next = head;
head = n;
}
// ---------------------------------------------------------------------
// PYTHON::print_methods()
//
// Prints out the method array.
// ---------------------------------------------------------------------
void PYTHON::print_methods() {
Method *n;
Printf(f_wrappers,"static PyMethodDef %sMethods[] = {\n", module);
n = head;
while (n) {
if (!n->kw) {
Printf(f_wrappers,"\t { \"%s\", %s, METH_VARARGS },\n", n->name, n->function);
} else {
Printf(f_wrappers,"\t { \"%s\", (PyCFunction) %s, METH_VARARGS | METH_KEYWORDS },\n", n->name, n->function);
}
n = n->next;
}
Printf(f_wrappers,"\t { NULL, NULL }\n");
Printf(f_wrappers,"};\n");
Printf(f_wrappers,"#ifdef __cplusplus\n");
Printf(f_wrappers,"}\n");
Printf(f_wrappers,"#endif\n");
}
// ---------------------------------------------------------------------
// PYTHON::headers(void)
//
// ----------------------------------------------------------------------
void PYTHON::headers(void)
{
Swig_banner(f_runtime);
Printf(f_runtime,"/* Implementation : PYTHON */\n\n");
Printf(f_runtime,"#define SWIGPYTHON\n");
if (NoInclude)
Printf(f_runtime,"#define SWIG_NOINCLUDE\n");
if (Swig_insert_file("python.swg", f_runtime) == -1) {
Printf(stderr,"SWIG : Fatal error. Unable to locate python.swg. (Possible installation problem).\n");
SWIG_exit(1);
}
}
// --------------------------------------------------------------------
// PYTHON::initialize(void)
//
// This function outputs the starting code for a function to initialize
// your interface. It is only called once by the parser.
//
// ---------------------------------------------------------------------
void PYTHON::initialize(void)
{
char filen[256];
char *temp;
char *oldmodule = 0;
if (!module) {
Printf(stderr,"*** Error. No module name specified.\n");
SWIG_exit(1);
}
// If shadow classing is enabled, we're going to change the module
// name to "modulec"
if (shadow) {
temp = new char[strlen(module)+2];
sprintf(temp,"%sc",module);
oldmodule = module;
module = temp;
}
/* Initialize the C code for the module */
initialize_cmodule();
/* Create a shadow file (if enabled).*/
if (shadow) {
sprintf(filen,"%s%s.py", output_dir, oldmodule);
if ((f_shadow = fopen(filen,"w")) == 0) {
Printf(stderr,"Unable to open %s\n", filen);
SWIG_exit(0);
}
Printf(f_shadow,"# This file was created automatically by SWIG.\n");
Printf(f_shadow,"import %s\n", module);
if (!noopt)
Printf(f_shadow,"import new\n");
}
// Dump out external module declarations
if (Len(modinit) > 0) {
Printf(f_header,"%s\n",modinit);
}
if (Len(modextern) > 0) {
Printf(f_header,"%s\n",modextern);
}
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");
}
// ---------------------------------------------------------------------
// PYTHON::initialize_cmodule(void)
//
// Initializes the C module.
//
// ---------------------------------------------------------------------
void PYTHON::initialize_cmodule(void)
{
Printf(f_header,"#define SWIG_init init%s\n\n", module);
Printf(f_header,"#define SWIG_name \"%s\"\n", module);
// Output the start of the init function.
// Modify this to use the proper return type and arguments used
// by the target Language
Printf(f_init,"static PyObject *SWIG_globals;\n");
Printf(f_init,"#ifdef __cplusplus\n");
Printf(f_init,"extern \"C\" \n");
Printf(f_init,"#endif\n");
Printf(f_init,"SWIGEXPORT(void) init%s(void) {\n",module);
Printf(f_init,"\t PyObject *m, *d;\n");
Printf(f_init,"\t SWIG_globals = SWIG_newvarlink();\n");
Printf(f_init,"\t m = Py_InitModule(\"%s\", %sMethods);\n", module, module);
Printf(f_init,"\t d = PyModule_GetDict(m);\n");
Printv(f_init,
tab4, "{\n",
tab8, "int i;\n",
tab8, "for (i = 0; _swig_types_initial[i]; i++) {\n",
tab8, tab4, "_swig_types[i] = SWIG_TypeRegister(_swig_types_initial[i]);\n",
tab8, "}\n",
tab4, "}\n",
0);
#ifdef SHADOW_METHODS
if (shadow) {
Printv(shadow_methods,
"static struct { \n",
tab4, "char *name;\n",
tab4, "char *classname;\n",
"} _swig_shadow_methods[] = {\n",
0);
}
#endif
}
// ---------------------------------------------------------------------
// PYTHON::close(void)
//
// Called when the end of the interface file is reached. Closes the
// initialization function and performs cleanup as necessary.
// ---------------------------------------------------------------------
void PYTHON::close(void)
{
print_methods();
close_cmodule();
if (shadow) {
Printv(f_shadow,
classes,
"\n\n#-------------- FUNCTION WRAPPERS ------------------\n\n",
func,
"\n\n#-------------- VARIABLE WRAPPERS ------------------\n\n",
vars,
0);
if (Len(pragma_include) > 0) {
Printv(f_shadow,
"\n\n#-------------- USER INCLUDE -----------------------\n\n",
pragma_include,
0);
}
fclose(f_shadow);
}
}
// --------------------------------------------------------------------
// PYTHON::close_cmodule(void)
//
// Called to cleanup the C module code
// --------------------------------------------------------------------
void PYTHON::close_cmodule(void)
{
emit_type_table(f_runtime);
/* emit_ptr_equivalence(f_init); */
Printf(const_code, "{0}};\n");
Printf(f_wrappers,"%s\n",const_code);
#ifdef SHADOW_METHODS
if (shadow) {
Printv(shadow_methods, tab4, "{0, 0}\n", "};\n", 0);
Printf(f_wrappers,"%s\n", shadow_methods);
}
#endif
Printv(f_init, tab4, "SWIG_InstallConstants(d,_swig_const_table);\n", 0);
#ifdef SHADOW_METHODS
// Not done yet. If doing shadows, create a bunch of instancemethod objects for use
if (shadow) {
Printv(f_init,
tab4, "{\n",
tab8, "PyObject *sd, *im, *co, *sclass;\n",
tab8, "int i;\n",
tab8, "sd = PyDict_New();\n",
tab8, "sclass = PyClass_New(NULL, sd, PyString_FromString(\"__shadow__\"));\n",
tab8, "for (i = 0; _swig_shadow_methods[i].name; i++) {\n",
tab8, tab4, "char *name;\n",
tab8, tab4, "name = _swig_shadow_methods[i].name;\n",
tab8, tab4, "co = PyDict_GetItemString(d,name);\n",
tab8, tab4, "im = PyMethod_New(co, NULL, sclass);\n",
tab8, tab4, "PyDict_SetItemString(sd,name,im);\n",
tab8, tab4, "}\n",
tab8, "PyDict_SetItemString(d,\"__shadow__\", sclass);\n",
tab4, "}\n",
0);
}
#endif
Printf(f_init,"}\n");
}
// ----------------------------------------------------------------------
// PYTHON::get_pointer(char *iname, char *srcname, char *src, char *target,
// DataType *t, DOHString *f, char *ret)
//
// Emits code to get a pointer and do type checking.
// iname = name of the function/method (used for error messages)
// srcname = Name of source (used for error message reporting).
// src = name of variable where source string is located.
// dest = name of variable where pointer value is stored.
// t = Expected datatype of the parameter
// f = Wrapper function object being used to generate code.
// ret = return code upon failure.
//
// Note : pointers are stored as strings so you first need to get
// a string and then call _swig_get_hex() to extract a point.
//
// This module is pretty ugly, but type checking is kind of nasty
// anyways.
// ----------------------------------------------------------------------
void
PYTHON::get_pointer(char *iname, char *srcname, char *src, char *dest,
DataType *t, DOHString *f, char *ret)
{
DataType_remember(t);
// Now get the pointer value from the string and save in dest
Printv(f,tab4, "if ((SWIG_ConvertPtr(", src, ",(void **) &", dest, ",", 0);
// If we're passing a void pointer, we give the pointer conversion a NULL
// pointer, otherwise pass in the expected type.
if (t->type == T_VOID) Printv(f, "0,1)) == -1) return ", ret, ";\n", 0);
else
Printv(f,"SWIGTYPE", DataType_manglestr(t), ",1)) == -1) return ", ret, ";\n", 0);
}
// ----------------------------------------------------------------------
// PYTHON::emit_function_header()
//
// Return the code to be used as a function header
// ----------------------------------------------------------------------
void PYTHON::emit_function_header(Wrapper *emit_to, char *wname)
{
if (!use_kw) {
Printv(emit_to->def,
"static PyObject *", wname,
"(PyObject *self, PyObject *args) {",
0);
} else {
Printv(emit_to->def,
"static PyObject *", wname,
"(PyObject *self, PyObject *args, PyObject *kwargs) {",
0);
}
Printf(emit_to->code," self = self;\n");
}
// ----------------------------------------------------------------------
// PYTHON::convert_self()
//
// Called during the function generation process, to determine what to
// use as the "self" variable during the call. Derived classes may emit code
// to convert the real self pointer into a usable pointer.
//
// Returns the name of the variable to use as the self pointer
// ----------------------------------------------------------------------
char *PYTHON::convert_self(Wrapper *f)
{
// Default behaviour is no translation
return (char*)"";
}
// ----------------------------------------------------------------------
// PYTHON::make_funcname_wrapper()
//
// Called to create a name for a wrapper function
// ----------------------------------------------------------------------
char *PYTHON::make_funcname_wrapper(char *fnName)
{
return Swig_name_wrapper(fnName);
}
// ----------------------------------------------------------------------
// PYTHON::create_command(char *cname, char *iname)
//
// Create a new command in the interpreter. Used for C++ inheritance
// stuff.
// ----------------------------------------------------------------------
void PYTHON::create_command(char *cname, char *iname) {
// Create the name of the wrapper function
char *wname = Swig_name_wrapper(cname);
// Now register the function with the interpreter.
add_method(iname, wname, use_kw);
}
// ----------------------------------------------------------------------
// PYTHON::create_function(char *name, char *iname, DataType *d,
// ParmList *l)
//
// This function creates a wrapper function and registers it with the
// interpreter.
//
// Inputs :
// name = actual name of the function that's being wrapped
// iname = name of the function in the interpreter (may be different)
// d = Return datatype of the functions.
// l = A linked list containing function parameter information.
//
// ----------------------------------------------------------------------
void PYTHON::create_function(char *name, char *iname, DataType *d, ParmList *l)
{
Parm *p;
int pcount,i,j;
char wname[256], self_name[256], call_name[256];
char source[64], target[64], temp[256], argnum[20];
char *usage = 0;
Wrapper *f;
DOHString *parse_args;
DOHString *arglist;
DOHString *get_pointers;
DOHString *cleanup;
DOHString *outarg;
DOHString *check;
DOHString *kwargs;
char *tm;
int numopt = 0;
f = NewWrapper();
parse_args = NewString("");
arglist = NewString("");
get_pointers = NewString("");
cleanup = NewString("");
outarg = NewString("");
check = NewString("");
kwargs = NewString("");
have_output = 0;
// Make a valid name for this function. This removes special symbols
// that would cause problems in the C compiler.
strcpy(wname,make_funcname_wrapper(iname));
// Now emit the function declaration for the wrapper function. You
// should modify this to return the appropriate types and use the
// appropriate parameters.
emit_function_header(f, wname);
Wrapper_add_local(f,"resultobj", "PyObject *resultobj");
// Get the function usage string for later use
usage = usage_func(iname,d,l);
// Write code to extract function parameters.
// This is done in one pass, but we need to construct three independent
// pieces.
// 1. Python format string such as "iis"
// 2. The actual arguments to put values into
// 3. Pointer conversion code.
//
// If there is a type mapping, we will extract the Python argument
// as a raw PyObject and let the user deal with it.
//
pcount = emit_args(d, l, f);
if (!use_kw) {
Printf(parse_args," if(!PyArg_ParseTuple(args,\"");
} else {
Printf(parse_args," if(!PyArg_ParseTupleAndKeywords(args,kwargs,\"");
Printf(arglist,",kwnames");
}
i = 0;
j = 0;
numopt = check_numopt(l); // Get number of optional arguments
if (numopt) have_defarg = 1;
p = ParmList_first(l);
Printf(kwargs,"{ ");
while (p != 0) {
DataType *pt = Parm_Gettype(p);
char *pn = Parm_Getname(p);
char *pv = Parm_Getvalue(p);
// Generate source and target strings
sprintf(source,"obj%d",i);
sprintf(target,Parm_Getlname(p));
sprintf(argnum,"%d",j+1);
// Only consider this argument if it's not ignored
if (!Parm_Getignore(p)) {
Putc(',',arglist);
// Add an optional argument separator if needed
if (j == pcount-numopt) {
Putc('|',parse_args);
}
if (strlen(pn)) {
Printf(kwargs,"\"%s\",", pn);
} else {
Printf(kwargs,"\"arg%d\",", j+1);
}
// Look for input typemap
if ((tm = typemap_lookup((char*)"in",(char*)"python",pt,pn,source,target,f))) {
Putc('O',parse_args);
Wrapper_add_localv(f, source, "PyObject *",source,0);
Printf(arglist,"&%s",source);
if (i >= (pcount-numopt))
Printv(get_pointers, tab4, "if (", source, ")\n",
tm, "\n",
0);
Replace(get_pointers,"$argnum", argnum, DOH_REPLACE_ANY);
Replace(get_pointers,"$arg",source, DOH_REPLACE_ANY);
} else {
// Check if this parameter is a pointer. If not, we'll get values
if (!pt->is_pointer) {
// Extract a parameter by "value"
switch(pt->type) {
// Handle integers here. Usually this can be done as a single
// case if you appropriate cast things. However, if you have
// special cases, you'll need to add more code.
case T_INT : case T_UINT:
Putc('i',parse_args);
break;
case T_SHORT: case T_USHORT:
Putc('h',parse_args);
break;
case T_LONG : case T_ULONG:
Putc('l',parse_args);
break;
case T_SCHAR : case T_UCHAR :
Putc('b',parse_args);
break;
case T_CHAR:
Putc('c',parse_args);
break;
case T_FLOAT :
Putc('f',parse_args);
break;
case T_DOUBLE:
Putc('d',parse_args);
break;
case T_BOOL:
{
char tempb[128];
char tempval[128];
if (pv) {
sprintf(tempval, "(int) %s", pv);
}
sprintf(tempb,"tempbool%d",i);
Putc('i',parse_args);
if (!pv)
Wrapper_add_localv(f,tempb,"int",tempb,0);
else
Wrapper_add_localv(f,tempb,"int",tempb, "=",tempval,0);
Printv(get_pointers, tab4, target, " = (", DataType_lstr(pt,0), ") ", tempb, ";\n", 0);
Printf(arglist,"&%s",tempb);
}
break;
// Void.. Do nothing.
case T_VOID :
break;
case T_USER:
Putc('O',parse_args);
sprintf(source,"argo%d", i);
sprintf(target,Parm_Getlname(p));
sprintf(temp,"argument %d",i+1);
Wrapper_add_localv(f,source,"PyObject *",source,"=0",0);
Printf(arglist,"&%s",source);
pt->is_pointer++;
get_pointer(iname, temp, source, target, pt, get_pointers, (char*)"NULL");
pt->is_pointer--;
// Unsupported data type
break;
default :
Printf(stderr,"%s : Line %d. Unable to use type %s as a function argument.\n",input_file, line_number, DataType_str(pt,0));
break;
}
// Emit code for parameter list
if ((pt->type != T_VOID) && (pt->type != T_BOOL) && (pt->type != T_USER))
Printf(arglist,"&%s",Parm_Getlname(p));
} else {
// Is some other kind of variable.
if ((pt->type == T_CHAR) && (pt->is_pointer == 1)) {
Putc('s',parse_args);
Printf(arglist,"&%s", Parm_Getlname(p));
} else {
// Have some sort of pointer variable. Create a temporary local
// variable for the string and read the pointer value into it.
Putc('O',parse_args);
sprintf(source,"argo%d", i);
sprintf(target,"%s",Parm_Getlname(p));
sprintf(temp,"argument %d",i+1);
Wrapper_add_localv(f,source,"PyObject *",source,"=0",0);
Printf(arglist,"&%s",source);
get_pointer(iname, temp, source, target, pt, get_pointers, (char*)"NULL");
}
}
}
j++;
}
// Check if there was any constraint code
if ((tm = typemap_lookup((char*)"check",(char*)"python",pt,pn,source,target))) {
Printf(check,"%s\n",tm);
Replace(check,"$argnum", argnum, DOH_REPLACE_ANY);
}
// Check if there was any cleanup code
if ((tm = typemap_lookup((char*)"freearg",(char*)"python",pt,pn,target,source))) {
Printf(cleanup,"%s\n",tm);
Replace(cleanup,"$argnum", argnum, DOH_REPLACE_ANY);
Replace(cleanup,"$arg",source, DOH_REPLACE_ANY);
}
if ((tm = typemap_lookup((char*)"argout",(char*)"python",pt,pn,target,(char*)"resultobj"))) {
Printf(outarg,"%s\n", tm);
Replace(outarg,"$argnum",argnum,DOH_REPLACE_ANY);
Replace(outarg,"$arg",source, DOH_REPLACE_ANY);
have_output++;
}
p = ParmList_next(l);
i++;
}
Printf(kwargs," NULL }");
if (use_kw) {
Printv(f->locals,tab4, "char *kwnames[] = ", kwargs, ";\n", 0);
}
Printf(parse_args,":%s\"", iname);
Printv(parse_args,
arglist, ")) return NULL;\n",
0);
strcpy(self_name,convert_self(f));
/* Now slap the whole first part of the wrapper function together */
Printv(f->code, parse_args, get_pointers, check, 0);
// This function emits code to call the real function. Assuming you read
// the parameters in correctly, this will work.
sprintf(call_name,"%s%s",self_name,name);
emit_func_call(call_name,d,l,f);
// Now emit code to return the functions return value (if any).
// If there was a result, it was saved in result.
// If the function is a void type, don't do anything.
if ((tm = typemap_lookup((char*)"out",(char*)"python",d,iname,(char*)"result",(char*)"resultobj"))) {
// Yep. Use it instead of the default
Printf(f->code,"%s\n", tm);
} else {
if ((d->type != T_VOID) || (d->is_pointer)) {
// Now have return value, figure out what to do with it.
if (!d->is_pointer) {
// Function returns a "value"
switch(d->type) {
// Return an integer type
case T_INT: case T_UINT: case T_BOOL:
Printf(f->code," resultobj = Py_BuildValue(\"i\",result);\n");
break;
case T_SHORT: case T_USHORT:
Printf(f->code," resultobj = Py_BuildValue(\"h\",result);\n");
break;
case T_LONG : case T_ULONG:
Printf(f->code," resultobj = Py_BuildValue(\"l\",result);\n");
break;
case T_SCHAR: case T_UCHAR :
Printf(f->code," resultobj = Py_BuildValue(\"b\",result);\n");
break;
// Return a floating point value
case T_DOUBLE :
Printf(f->code," resultobj = Py_BuildValue(\"d\",result);\n");
break;
case T_FLOAT :
Printf(f->code," resultobj = Py_BuildValue(\"f\",result);\n");
break;
// Return a single ASCII value. Usually we need to convert
// it to a NULL-terminate string and return that instead.
case T_CHAR :
Printf(f->code," resultobj = Py_BuildValue(\"c\",result);\n");
break;
case T_USER :
d->is_pointer++;
DataType_remember(d);
Printv(f->code,tab4, "resultobj = SWIG_NewPointerObj((void *)result, SWIGTYPE", DataType_manglestr(d), ");\n",0);
d->is_pointer--;
break;
default :
Printf(stderr,"%s: Line %d. Unable to use return type %s in function %s.\n", input_file, line_number, DataType_str(d,0), name);
break;
}
} else {
// Return type is a pointer. We'll see if it's a char * and return
// a string. Otherwise, we'll convert it into a SWIG pointer and return
// that.
if ((d->type == T_CHAR) && (d->is_pointer == 1)) {
// Return a character string
Printf(f->code," resultobj = Py_BuildValue(\"s\", result);\n");
// If declared as a new object, free the result
} else {
// Build a SWIG pointer.
DataType_remember(d);
Printv(f->code, tab4, "resultobj = SWIG_NewPointerObj((void *) result, SWIGTYPE", DataType_manglestr(d), ");\n", 0);
}
}
} else {
Printf(f->code," Py_INCREF(Py_None);\n");
Printf(f->code," resultobj = Py_None;\n");
}
}
// Check to see if there were any output arguments, if so we're going to
// create a Python list object out of the current result
Printv(f->code,outarg,0);
// If there was any other cleanup needed, do that
Printv(f->code,cleanup,0);
// Look to see if there is any newfree cleanup code
if (NewObject) {
if ((tm = typemap_lookup((char*)"newfree",(char*)"python",d,iname,(char*)"result",(char*)""))) {
Printf(f->code,"%s\n",tm);
}
}
// See if there is any argument cleanup code
if ((tm = typemap_lookup((char*)"ret",(char*)"python",d,iname,(char*)"result",(char*)""))) {
// Yep. Use it instead of the default
Printf(f->code,"%s\n",tm);
}
Printf(f->code," return resultobj;\n}\n");
// Substitute the cleanup code
Replace(f->code,"$cleanup",cleanup, DOH_REPLACE_ANY);
// Substitute the function name
Replace(f->code,"$name",iname, DOH_REPLACE_ANY);
// Dump the function out
Wrapper_print(f,f_wrappers);
// Now register the function with the interpreter.
add_method(iname, wname, use_kw);
#ifdef SHADOW_METHODS
if (shadow && (shadow & PYSHADOW_MEMBER)) {
Printv(shadow_methods, tab4, "{ \"", iname, "\", \"", class_name, "\" },\n", 0);
}
#endif
// ---------------------------------------------------------------------------
// Create a shadow for this function (if enabled and not in a member function)
// ---------------------------------------------------------------------------
if ((shadow) && (!(shadow & PYSHADOW_MEMBER))) {
int need_wrapper = 0;
int munge_return = 0;
// Check return code for modification
if ((Getattr(hash,d->name)) && (d->is_pointer <=1)) {
need_wrapper = 1;
munge_return = 1;
}
// If no modification is needed. We're just going to play some
// symbol table games instead
if (!need_wrapper) {
Printv(func,iname, " = ", module, ".", iname, "\n\n", 0);
} else {
Printv(func,"def ", iname, "(*args, **kwargs):\n", 0);
Printv(func, tab4, "val = apply(", module, ".", iname, ",args,kwargs)\n",0);
if (munge_return) {
// If the output of this object has been remapped in any way, we're
// going to return it as a bare object.
if (!typemap_check((char*)"out",typemap_lang,d,iname)) {
// If there are output arguments, we are going to return the value
// unchanged. Otherwise, emit some shadow class conversion code.
if (!have_output) {
Printv(func, tab4, "if val: val = ", GetChar(hash,d->name), "Ptr(val)", 0);
if (((Getattr(hash,d->name)) && (d->is_pointer < 1)) ||
((Getattr(hash,d->name)) && (d->is_pointer == 1) && NewObject))
Printf(func, "; val.thisown = 1\n");
else
Printf(func,"\n");
} else {
// Does nothing--returns the value unmolested
}
}
}
Printv(func, tab4, "return val\n\n", 0);
}
}
Delete(parse_args);
Delete(arglist);
Delete(get_pointers);
Delete(cleanup);
Delete(outarg);
Delete(check);
Delete(kwargs);
DelWrapper(f);
}
// -----------------------------------------------------------------------
// PYTHON::link_variable(char *name, char *iname, DataType *d)
//
// Input variables:
// name = the real name of the variable being linked
// iname = Name of the variable in the interpreter (may be different)
// d = Datatype of the variable.
//
// This creates a pair of functions for evaluating/setting the value
// of a variable. These are then added to the special SWIG global
// variable type.
// -----------------------------------------------------------------------
void PYTHON::link_variable(char *name, char *iname, DataType *t) {
char *wname;
static int have_globals = 0;
char *tm;
Wrapper *getf, *setf;
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,\"%s\", SWIG_globals);\n",global_name);
have_globals=1;
if ((shadow) && (!(shadow & PYSHADOW_MEMBER))) {
Printv(vars, global_name, " = ", module, ".", global_name, "\n", 0);
}
}
// First make a sanitized version of the function name (in case it's some
// funky C++ thing).
wname = Swig_name_wrapper(name);
// ---------------------------------------------------------------------
// Create a function for setting the value of the variable
// ---------------------------------------------------------------------
Printf(setf->def,"static int %s_set(PyObject *val) {", wname);
if (!(Status & STAT_READONLY)) {
if ((tm = typemap_lookup((char*)"varin",(char*)"python",t,name,(char*)"val",name))) {
Printf(setf->code,"%s\n",tm);
Replace(setf->code,"$name",iname, DOH_REPLACE_ANY);
} else {
if ((t->type != T_VOID) || (t->is_pointer)) {
if (!t->is_pointer) {
// Have a real value here
switch(t->type) {
case T_INT: case T_SHORT: case T_LONG :
case T_UINT: case T_USHORT: case T_ULONG:
case T_SCHAR: case T_UCHAR: case T_BOOL:
// Get an integer value
Wrapper_add_localv(setf,"tval",DataType_lstr(t,0),"tval",0);
Printv(setf->code,
tab4, "tval = (", DataType_lstr(t,0), ") PyInt_AsLong(val);\n",
tab4, "if (PyErr_Occurred()) {\n",
tab8, "PyErr_SetString(PyExc_TypeError,\"C variable '",
iname, "'(", DataType_str(t,0), ")\");\n",
tab8, "return 1; \n",
tab4, "}\n",
tab4, name, " = tval;\n",
0);
break;
case T_FLOAT: case T_DOUBLE:
// Get a floating point value
Wrapper_add_localv(setf,"tval",DataType_lstr(t,0), "tval",0);
Printv(setf->code,
tab4, "tval = (", DataType_lstr(t,0), ") PyFloat_AsDouble(val);\n",
tab4, "if (PyErr_Occurred()) {\n",
tab8, "PyErr_SetString(PyExc_TypeError,\"C variable '",
iname, "'(", DataType_str(t,0), ")\");\n",
tab8, "return 1; \n",
tab4, "}\n",
tab4, name, " = tval;\n",
0);
break;
// A single ascii character
case T_CHAR:
Wrapper_add_local(setf,"tval","char * tval");
Printv(setf->code,
tab4, "tval = (char *) PyString_AsString(val);\n",
tab4, "if (PyErr_Occurred()) {\n",
tab8, "PyErr_SetString(PyExc_TypeError,\"C variable '",
iname, "'(", DataType_str(t,0), ")\");\n",
tab8, "return 1; \n",
tab4, "}\n",
tab4, name, " = *tval;\n",
0);
break;
case T_USER:
t->is_pointer++;
Wrapper_add_localv(setf,"temp",DataType_lstr(t,0),"temp",0);
get_pointer(iname,(char*)"value",(char*)"val",(char*)"temp",t,setf->code,(char*)"1");
Printv(setf->code, tab4, name, " = *temp;\n", 0);
t->is_pointer--;
break;
default:
Printf(stderr,"%s : Line %d. Unable to link with type %s.\n", input_file, line_number, DataType_str(t,0));
}
} else {
// Parse a pointer value
if ((t->type == T_CHAR) && (t->is_pointer == 1)) {
Wrapper_add_local(setf,"tval","char * tval");
Printv(setf->code,
tab4, "tval = (char *) PyString_AsString(val);\n",
tab4, "if (PyErr_Occurred()) {\n",
tab8, "PyErr_SetString(PyExc_TypeError,\"C variable '",
iname, "'(", DataType_str(t,0), ")\");\n",
tab8, "return 1; \n",
tab4, "}\n",
0);
if (CPlusPlus) {
Printv(setf->code,
tab4, "if (", name, ") delete [] ", name, ";\n",
tab4, name, " = new char[strlen(tval)+1];\n",
tab4, "strcpy((char *)", name, ",tval);\n",
0);
} else {
Printv(setf->code,
tab4, "if (", name, ") free(", name, ");\n",
tab4, name, " = (char *) malloc(strlen(tval)+1);\n",
tab4, "strcpy((char *)", name, ",tval);\n",
0);
}
} else {
// Is a generic pointer value.
Wrapper_add_localv(setf,"temp", DataType_lstr(t,0), "temp",0);
get_pointer(iname,(char*)"value",(char*)"val",(char*)"temp",t,setf->code,(char*)"1");
Printv(setf->code,tab4, name, " = temp;\n", 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",
0);
}
Printf(setf->code,"}\n");
// Dump out function for setting value
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 = typemap_lookup((char*)"varout",(char*)"python",t,name,name,(char*)"pyobj"))) {
Printf(getf->code,"%s\n",tm);
Replace(getf->code,"$name",iname, DOH_REPLACE_ANY);
} else if ((tm = typemap_lookup((char*)"out",(char*)"python",t,name,name,(char*)"pyobj"))) {
Printf(getf->code,"%s\n",tm);
Replace(getf->code,"$name",iname, DOH_REPLACE_ANY);
} else {
if ((t->type != T_VOID) || (t->is_pointer)) {
if (!t->is_pointer) {
/* Is a normal datatype */
switch(t->type) {
case T_INT: case T_UINT:
case T_SHORT: case T_USHORT:
case T_LONG: case T_ULONG:
case T_SCHAR: case T_UCHAR: case T_BOOL:
Printv(getf->code, tab4, "pyobj = PyInt_FromLong((long) ", name, ");\n", 0);
break;
case T_FLOAT: case T_DOUBLE:
Printv(getf->code, tab4, "pyobj = PyFloat_FromDouble((double) ", name, ");\n", 0);
break;
case T_CHAR:
Wrapper_add_local(getf,"ptemp","char ptemp[2]");
Printv(getf->code,
tab4, "ptemp[0] = ", name, ";\n",
tab4, "ptemp[1] = 0;\n",
tab4, "pyobj = PyString_FromString(ptemp);\n",
0);
break;
case T_USER:
// Hack this into a pointer
t->is_pointer++;
DataType_remember(t);
Printv(getf->code,
tab4, "pyobj = SWIG_NewPointerObj((void *) &", name ,
", SWIGTYPE", DataType_manglestr(t), ");\n",
0);
t->is_pointer--;
break;
default:
Printf(stderr,"Unable to link with type %s\n", DataType_str(t,0));
break;
}
} else {
// Is some sort of pointer value
if ((t->type == T_CHAR) && (t->is_pointer == 1)) {
Printv(getf->code,
tab4, "if (", name, ")\n",
tab8, "pyobj = PyString_FromString(", name, ");\n",
tab4, "else pyobj = PyString_FromString(\"(NULL)\");\n",
0);
} else {
DataType_remember(t);
Printv(getf->code,
tab4, "pyobj = SWIG_NewPointerObj((void *)", name,
", SWIGTYPE", DataType_manglestr(t), ");\n",
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,\"%s\",%s_get, %s_set);\n", iname, wname, wname);
// ----------------------------------------------------------
// Output a shadow variable. (If applicable and possible)
// ----------------------------------------------------------
if ((shadow) && (!(shadow & PYSHADOW_MEMBER))) {
if ((Getattr(hash,t->name)) && (t->is_pointer <= 1)) {
Printv(vars,
iname, " = ", GetChar(hash,t->name), "Ptr(", module, ".", global_name,
".", iname, ")\n",
0);
}
}
DelWrapper(setf);
DelWrapper(getf);
}
// -----------------------------------------------------------------------
// PYTHON::declare_const(char *name, char *iname, DataType *type, char *value)
//
// Makes a constant as defined with #define. Constants are added to the
// module's dictionary and are **NOT** guaranteed to be read-only,
// sorry.
//
// ------------------------------------------------------------------------
void PYTHON::declare_const(char *name, char *, DataType *type, char *value) {
char *tm;
// Make a static python object
if ((tm = typemap_lookup((char*)"const",(char*)"python",type,name,value,name))) {
Printf(const_code,"%s\n", tm);
} else {
if ((type->type == T_USER) && (!type->is_pointer)) {
Printf(stderr,"%s : Line %d. Unsupported constant value.\n", input_file, line_number);
return;
}
if (type->is_pointer == 0) {
switch(type->type) {
case T_INT: case T_UINT: case T_BOOL:
case T_SHORT: case T_USHORT:
case T_LONG: case T_ULONG:
case T_SCHAR: case T_UCHAR:
Printv(const_code, tab4, "{ SWIG_PY_INT, \"", name, "\", (long) ", value, ", 0, 0, 0},\n", 0);
break;
case T_DOUBLE:
case T_FLOAT:
Printv(const_code, tab4, "{ SWIG_PY_FLOAT, \"", name, "\", 0, (double) ", value, ", 0,0},\n", 0);
break;
case T_CHAR :
Printv(const_code, tab4, "{ SWIG_PY_STRING, \"", name, "\", 0, 0, (void *) \"", value, "\", 0},\n", 0);
break;
default:
Printf(stderr,"%s : Line %d. Unsupported constant value.\n", input_file, line_number);
break;
}
} else {
if ((type->type == T_CHAR) && (type->is_pointer == 1)) {
Printv(const_code,tab4, "{ SWIG_PY_STRING, \"", name, "\", 0, 0, (void *) \"", value, "\", 0},\n", 0);
} else {
// A funky user-defined type. We're going to munge it into a string pointer value
DataType_remember(type);
Printv(const_code, tab4, "{ SWIG_PY_POINTER, \"", name, "\", 0, 0, (void *) ", value, ", &SWIGTYPE", DataType_manglestr(type), "}, \n", 0);
}
}
}
if ((shadow) && (!(shadow & PYSHADOW_MEMBER))) {
Printv(vars,name, " = ", module, ".", name, "\n", 0);
}
}
// ----------------------------------------------------------------------
// PYTHON::usage_var(char *iname, DataType *t)
//
// This function produces a string indicating how to use a variable.
// It is called by the documentation system to produce syntactically
// correct documentation entires.
//
// s is a pointer to a character pointer. You should create
// a string and set this pointer to point to it.
// ----------------------------------------------------------------------
char *PYTHON::usage_var(char *iname, DataType *) {
static char temp[512];
sprintf(temp,"%s.%s", global_name,iname);
// Create result. Don't modify this
return temp;
}
// ---------------------------------------------------------------------------
// PYTHON::usage_func(char *iname, DataType *t, ParmList *l)
//
// Produces a string indicating how to call a function in the target
// language.
//
// ---------------------------------------------------------------------------
char *PYTHON::usage_func(char *iname, DataType *, ParmList *l) {
static DOHString *temp = 0;
Parm *p;
int i;
if (!temp) temp = NewString("");
Clear(temp);
Printf(temp,"%s(", iname);
// Now go through and print parameters
// You probably don't need to change this
i = 0;
p = ParmList_first(l);
while (p != 0) {
DataType *pt = Parm_Gettype(p);
char *pn = Parm_Getname(p);
if (!Parm_Getignore(p)) {
i++;
/* If parameter has been named, use that. Otherwise, just print a type */
if ((pt->type != T_VOID) || (pt->is_pointer)) {
if (strlen(pn) > 0) {
Printf(temp,"%s",pn);
} else {
Printf(temp,"%s", DataType_str(pt,0));
}
}
p = ParmList_next(l);
if (p != 0) {
if (!Parm_Getignore(p))
Putc(',',temp);
}
} else {
p = ParmList_next(l);
if (p) {
if ((!Parm_Getignore(p)) && (i > 0))
Putc(',',temp);
}
}
}
Putc(')',temp);
return Char(temp);
}
// ----------------------------------------------------------------------
// PYTHON::usage_const(char *iname, DataType *type, char *value)
//
// Produces a string for a constant. Really about the same as
// usage_var() except we'll indicate the value of the constant.
// ----------------------------------------------------------------------
char *PYTHON::usage_const(char *iname, DataType *, char *value) {
static char temp[1024];
sprintf(temp,"%s = %s", iname, value);
return temp;
}
// -----------------------------------------------------------------------
// PYTHON::add_native(char *name, char *funcname, DataType *, ParmList *)
//
// Add a native module name to the methods list.
// -----------------------------------------------------------------------
void PYTHON::add_native(char *name, char *funcname, DataType *, ParmList *) {
add_method(name, funcname,0);
if (shadow) {
Printv(func, name, " = ", module, ".", name, "\n\n", 0);
}
}
// -----------------------------------------------------------------------
// PYTHON::cpp_class_decl(char *name, char *rename, char *type)
//
// Treatment of an empty class definition. Used to handle
// shadow classes across modules.
// -----------------------------------------------------------------------
void PYTHON::cpp_class_decl(char *name, char *rename, char *type) {
char temp[256];
if (shadow) {
Setattr(hash,name,rename);
// Add full name of datatype to the hash table
if (strlen(type) > 0) {
sprintf(temp,"%s %s", type, name);
Setattr(hash,temp,rename);
}
}
}
// -----------------------------------------------------------------------
// PYTHON::pragma(char *name, char *type)
//
// Pragma directive. Used to do various python specific things
// -----------------------------------------------------------------------
void PYTHON::pragma(char *lang, char *cmd, char *value) {
if (strcmp(lang,(char*)"python") == 0) {
if (strcmp(cmd,"CODE") == 0) {
if (shadow) {
Printf(f_shadow,"%s\n",value);
}
} else if (strcmp(cmd,"code") == 0) {
if (shadow) {
Printf(f_shadow,"%s\n",value);
}
} else if (strcmp(cmd,"include") == 0) {
if (shadow) {
if (value) {
FILE *f = Swig_open(value);
if (!f) {
Printf(stderr,"%s : Line %d. Unable to locate file %s\n", input_file, line_number,value);
} else {
char buffer[4096];
while (fgets(buffer,4095,f)) {
Printv(pragma_include,buffer,0);
}
}
}
}
} else {
Printf(stderr,"%s : Line %d. Unrecognized pragma.\n", input_file, line_number);
}
}
}
struct PyPragma {
DOHString *m_method;
DOHString *m_text;
PyPragma *next;
PyPragma(char *method, char *text) {
m_method = NewString(method);
m_text = NewString(text);
next = 0;
}
~PyPragma() {
Delete(m_method);
Delete(m_text);
if (next) delete next;
}
};
static PyPragma *pragmas = 0;
// -----------------------------------------------------------------------------
// PYTHON::cpp_pragma(Pragma *plist)
//
// Handle C++ pragmas
// -----------------------------------------------------------------------------
void PYTHON::cpp_pragma(Pragma *plist) {
PyPragma *pyp1 = 0, *pyp2 = 0;
if (pragmas) {
delete pragmas;
pragmas = 0;
}
while (plist) {
if (strcmp(Char(plist->lang),(char*)"python") == 0) {
if (strcmp(Char(plist->name),"addtomethod") == 0) {
// parse value, expected to be in the form "methodName:line"
DOHString *temp = NewString(plist->value);
char* txtptr = strchr(Char(temp), ':');
if (txtptr) {
// add name and line to a list in current_class
*txtptr = 0;
txtptr++;
pyp1 = new PyPragma(Char(temp),txtptr);
pyp1->next = 0;
if (pyp2) {
pyp2->next = pyp1;
pyp2 = pyp1;
} else {
pragmas = pyp1;
pyp2 = pragmas;
}
} else {
Printf(stderr,"%s : Line %d. Malformed addtomethod pragma. Should be \"methodName:text\"\n",
Char(plist->filename),plist->lineno);
}
Delete(temp);
} else if (strcmp(Char(plist->name), "addtoclass") == 0) {
pyp1 = new PyPragma((char*)"__class__",Char(plist->value));
pyp1->next = 0;
if (pyp2) {
pyp2->next = pyp1;
pyp2 = pyp1;
} else {
pragmas = pyp1;
pyp2 = pragmas;
}
}
}
plist = plist->next;
}
}
// --------------------------------------------------------------------------------
// PYTHON::emitAddPragmas(String& output, char* name, char* spacing);
//
// Search the current class pragma for any text belonging to name.
// Append the text properly spaced to the output string.
// --------------------------------------------------------------------------------
void PYTHON::emitAddPragmas(DOHString *output, char* name, char* spacing)
{
PyPragma *p = pragmas;
while (p) {
if (strcmp(Char(p->m_method),name) == 0) {
Printv(output,spacing,p->m_text,"\n",0);
}
p = p->next;
}
}
/**********************************************************************
* C++ Support + Shadow Classes
**************************************************************************/
static DOHString *setattr = 0;
static DOHString *getattr = 0;
static DOHString *csetattr = 0;
static DOHString *cgetattr = 0;
static DOHString *pyclass = 0;
static DOHString *imethod = 0;
static DOHString *construct = 0;
static DOHString *cinit = 0;
static DOHString *additional = 0;
static int have_constructor;
static int have_destructor;
static int have_getattr;
static int have_setattr;
static int have_repr;
static char *class_type;
static char *real_classname;
static DOHString *base_class = 0;
static int class_renamed = 0;
// --------------------------------------------------------------------------
// PYTHON::cpp_open_class(char *classname, char *rname, char *ctype, int strip)
//
// Opens a new C++ class or structure.
// --------------------------------------------------------------------------
void PYTHON::cpp_open_class(char *classname, char *rname, char *ctype, int strip) {
char temp[256];
this->Language::cpp_open_class(classname, rname, ctype, strip);
if (shadow) {
/* Create new strings for building up a wrapper function */
setattr = NewString("");
getattr = NewString("");
csetattr = NewString("");
cgetattr = NewString("");
pyclass = NewString("");
imethod = NewString("");
construct = NewString("");
cinit = NewString("");
additional= NewString("");
base_class = 0;
have_constructor = 0;
have_destructor = 0;
have_getattr = 0;
have_setattr = 0;
have_repr = 0;
if (rname) {
class_name = Swig_copy_string(rname);
class_renamed = 1;
} else {
class_name = Swig_copy_string(classname);
class_renamed = 0;
}
}
real_classname = Swig_copy_string(classname);
class_type = Swig_copy_string(ctype);
// Build up the hash table
Setattr(hash,real_classname,class_name);
sprintf(temp,"%s %s", class_type, real_classname);
Setattr(hash,temp,class_name);
if (shadow) {
Printv(setattr,
tab4, "def __setattr__(self,name,value):\n",
tab8, "if (name == \"this\") or (name == \"thisown\"): self.__dict__[name] = value; return\n",
tab8, "method = ", class_name, ".__setmethods__.get(name,None)\n",
tab8, "if method: return method(self,value)\n",
0);
Printv(getattr, tab4, "def __getattr__(self,name):\n", 0);
Printv(csetattr, tab4, "__setmethods__ = {\n", 0);
Printv(cgetattr, tab4, "__getmethods__ = {\n", 0);
}
}
// --------------------------------------------------------------------------
// PYTHON::cpp_member_func(char *name, char *iname, DataType *t, ParmList *l)
//
// Creates a C++ member function
// --------------------------------------------------------------------------
void PYTHON::cpp_member_func(char *name, char *iname, DataType *t, ParmList *l) {
char *realname;
int oldshadow;
char cname[1024];
// Create the default member function
oldshadow = shadow; // Disable shadowing when wrapping member functions
if (shadow) shadow = shadow | PYSHADOW_MEMBER;
this->Language::cpp_member_func(name,iname,t,l);
shadow = oldshadow;
if (shadow) {
if (!iname)
realname = name;
else
realname = iname;
// Check to see if we've already seen this
sprintf(cname,"python:%s::%s",class_name,realname);
if (Getattr(symbols,cname)) {
return; // Forget it, already saw it
}
Setattr(symbols,cname,cname);
if (strcmp(realname,"__repr__") == 0)
have_repr = 1;
if (!((Getattr(hash,t->name)) && (t->is_pointer <=1)) && !noopt) {
Printv(imethod,
class_name, ".", realname, " = new.instancemethod(", module, ".", Swig_name_member(class_name,realname), ", None, ", class_name, ")\n",
0);
/* *pyclass << tab4 << realname << " = " << module << ".__shadow__." << Swig_name_member(class_name,realname) << "\n"; */
} else {
// Now add it to the class
if (use_kw)
Printv(pyclass,tab4, "def ", realname, "(*args, **kwargs):\n", 0);
else
Printv(pyclass, tab4, "def ", realname, "(*args):\n", 0);
if (use_kw)
Printv(pyclass, tab8, "val = apply(", module, ".", Swig_name_member(class_name,realname), ",args, kwargs)\n", 0);
else
Printv(pyclass, tab8, "val = apply(", module, ".", Swig_name_member(class_name,realname), ",args)\n",0);
// Check to see if the return type is an object
if ((Getattr(hash,t->name)) && (t->is_pointer <= 1)) {
if (!typemap_check((char*)"out",typemap_lang,t,Swig_name_member(class_name,realname))) {
if (!have_output) {
Printv(pyclass, tab8, "if val: val = ", GetChar(hash,t->name), "Ptr(val) ", 0);
if (((Getattr(hash,t->name)) && (t->is_pointer < 1)) ||
((Getattr(hash,t->name)) && (t->is_pointer == 1) && NewObject))
Printf(pyclass, "; val.thisown = 1\n");
else
Printf(pyclass,"\n");
} else {
// Do nothing!
}
}
}
Printv(pyclass, tab8, "return val\n", 0);
}
// emitAddPragmas(*pyclass, realname, tab8);
// *pyclass << tab8 << "return val\n";
}
}
// -----------------------------------------------------------------------------
// void PYTHON::cpp_constructor(char *name, char *iname, ParmList *l)
//
// Make a constructor for our class
// -----------------------------------------------------------------------------
void PYTHON::cpp_constructor(char *name, char *iname, ParmList *l) {
char *realname;
int oldshadow = shadow;
char cname[1024];
if (shadow) shadow = shadow | PYSHADOW_MEMBER;
this->Language::cpp_constructor(name,iname,l);
shadow = oldshadow;
if (shadow) {
if (iname)
realname = iname;
else {
if (class_renamed) realname = class_name;
else realname = class_name;
}
// Check to see if we've already seen this
sprintf(cname,":python:constructor:%s::%s",class_name,realname);
if (Getattr(symbols,cname)) {
return; // Forget it, already seen it
}
Setattr(symbols,cname,cname);
if (!have_constructor) {
// Create a new constructor
if (use_kw)
Printv(construct, tab4, "def __init__(self,*args,**kwargs):\n", 0);
else
Printv(construct, tab4, "def __init__(self,*args):\n",0);
if (use_kw)
Printv(construct, tab8, "self.this = apply(", module, ".", Swig_name_construct(realname), ",args,kwargs)\n", 0);
else
Printv(construct, tab8, "self.this = apply(", module, ".", Swig_name_construct(realname), ",args)\n", 0);
Printv(construct, tab8, "self.thisown = 1\n", 0);
emitAddPragmas(construct,(char*)"__init__",(char*)tab8);
have_constructor = 1;
} else {
// Hmmm. We seem to be creating a different constructor. We're just going to create a
// function for it.
if (use_kw)
Printv(additional, "def ", realname, "(*args,**kwargs):\n", 0);
else
Printv(additional, "def ", realname, "(*args):\n", 0);
Printv(additional, tab4, "val = ", class_name, "Ptr(apply(", 0);
if (use_kw)
Printv(additional, module, ".", Swig_name_construct(realname), ",args,kwargs))\n", 0);
else
Printv(additional, module, ".", Swig_name_construct(realname), ",args))\n", 0);
Printv(additional,tab4, "val.thisown = 1\n",
tab4, "return val\n\n", 0);
}
}
}
// ------------------------------------------------------------------------------
// void PYTHON::cpp_destructor(char *name, char *newname)
//
// Creates a destructor for this object
// ------------------------------------------------------------------------------
void PYTHON::cpp_destructor(char *name, char *newname) {
char *realname;
int oldshadow = shadow;
if (shadow) shadow = shadow | PYSHADOW_MEMBER;
this->Language::cpp_destructor(name,newname);
shadow = oldshadow;
if (shadow) {
if (newname) realname = newname;
else {
if (class_renamed) realname = class_name;
else realname = name;
}
Printv(pyclass, tab4, "def __del__(self,", module, "=", module, "):\n", 0);
emitAddPragmas(pyclass,(char*)"__del__",(char*)tab8);
Printv(pyclass, tab8, "if self.thisown == 1 :\n",
tab8, tab4, module, ".", Swig_name_destroy(realname), "(self)\n", 0);
have_destructor = 1;
}
}
// -------------------------------------------------------------------------------
// PYTHON::cpp_close_class()
//
// Closes a Python class and writes out a wrapper
// -------------------------------------------------------------------------------
void PYTHON::cpp_close_class() {
DOHString *ptrclass;
DOHString *repr;
ptrclass = NewString("");
repr = NewString("");
if (shadow) {
if (!have_constructor) {
// Build a constructor that takes a pointer to this kind of object
Printv(construct,
tab4, "def __init__(self,this):\n",
tab8, "self.this = this\n",
0);
}
// First, build the pointer base class
if (base_class) {
Printv(ptrclass, "class ", class_name, "(", base_class, "):\n", 0);
} else {
Printv(ptrclass, "class ", class_name, ":\n", 0);
}
Printv(getattr,
tab8, "method = ", class_name, ".__getmethods__.get(name,None)\n",
tab8, "if method: return method(self)\n",
tab8, "raise AttributeError,name\n",
0);
Printv(setattr, tab8, "self.__dict__[name] = value\n",0);
Printv(cgetattr, tab4, "}\n", 0);
Printv(csetattr, tab4, "}\n", 0);
Printv(ptrclass,cinit,construct,"\n",0);
Printv(classes,ptrclass,pyclass,0);
if (have_setattr) {
Printv(classes, csetattr, setattr, 0);
}
if (have_getattr) {
Printv(classes,cgetattr,getattr,0);
}
if (!have_repr) {
// Supply a repr method for this class
Printv(repr,
tab4, "def __repr__(self):\n",
tab8, "return \"<C ", class_name," instance at %s>\" % (self.this,)\n",
0);
Printv(classes,repr,0);
emitAddPragmas(classes,(char*)"__class__",(char*)tab4);
}
// Now build the real class with a normal constructor
Printv(classes,
"class ", class_name, "Ptr(", class_name, "):\n",
tab4, "def __init__(self,this):\n",
tab8, "self.this = this\n",
tab8, "self.thisown = 0\n",
tab8, "self.__class__ = ", class_name, "\n",
"\n", additional, "\n",
0);
Printv(classes,imethod,"\n",0);
Delete(pyclass);
Delete(imethod);
Delete(setattr);
Delete(getattr);
Delete(additional);
}
Delete(ptrclass);
Delete(repr);
}
void PYTHON::cpp_cleanup() { };
void PYTHON::cpp_inherit(char **baseclass,int) {
char *bc;
int i = 0, first_base = 0;
if (!shadow) {
this->Language::cpp_inherit(baseclass);
return;
}
// We'll inherit variables and constants, but not methods
this->Language::cpp_inherit(baseclass, INHERIT_VAR);
if (!baseclass) return;
base_class = NewString("");
// Now tell the Python module that we're inheriting from a base class
while (baseclass[i]) {
bc = GetChar(hash,baseclass[i]);
if (bc) {
if (first_base) Putc(',',base_class);
Printv(base_class,bc,0);
first_base = 1;
}
i++;
}
if (!first_base) {
Delete(base_class);
base_class = 0;
}
}
// --------------------------------------------------------------------------------
// PYTHON::cpp_variable(char *name, char *iname, DataType *t)
//
// Adds an instance member.
// --------------------------------------------------------------------------------
void PYTHON::cpp_variable(char *name, char *iname, DataType *t) {
char *realname;
int inhash = 0;
int oldshadow = shadow;
char cname[512];
if (shadow) shadow = shadow | PYSHADOW_MEMBER;
this->Language::cpp_variable(name,iname,t);
shadow = oldshadow;
if (shadow) {
have_getattr = 1;
have_setattr = 1;
if (!iname)
realname = name;
else
realname = iname;
// Check to see if we've already seen this
sprintf(cname,"python:%s::%s:",class_name,realname);
if (Getattr(symbols,cname)) {
return; // Forget it, already seen it
}
Setattr(symbols,cname,cname);
// Figure out if we've seen this datatype before
if ((Getattr(hash,t->name)) && (t->is_pointer <= 1)) inhash = 1;
// Now write some code to set the variable
if (Status & STAT_READONLY) {
// *setattr << tab8 << tab4 << "raise RuntimeError, \'Member is read-only\'\n";
} else {
Printv(csetattr, tab8, "\"", realname, "\" : ", module, ".", Swig_name_set(Swig_name_member(class_name,realname)), ",\n", 0);
}
// Write some code to get the variable
if (inhash) {
Printv(cgetattr, tab8, "\"", realname, "\" : lambda x : ", GetChar(hash,t->name), "Ptr(", module, ".", Swig_name_get(Swig_name_member(class_name,realname)), "(x)),\n", 0);
} else {
Printv(cgetattr, tab8, "\"", realname, "\" : ", module, ".", Swig_name_get(Swig_name_member(class_name,realname)),",\n", 0);
}
}
}
// --------------------------------------------------------------------------------
// PYTHON::cpp_declare_const(char *name, char *iname, DataType *type, char *value)
//
// Add access to a C++ constant
// --------------------------------------------------------------------------------
void PYTHON::cpp_declare_const(char *name, char *iname, DataType *type, char *value) {
char *realname;
int oldshadow = shadow;
char cname[512];
if (shadow) shadow = shadow | PYSHADOW_MEMBER;
this->Language::cpp_declare_const(name,iname,type,value);
shadow = oldshadow;
if (shadow) {
if (!iname)
realname = name;
else
realname = iname;
// Check to see if we've already seen this
sprintf(cname,"python:%s::%s", class_name, realname);
if (Getattr(symbols,cname)) {
return; // Forget it, already seen it
}
Setattr(symbols,cname,cname);
Printv(cinit, tab4, realname, " = ", module, ".", Swig_name_member(class_name,realname), "\n", 0);
}
}
// --------------------------------------------------------------------------------
// PYTHON::add_typedef(DataType *t, char *name)
//
// This is called whenever a typedef is encountered. When shadow classes are
// used, this function lets us discovered hidden uses of a class. For example :
//
// struct FooBar {
// ...
// }
//
// typedef FooBar *FooBarPtr;
//
// --------------------------------------------------------------------------------
void PYTHON::add_typedef(DataType *t, char *name) {
if (!shadow) return;
// First check to see if there aren't too many pointers
if (t->is_pointer > 1) return;
if (Getattr(hash,name)) return; // Already added
// Now look up the datatype in our shadow class hash table
if (Getattr(hash,t->name)) {
// Yep. This datatype is in the hash
// Put this types 'new' name into the hash
Setattr(hash,name, GetChar(hash,t->name));
}
}