summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Zager <szager@gmail.com>2011-04-01 19:35:30 +0000
committerStefan Zager <szager@gmail.com>2011-04-01 19:35:30 +0000
commitcd7fc2047b88d87a7d394c03da2a01a101510093 (patch)
treef7dbddbcc4a3441faf9ce2be1a108de6ad932271
parent960b503a7268f65b5bb23884bf952bce98515db3 (diff)
downloadswig-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.html63
-rw-r--r--Lib/python/builtin.swg10
-rw-r--r--Lib/python/pyinit.swg3
-rw-r--r--Source/Modules/python.cxx56
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);