diff options
author | Stefan Zager <szager@gmail.com> | 2011-04-01 19:35:30 +0000 |
---|---|---|
committer | Stefan Zager <szager@gmail.com> | 2011-04-01 19:35:30 +0000 |
commit | cd7fc2047b88d87a7d394c03da2a01a101510093 (patch) | |
tree | f7dbddbcc4a3441faf9ce2be1a108de6ad932271 | |
parent | 960b503a7268f65b5bb23884bf952bce98515db3 (diff) | |
download | swig-cd7fc2047b88d87a7d394c03da2a01a101510093.tar.gz |
Factored some #ifdef noise out of the initialization function by adding
SwigPyBuiltin_SetMetaType.
For %import statements, move the runtime import out of SWIG_init and into the
.py file. The reason for this is that the import must be executed within the
python execution frame of the module, which is true in the .py file, but *not*
true in the initialization function. Had to re-order the .py file slightly
to put the 'import' statements at the top; that's necessary to make sure base
types from an imported module are initialized first. If -builtin isn't used,
then the .py code is not re-ordered.
Added an explanation and workaround for the limitation that wrapped types are
not raise-able.
git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/branches/szager-python-builtin@12585 626c5289-ae23-0410-ae9c-e8d60b6d4f22
-rw-r--r-- | Doc/Manual/Python.html | 63 | ||||
-rw-r--r-- | Lib/python/builtin.swg | 10 | ||||
-rw-r--r-- | Lib/python/pyinit.swg | 3 | ||||
-rw-r--r-- | Source/Modules/python.cxx | 56 |
4 files changed, 83 insertions, 49 deletions
diff --git a/Doc/Manual/Python.html b/Doc/Manual/Python.html index e766baaf0..0c88185cb 100644 --- a/Doc/Manual/Python.html +++ b/Doc/Manual/Python.html @@ -2350,14 +2350,71 @@ please refer to the python documentation:</p> <p>Use of the <tt>-builtin</tt> option implies a couple of limitations: <ul> -<li>Some legacy syntax is no longer supported; in particular:</li> +<li><p>Some legacy syntax is no longer supported; in particular:</p></li> <ul> <li>The functional interface is no longer exposed. For example, you may no longer call <tt>Whizzo.new_CrunchyFrog()</tt>. Instead, you must use <tt>Whizzo.CrunchyFrog()</tt>.</li> <li>Static member variables are no longer accessed through the 'cvar' field (e.g., <tt>Dances.cvar.FishSlap</tt>). They are instead accessed in the idiomatic way (<tt>Dances.FishSlap</tt>).</li> </ul> -<li>Wrapped types may not be thrown as python exceptions</li> -<li>Reverse operators are not supported.</li> +<li><p>Wrapped types may not be thrown as python exceptions. Here's why: the python internals expect that all sub-classes of Exception will have this struct layout:</p> + +<div class="code"> +<pre> +typedef struct { + PyObject_HEAD + PyObject *dict; + PyObject *args; + PyObject *message; +} PyBaseExceptionObject; +</pre> +</div> + +<p>But swig-generated wrappers expect that all swig-wrapped classes will have this struct layout:</p> + +<div class="code"> +<pre> +typedef struct { + PyObject_HEAD + void *ptr; + swig_type_info *ty; + int own; + PyObject *next; + PyObject *dict; +} SwigPyObject; +</pre> +</div> + +<p>There are workarounds for this. For example, if you wrap this class: + +<div class="code"> +<pre> +class MyException { +public: + MyException (const char *msg_); + ~MyException (); + + const char *what () const; + +private: + char *msg; +}; +</pre> +</div> + +<p>... you can define this python class, which may be raised as an exception:</p> + +<div class="targetlang"> +<pre> +class MyPyException (Exception, MyException) : + def __init__(self, msg, *args) : + Exception.__init__(self, *args) + self.myexc = MyException(msg) + def what (self) : + return self.myexc.what() +</pre> +</div> +</li> +<li><p>Reverse binary operators (e.g., <tt>__radd__</tt>) are not supported.</p></li> </ul> </p> diff --git a/Lib/python/builtin.swg b/Lib/python/builtin.swg index ffd3fbd1c..876bcd1cc 100644 --- a/Lib/python/builtin.swg +++ b/Lib/python/builtin.swg @@ -409,3 +409,13 @@ SwigPyBuiltin_ThisClosure (PyObject *self, void *closure) { Py_XINCREF(result); return result; } + +SWIGINTERN void +SwigPyBuiltin_SetMetaType (PyTypeObject *type, PyTypeObject *metatype) +{ +#if PY_VERSION_HEX >= 0x03000000 + type->ob_base.ob_base.ob_type = metatype; +#else + type->ob_type = metatype; +#endif +} diff --git a/Lib/python/pyinit.swg b/Lib/python/pyinit.swg index 88d2d3f16..088eb0ab0 100644 --- a/Lib/python/pyinit.swg +++ b/Lib/python/pyinit.swg @@ -355,9 +355,6 @@ SWIG_init(void) { Py_DECREF(metatype_args); metatype->tp_setattro = (setattrofunc) &SwigPyObjectType_setattro; assert(PyType_Ready(metatype) >= 0); - - SWIG_Python_builtin_imports(); - #endif /* Fix SwigMethods to carry the callback ptrs when needed */ diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx index 0b6f968e1..fe63a3dbc 100644 --- a/Source/Modules/python.cxx +++ b/Source/Modules/python.cxx @@ -44,8 +44,8 @@ static File *f_directors_h = 0; static File *f_init = 0; static File *f_shadow_py = 0; static String *f_shadow = 0; -static String *f_shadow_imports = 0; -static String *f_shadow_import_stmts = 0; +static Hash *f_shadow_imports = 0; +static String *f_shadow_builtin_imports = 0; static String *f_shadow_stubs = 0; static Hash *builtin_getset = 0; static Hash *class_members = 0; @@ -782,24 +782,13 @@ public: filen = NULL; f_shadow = NewString(""); - f_shadow_imports = NewString(""); - f_shadow_import_stmts = NewString(""); + f_shadow_imports = NewHash(); + f_shadow_builtin_imports = NewString(""); f_shadow_stubs = NewString(""); - Printv(f_shadow_import_stmts, "SWIGINTERN void\n", NIL); - Printv(f_shadow_import_stmts, "SWIG_Python_builtin_imports()\n", NIL); - Printv(f_shadow_import_stmts, "{\n", NIL); - Printv(f_shadow_import_stmts, tab4 "PyObject *import_str = NULL;\n", NIL); - Swig_register_filebyname("shadow", f_shadow); Swig_register_filebyname("python", f_shadow); - Swig_banner_target_lang(f_shadow, "#"); - - if (!modern) { - Printv(f_shadow, "# This file is compatible with both classic and new-style classes.\n", NIL); - } - if (mod_docstring && Len(mod_docstring)) { Printv(f_shadow, "\"\"\"\n", mod_docstring, "\n\"\"\"\n\n", NIL); Delete(mod_docstring); @@ -982,13 +971,13 @@ public: Printf(f_init, "}\n"); if (shadow) { - if (builtin) { - Printv(f_shadow_import_stmts, "}\n", NIL); - Printv(f_header, f_shadow_import_stmts, NIL); + Swig_banner_target_lang(f_shadow_py, "#"); + if (!modern) { + Printv(f_shadow, "# This file is compatible with both classic and new-style classes.\n", NIL); } + Printv(f_shadow_py, "\n", f_shadow_builtin_imports, "\n", NIL); Printv(f_shadow_py, f_shadow, "\n", NIL); Printv(f_shadow_py, f_shadow_stubs, "\n", NIL); - Close(f_shadow_py); Delete(f_shadow_py); } @@ -1066,25 +1055,13 @@ public: if (shadowimport) { if (!options || (!Getattr(options, "noshadow") && !Getattr(options, "noproxy"))) { Printf(import, "_%s\n", modname); - if (!Strstr(f_shadow_imports, import)) { + if (!GetFlagAttr(f_shadow_imports, import)) { if (pkg && (!package || Strcmp(pkg, package) != 0)) { - if (builtin) { - Printf(f_shadow_import_stmts, tab4 "import_str = PyString_FromString(\"%s.%s\");\n", pkg, modname); - Printf(f_shadow_import_stmts, tab4 "PyImport_Import(import_str);\n"); - Printf(f_shadow_import_stmts, tab4 "Py_XDECREF(import_str);\n"); - } else { - Printf(f_shadow, "import %s.%s\n", pkg, modname); - } + Printf(builtin ? f_shadow_builtin_imports : f_shadow, "import %s.%s\n", pkg, modname); } else { - if (builtin) { - Printf(f_shadow_import_stmts, tab4 "import_str = PyString_FromString(\"%s\");\n", modname); - Printf(f_shadow_import_stmts, tab4 "PyImport_Import(import_str);\n"); - Printf(f_shadow_import_stmts, tab4 "Py_XDECREF(import_str);\n"); - } else { - Printf(f_shadow, "import %s\n", modname); - } + Printf(builtin ? f_shadow_builtin_imports : f_shadow, "import %s\n", modname); } - Printv(f_shadow_imports, import, NULL); + SetFlag(f_shadow_imports, import); } } } @@ -3227,11 +3204,7 @@ public: String *templ = NewStringf("SwigPyBuiltin_%s", mname); int funpack = modernargs && fastunpack; - Printv(f_init, "#if PY_VERSION_HEX >= 0x03000000\n", NIL); - Printf(f_init, " builtin_pytype->ob_base.ob_base.ob_type = metatype;\n"); - Printv(f_init, "#else\n", NIL); - Printf(f_init, " builtin_pytype->ob_type = metatype;\n"); - Printv(f_init, "#endif\n", NIL); + Printv(f_init, " SwigPyBuiltin_SetMetaType(builtin_pytype, metatype);\n", NIL); Printf(f_init, " builtin_pytype->tp_new = PyType_GenericNew;\n"); Printv(f_init, " builtin_base_count = 0;\n", NIL); List *baselist = Getattr(n, "bases"); @@ -3848,9 +3821,6 @@ public: } if (builtin) { - //Dump(f_shadow, f_builtins); - //Printf(f_builtins, " {NULL} // Sentinel\n};\n\n"); - //Dump(builtin_methods, f_builtins); Clear(class_members); Clear(builtin_getset); Clear(builtin_methods); |