diff --git a/Doc/Manual/Contents.html b/Doc/Manual/Contents.html index 0b456fca7..3f283ecb9 100644 --- a/Doc/Manual/Contents.html +++ b/Doc/Manual/Contents.html @@ -310,7 +310,7 @@
  • General-purpose smart pointers
  • Extensible random number facility
  • Wrapper reference -
  • Polymorphous wrappers for function objects +
  • Polymorphic wrappers for function objects
  • Type traits for metaprogramming
  • Uniform method for computing return type of function objects @@ -1529,7 +1529,7 @@
  • Built-in Types
  • Memory management
  • Python 2.2 and classic classes diff --git a/Doc/Manual/Python.html b/Doc/Manual/Python.html index ce7f9fe5a..cf0f86024 100644 --- a/Doc/Manual/Python.html +++ b/Doc/Manual/Python.html @@ -51,7 +51,7 @@
  • Built-in Types
  • Memory management
  • Python 2.2 and classic classes @@ -2442,7 +2442,7 @@ assert(issubclass(B.Derived, A.Base))
  • -

    36.4.2.2 Operator overloads -- use them!

    +

    36.4.2.2 Operator overloads and slots -- use them!

    The entire justification for the -builtin option is improved @@ -2494,52 +2494,110 @@ automatically converted to python slot operators, refer to the file python/pyopers.swig in the SWIG library.

    -

    There are other very useful python slots that you -may explicitly define using %feature directives. For example, -suppose you want to use instances of a wrapped class as keys in a native python -dict. That will work as long as you define a hash function for -instances of your class, and use it to define the python tp_hash -slot: + +

    +Read about all of the available python slots here: +http://docs.python.org/c-api/typeobj.html

    + +

    +There are two ways to define a python slot function: dispatch to a +statically defined function; or dispatch to a method defined on the +operand. +

    + +

    +To dispatch to a statically defined function, use %feature("python:<slot>"), +where <slot> is the name of a field in a PyTypeObject, PyNumberMethods, +PyMappingMethods, PySequenceMethods or PyBufferProcs. +You may override (almost) all of these slots. +

    + + +

    +Let's consider an example setting the tp_hash slot for the MyClass type. +This is akin to providing a __hash__ method (for non-builtin types) to make a type hashable. +The hashable type can then for example be added to a Python dict.

    -%feature("python:slot", "tp_hash", functype="hashfunc") Cheese::cheeseHashFunc;
    +%feature("python:tp_hash") MyClass "myHashFunc";
     
    -class Cheese {
    +class MyClass {
     public:
    -    Cheese (const char *name);
    -    long cheeseHashFunc () const;
    +  long field1;
    +  long field2;
    +  ...
    +};
    +
    +%{
    +#if PY_VERSION_HEX >= 0x03020000
    +  static Py_hash_t myHashFunc(PyObject *pyobj)
    +#else
    +  static long myHashFunc(PyObject *pyobj)
    +#endif
    +  {
    +    MyClass *cobj;
    +    // Convert pyobj to cobj
    +    return (cobj->field1 * (cobj->field2 << 7));
    +  }
    +%}
    +
    +
    + +

    +If you examine the generated code, the supplied hash function will now be +the function callback in the tp_hash slot for the builtin type for MyClass: +

    + +
    +
    +static PyHeapTypeObject SwigPyBuiltin__MyClass_type = {
    +    ...
    +    (hashfunc) myHashFunc,       /* tp_hash */
    +    ...
    +
    +
    + +

    +NOTE: It is the responsibility of the programmer (that's you!) to ensure +that a statically defined slot function has the correct signature, the hashfunc +typedef in this case. +

    + +

    +If, instead, you want to dispatch to an instance method, you can +use %feature("python:slot"). For example: +

    + +
    +
    +%feature("python:slot", "tp_hash", functype="hashfunc") MyClass::myHashFunc;
    +
    +#if PY_VERSION_HEX < 0x03020000
    +  #define Py_hash_t long
    +#endif
    +
    +class MyClass {
    +  public:
    +    Py_hash_t myHashFunc() const;
    +    ...
     };
     
    -

    This will allow you to write python code like this:

    +

    +NOTE: Some python slots use a method signature which does not +match the signature of SWIG-wrapped methods. For those slots, +SWIG will automatically generate a "closure" function to re-marshal +the arguments before dispatching to the wrapped method. Setting +the "functype" attribute of the feature enables SWIG to generate +the chosen closure function. +

    -
    -
    -from my MyPackage import Cheese
    -
    -inventory = {
    -    Cheese("cheddar") : 0,
    -    Cheese("gouda") : 0,
    -    Cheese("camembert") : 0
    -}
    -
    -
    - -

    Because you defined the tp_hash slot, Cheese objects may -be used as hash keys; and when the cheeseHashFunc method is invoked -by a python dict, it will not go through named method dispatch. -A more detailed discussion about %feature("python:slot") can be found +

    +There is further information on %feature("python:slot") in the file python/pyopers.swig in the SWIG library. -You can read about all of the available python slots here:

    - -

    http://docs.python.org/c-api/typeobj.html

    - -

    You may override (almost) all of the slots defined in the PyTypeObject, -PyNumberMethods, PyMappingMethods, PySequenceMethods, and PyBufferProcs -structs.

    diff --git a/Examples/test-suite/python/Makefile.in b/Examples/test-suite/python/Makefile.in index a7993b0b8..bfc5450b0 100644 --- a/Examples/test-suite/python/Makefile.in +++ b/Examples/test-suite/python/Makefile.in @@ -58,6 +58,7 @@ CPP_TEST_CASES += \ primitive_types \ python_abstractbase \ python_append \ + python_builtin \ python_destructor_exception \ python_director \ python_docstring \ diff --git a/Examples/test-suite/python/python_builtin_runme.py b/Examples/test-suite/python/python_builtin_runme.py new file mode 100644 index 000000000..c41dfc0b1 --- /dev/null +++ b/Examples/test-suite/python/python_builtin_runme.py @@ -0,0 +1,70 @@ +from python_builtin import * + +if is_python_builtin(): + # Test 1 for tp_hash + if hash(SimpleValue(222)) != 222: + raise RuntimeError("tp_hash not working") + + # Test 2 for tp_hash + try: + # Was incorrectly raising: SystemError: error return without exception set + h = hash(BadHashFunctionReturnType()) + raise RuntimeError("Missing TypeError") + except TypeError: + pass + + # Test 3 for tp_hash + passed = False + try: + h = hash(ExceptionHashFunction()) + except RuntimeError, e: + passed = str(e).find("oops") != -1 + pass + + if not passed: + raise RuntimeError("did not catch exception in hash()") + + # Test 4 for tp_dealloc (which is handled differently to other slots in the SWIG source) + d = Dealloc1() + if cvar.Dealloc1CalledCount != 0: + raise RuntimeError("count should be 0") + del d + if cvar.Dealloc1CalledCount != 1: + raise RuntimeError("count should be 1") + + d = Dealloc2() + if cvar.Dealloc2CalledCount != 0: + raise RuntimeError("count should be 0") + del d + if cvar.Dealloc2CalledCount != 1: + raise RuntimeError("count should be 1") + + d = Dealloc3() + if cvar.Dealloc3CalledCount != 0: + raise RuntimeError("count should be 0") + del d + if cvar.Dealloc3CalledCount != 1: + raise RuntimeError("count should be 1") + + # Test 5 for python:compare feature + m10 = MyClass(10) + m20 = MyClass(20) + m15 = MyClass(15) + + if not m10 < m15: + raise RuntimeError("m10 < m15") + if not m10 < m20: + raise RuntimeError("m10 < m20") + if not m15 < m20: + raise RuntimeError("m15 < m20") + + if m10 > m15: + raise RuntimeError("m10 > m15") + if m10 > m20: + raise RuntimeError("m10 > m20") + if m15 > m20: + raise RuntimeError("m15 > m20") + + if MyClass.less_than_counts != 6: + raise RuntimeError("python:compare feature not working") + diff --git a/Examples/test-suite/python_builtin.i b/Examples/test-suite/python_builtin.i new file mode 100644 index 000000000..ac1ad9c2d --- /dev/null +++ b/Examples/test-suite/python_builtin.i @@ -0,0 +1,130 @@ +// Test customizing slots when using the -builtin option + +%module python_builtin + +%inline %{ +#ifdef SWIGPYTHON_BUILTIN +bool is_python_builtin() { return true; } +#else +bool is_python_builtin() { return false; } +#endif +%} + +// Test 1 for tp_hash +#if defined(SWIGPYTHON_BUILTIN) +%feature("python:tp_hash") SimpleValue "SimpleValueHashFunction" +#endif + +%inline %{ +struct SimpleValue { + int value; + SimpleValue(int value) : value(value) {} + static SimpleValue *inout(SimpleValue *sv) { + return sv; + } +}; +%} + +%{ +#if PY_VERSION_HEX >= 0x03020000 +Py_hash_t SimpleValueHashFunction(PyObject *v) +#else +long SimpleValueHashFunction(PyObject *v) +#endif +{ + SwigPyObject *sobj = (SwigPyObject *) v; + SimpleValue *p = (SimpleValue *)sobj->ptr; + return p->value; +} +hashfunc test_hashfunc_cast() { + return SimpleValueHashFunction; +} +%} + +// Test 2 for tp_hash +#if defined(SWIGPYTHON_BUILTIN) +%feature("python:slot", "tp_hash", functype="hashfunc") BadHashFunctionReturnType::bad_hash_function; +#endif + +%inline %{ +struct BadHashFunctionReturnType { + static const char * bad_hash_function() { + return "bad hash function"; + } +}; +%} + +// Test 3 for tp_hash +#if defined(SWIGPYTHON_BUILTIN) +%feature("python:slot", "tp_hash", functype="hashfunc") ExceptionHashFunction::exception_hash_function; +#endif + +%catches(const char *) exception_hash_function; + +%inline %{ +#if PY_VERSION_HEX < 0x03020000 + #define Py_hash_t long +#endif +struct ExceptionHashFunction { + static Py_hash_t exception_hash_function() { + throw "oops"; + } +}; +%} + +// Test 4 for tp_dealloc (which is handled differently to other slots in the SWIG source) +#if defined(SWIGPYTHON_BUILTIN) +%feature("python:tp_dealloc") Dealloc1 "Dealloc1Destroyer" +%feature("python:tp_dealloc") Dealloc2 "Dealloc2Destroyer" +%feature("python:slot", "tp_dealloc", functype="destructor") Dealloc3::Destroyer; +#endif + +%inline %{ +static int Dealloc1CalledCount = 0; +static int Dealloc2CalledCount = 0; +static int Dealloc3CalledCount = 0; + +struct Dealloc1 { +}; +struct Dealloc2 { + ~Dealloc2() {} +}; +struct Dealloc3 { + void Destroyer() { + Dealloc3CalledCount++; + delete this; + } +}; +%} + +%{ +void Dealloc1Destroyer(PyObject *v) { + SwigPyObject *sobj = (SwigPyObject *) v; + Dealloc1 *p = (Dealloc1 *)sobj->ptr; + delete p; + Dealloc1CalledCount++; +} +void Dealloc2Destroyer(PyObject *v) { + SwigPyObject *sobj = (SwigPyObject *) v; + Dealloc2 *p = (Dealloc2 *)sobj->ptr; + delete p; + Dealloc2CalledCount++; +} +%} + +// Test 5 for python:compare feature +%feature("python:compare", "Py_LT") MyClass::lessThan; + +%inline %{ + class MyClass { + public: + MyClass(int val = 0) : val(val) {} + bool lessThan(const MyClass& other) const { + less_than_counts++; + return val < other.val; + } + int val; + static int less_than_counts; + }; + int MyClass::less_than_counts = 0; +%} diff --git a/Lib/python/builtin.swg b/Lib/python/builtin.swg index 5767a1422..6085980d4 100644 --- a/Lib/python/builtin.swg +++ b/Lib/python/builtin.swg @@ -192,9 +192,11 @@ wrapper##_closure(PyObject *a) { \ PyObject *pyresult; \ long result; \ pyresult = wrapper(a, NULL); \ - if (!pyresult || !PyLong_Check(pyresult)) \ - return -1; \ + if (!pyresult) \ + return -1; \ result = PyLong_AsLong(pyresult); \ + if (PyErr_Occurred()) \ + result = -1; \ Py_DECREF(pyresult); \ return result; \ } @@ -387,16 +389,15 @@ SwigPyStaticVar_Type(void) { static int type_init = 0; if (!type_init) { const PyTypeObject tmp = { - /* PyObject header changed in Python 3 */ #if PY_VERSION_HEX >= 0x03000000 PyVarObject_HEAD_INIT(&PyType_Type, 0) #else PyObject_HEAD_INIT(&PyType_Type) - 0, + 0, /* ob_size */ #endif - "swig_static_var_getset_descriptor", - sizeof(PyGetSetDescrObject), - 0, + "swig_static_var_getset_descriptor", /* tp_name */ + sizeof(PyGetSetDescrObject), /* tp_basicsize */ + 0, /* tp_itemsize */ (destructor)SwigPyStaticVar_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ diff --git a/Lib/python/pyinit.swg b/Lib/python/pyinit.swg index 2e21b8265..e671731ac 100644 --- a/Lib/python/pyinit.swg +++ b/Lib/python/pyinit.swg @@ -145,7 +145,6 @@ swig_varlink_type(void) { static int type_init = 0; if (!type_init) { const PyTypeObject tmp = { - /* PyObject header changed in Python 3 */ #if PY_VERSION_HEX >= 0x03000000 PyVarObject_HEAD_INIT(NULL, 0) #else diff --git a/Lib/python/pyopers.swg b/Lib/python/pyopers.swg index 292c593a8..5fb22354b 100644 --- a/Lib/python/pyopers.swg +++ b/Lib/python/pyopers.swg @@ -18,31 +18,35 @@ where is the name of a field in a PyTypeObject, PyNumberMethods, PyMappingMethods, PySequenceMethods, or PyBufferProcs. For example: - %{ - - static long myHashFunc (PyObject *pyobj) { - MyClass *cobj; - // Convert pyobj to cobj - return (cobj->field1 * (cobj->field2 << 7)); - } - - %} - %feature("python:tp_hash") MyClass "myHashFunc"; + class MyClass { + public: + ... + }; + + %{ + // Note: Py_hash_t was introduced in Python 3.2 + static Py_hash_t myHashFunc(PyObject *pyobj) { + MyClass *cobj; + // Convert pyobj to cobj + return (cobj->field1 * (cobj->field2 << 7)); + } + %} + NOTE: It is the responsibility of the programmer (that's you) to ensure that a statically defined slot function has the correct signature. If, instead, you want to dispatch to an instance method, you can use %feature("python:slot"). For example: + %feature("python:slot", "tp_hash", functype="hashfunc") MyClass::myHashFunc; + class MyClass { public: - long myHashFunc () const; + Py_hash_t myHashFunc () const; ... }; - - %feature("python:slot", "tp_hash", functype="hashfunc") MyClass::myHashFunc; NOTE: Some python slots use a method signature which does not match the signature of SWIG-wrapped methods. For those slots, @@ -58,20 +62,21 @@ operator overloads for comparison (operator==, operator<, etc.), they will be called from the generated rich compare function. If you want to explicitly choose a method to handle a certain comparison - operation, you may use %feature("python:slot") like this: + operation, you may use a different feature, %feature("python:compare") + like this: + + %feature("python:compare", "Py_LT") MyClass::lessThan; class MyClass { public: - bool lessThan (const MyClass& x) const; + bool lessThan(const MyClass& other) const; ... }; - %feature("python:slot", "Py_LT") MyClass::lessThan; - ... where "Py_LT" is one of the rich comparison opcodes defined in the python header file object.h. - If there's no method defined to handle a particular comparsion operation, + If there's no method defined to handle a particular comparison operation, the default behavior is to compare pointer values of the wrapped C++ objects. diff --git a/Lib/python/pyrun.swg b/Lib/python/pyrun.swg index 08f0848d4..ab1237f62 100644 --- a/Lib/python/pyrun.swg +++ b/Lib/python/pyrun.swg @@ -758,7 +758,6 @@ SwigPyObject_TypeOnce(void) { static int type_init = 0; if (!type_init) { const PyTypeObject tmp = { - /* PyObject header changed in Python 3 */ #if PY_VERSION_HEX >= 0x03000000 PyVarObject_HEAD_INIT(NULL, 0) #else @@ -769,7 +768,7 @@ SwigPyObject_TypeOnce(void) { sizeof(SwigPyObject), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)SwigPyObject_dealloc, /* tp_dealloc */ - 0, /* tp_print */ + 0, /* tp_print */ #if PY_VERSION_HEX < 0x02020000 (getattrfunc)SwigPyObject_getattr, /* tp_getattr */ #else @@ -777,7 +776,7 @@ SwigPyObject_TypeOnce(void) { #endif (setattrfunc)0, /* tp_setattr */ #if PY_VERSION_HEX >= 0x03000000 - 0, /* tp_reserved in 3.0.1, tp_compare in 3.0.0 but not used */ + 0, /* tp_reserved in 3.0.1, tp_compare in 3.0.0 but not used */ #else (cmpfunc)SwigPyObject_compare, /* tp_compare */ #endif @@ -787,7 +786,7 @@ SwigPyObject_TypeOnce(void) { 0, /* tp_as_mapping */ (hashfunc)0, /* tp_hash */ (ternaryfunc)0, /* tp_call */ - 0, /* tp_str */ + 0, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ @@ -950,7 +949,6 @@ SwigPyPacked_TypeOnce(void) { static int type_init = 0; if (!type_init) { const PyTypeObject tmp = { - /* PyObject header changed in Python 3 */ #if PY_VERSION_HEX>=0x03000000 PyVarObject_HEAD_INIT(NULL, 0) #else diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx index b42cf022f..d31554071 100644 --- a/Source/Modules/python.cxx +++ b/Source/Modules/python.cxx @@ -167,19 +167,19 @@ static const char *usage3 = "\ Function annotation \n\ \n"; -static String *getSlot(Node *n = NULL, const char *key = NULL) { - static String *slot_default = NewString("0"); - String *val = key && *key ? Getattr(n, key) : NULL; - return val ? val : slot_default; +static String *getSlot(Node *n = NULL, const char *key = NULL, String *default_slot = NULL) { + static String *zero = NewString("0"); + String *val = n && key && *key ? Getattr(n, key) : NULL; + return val ? val : default_slot ? default_slot : zero; } -static void printSlot(File *f, const String *slotval, const char *slotname, const char *functype = NULL) { - String *slotval_override = functype ? NewStringf("(%s) %s", functype, slotval) : 0; - if (slotval_override) - slotval = slotval_override; +static void printSlot(File *f, String *slotval, const char *slotname, const char *functype = NULL) { + String *slotval_override = 0; + if (functype) + slotval = slotval_override = NewStringf("(%s) %s", functype, slotval); int len = Len(slotval); - int fieldwidth = len > 40 ? 0 : 40 - len; - Printf(f, " %s, %*s/* %s */\n", slotval, fieldwidth, "", slotname); + int fieldwidth = len > 41 ? (len > 61 ? 0 : 61 - len) : 41 - len; + Printf(f, " %s,%*s/* %s */\n", slotval, fieldwidth, "", slotname); Delete(slotval_override); } @@ -2037,7 +2037,7 @@ public: // Disregard optional "f" suffix, it can be just dropped in Python as it // uses doubles for everything anyhow. - for (char* p = end; *p != '\0'; ++p) { + for (char * p = end; *p != '\0'; ++p) { switch (*p) { case 'f': case 'F': @@ -2083,7 +2083,7 @@ public: // combination of "l" and "u", but not anything else (again, stuff like // "LL" could be handled, but we don't bother to do it currently). bool seen_long = false; - for (char* p = end; *p != '\0'; ++p) { + for (char * p = end; *p != '\0'; ++p) { switch (*p) { case 'l': case 'L': @@ -3321,7 +3321,7 @@ public: } if (in_class && builtin) { - /* Handle operator overloads overloads for builtin types */ + /* Handle operator overloads for builtin types */ String *slot = Getattr(n, "feature:python:slot"); if (slot) { String *func_type = Getattr(n, "feature:python:slot:functype"); @@ -3329,9 +3329,9 @@ public: String *feature_name = NewStringf("feature:python:%s", slot); String *closure_name = Copy(wrapper_name); if (closure_decl) { - if (!Getattr(n, "sym:overloaded") || !Getattr(n, "sym:nextSibling")) - Printv(f_wrappers, closure_decl, "\n\n", NIL); Append(closure_name, "_closure"); + if (!Getattr(n, "sym:overloaded") || !Getattr(n, "sym:nextSibling")) + Printf(f_wrappers, "%s /* defines %s */\n\n", closure_decl, closure_name); Delete(closure_decl); } if (func_type) { @@ -3392,7 +3392,7 @@ public: Python dictionary. */ if (!have_globals) { - Printf(f_init, "\t PyDict_SetItemString(md,(char*)\"%s\", SWIG_globals());\n", global_name); + Printf(f_init, "\t PyDict_SetItemString(md,(char *)\"%s\", SWIG_globals());\n", global_name); if (builtin) Printf(f_init, "\t SwigPyBuiltin_AddPublicSymbol(public_interface, \"%s\");\n", global_name); have_globals = 1; @@ -3480,9 +3480,9 @@ public: Wrapper_print(getf, f_wrappers); /* Now add this to the variable linking mechanism */ - Printf(f_init, "\t SWIG_addvarlink(SWIG_globals(),(char*)\"%s\",%s, %s);\n", iname, vargetname, varsetname); + Printf(f_init, "\t SWIG_addvarlink(SWIG_globals(),(char *)\"%s\",%s, %s);\n", iname, vargetname, varsetname); if (builtin && shadow && !assignable && !in_class) { - Printf(f_init, "\t PyDict_SetItemString(md, (char*)\"%s\", PyObject_GetAttrString(SWIG_globals(), \"%s\"));\n", iname, iname); + Printf(f_init, "\t PyDict_SetItemString(md, (char *)\"%s\", PyObject_GetAttrString(SWIG_globals(), \"%s\"));\n", iname, iname); Printf(f_init, "\t SwigPyBuiltin_AddPublicSymbol(public_interface, \"%s\");\n", iname); } Delete(vargetname); @@ -3499,7 +3499,7 @@ public: * ------------------------------------------------------------ */ /* Determine if the node requires the _swigconstant code to be generated */ - bool needs_swigconstant(Node* n) { + bool needs_swigconstant(Node *n) { SwigType *type = Getattr(n, "type"); SwigType *qtype = SwigType_typedef_resolve_all(type); SwigType *uqtype = SwigType_strip_qualifiers(qtype); @@ -3576,12 +3576,12 @@ public: Printf(f_wrappers, tab2 "PyObject *d;\n"); if (modernargs) { if (fastunpack) { - Printf(f_wrappers, tab2 "if (!SWIG_Python_UnpackTuple(args,(char*)\"swigconstant\", 1, 1,&module)) return NULL;\n"); + Printf(f_wrappers, tab2 "if (!SWIG_Python_UnpackTuple(args,(char *)\"swigconstant\", 1, 1,&module)) return NULL;\n"); } else { - Printf(f_wrappers, tab2 "if (!PyArg_UnpackTuple(args,(char*)\"swigconstant\", 1, 1,&module)) return NULL;\n"); + Printf(f_wrappers, tab2 "if (!PyArg_UnpackTuple(args,(char *)\"swigconstant\", 1, 1,&module)) return NULL;\n"); } } else { - Printf(f_wrappers, tab2 "if (!PyArg_ParseTuple(args,(char*)\"O:swigconstant\", &module)) return NULL;\n"); + Printf(f_wrappers, tab2 "if (!PyArg_ParseTuple(args,(char *)\"O:swigconstant\", &module)) return NULL;\n"); } Printf(f_wrappers, tab2 "d = PyModule_GetDict(module);\n"); Printf(f_wrappers, tab2 "if (!d) return NULL;\n"); @@ -3737,13 +3737,13 @@ public: Node *parent = Swig_methodclass(n); String *basetype = Getattr(parent, "classtype"); Wrapper *w = NewWrapper(); - Printf(w->def, "SwigDirector_%s::SwigDirector_%s(PyObject* self) : Swig::Director(self) { \n", classname, classname); + Printf(w->def, "SwigDirector_%s::SwigDirector_%s(PyObject *self) : Swig::Director(self) { \n", classname, classname); Printf(w->def, " SWIG_DIRECTOR_RGTR((%s *)this, this); \n", basetype); Append(w->def, "}\n"); Wrapper_print(w, f_directors); DelWrapper(w); } - Printf(f_directors_h, " SwigDirector_%s(PyObject* self);\n", classname); + Printf(f_directors_h, " SwigDirector_%s(PyObject *self);\n", classname); Delete(classname); return Language::classDirectorDefaultConstructor(n); } @@ -3919,7 +3919,6 @@ public: int funpack = modernargs && fastunpack; 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"); if (baselist) { @@ -3933,8 +3932,8 @@ public: SwigType_add_pointer(base_name); String *base_mname = SwigType_manglestr(base_name); Printf(f_init, " builtin_basetype = SWIG_MangledTypeQuery(\"%s\");\n", base_mname); - Printv(f_init, " if (builtin_basetype && builtin_basetype->clientdata && ((SwigPyClientData*) builtin_basetype->clientdata)->pytype) {\n", NIL); - Printv(f_init, " builtin_bases[builtin_base_count++] = ((SwigPyClientData*) builtin_basetype->clientdata)->pytype;\n", NIL); + Printv(f_init, " if (builtin_basetype && builtin_basetype->clientdata && ((SwigPyClientData *) builtin_basetype->clientdata)->pytype) {\n", NIL); + Printv(f_init, " builtin_bases[builtin_base_count++] = ((SwigPyClientData *) builtin_basetype->clientdata)->pytype;\n", NIL); Printv(f_init, " } else {\n", NIL); Printf(f_init, " PyErr_SetString(PyExc_TypeError, \"Could not create type '%s' as base '%s' has not been initialized.\\n\");\n", symname, bname); Printv(f_init, "#if PY_VERSION_HEX >= 0x03000000\n", NIL); @@ -3956,13 +3955,7 @@ public: // Check for non-public destructor, in which case tp_dealloc will issue // a warning and allow the memory to leak. Any class that doesn't explicitly // have a private/protected destructor has an implicit public destructor. - String *tp_dealloc = Getattr(n, "feature:python:tp_dealloc"); - if (tp_dealloc) { - Printf(f, "SWIGPY_DESTRUCTOR_CLOSURE(%s)\n", tp_dealloc); - tp_dealloc = NewStringf("%s_closure", tp_dealloc); - } else { - tp_dealloc = NewString("SwigPyBuiltin_BadDealloc"); - } + static String *tp_dealloc_bad = NewString("SwigPyBuiltin_BadDealloc"); String *getset_name = NewStringf("%s_getset", templ); String *methods_name = NewStringf("%s_methods", templ); @@ -3984,12 +3977,12 @@ public: String *gspair = NewStringf("%s_%s_getset", symname, memname); Printf(f, "static SwigPyGetSet %s = { %s, %s };\n", gspair, getter ? getter : "0", setter ? setter : "0"); String *entry = - NewStringf("{ (char*) \"%s\", (getter) %s, (setter) %s, (char*)\"%s.%s\", (void*) &%s }\n", memname, getter_closure, + NewStringf("{ (char *) \"%s\", (getter) %s, (setter) %s, (char *)\"%s.%s\", (void *) &%s }\n", memname, getter_closure, setter_closure, name, memname, gspair); if (GetFlag(mgetset, "static")) { Printf(f, "static PyGetSetDef %s_def = %s;\n", gspair, entry); Printf(f_init, "static_getset = SwigPyStaticVar_new_getset(metatype, &%s_def);\n", gspair); - Printf(f_init, "PyDict_SetItemString(d, static_getset->d_getset->name, (PyObject*) static_getset);\n", memname); + Printf(f_init, "PyDict_SetItemString(d, static_getset->d_getset->name, (PyObject *) static_getset);\n", memname); Printf(f_init, "Py_DECREF(static_getset);\n"); } else { Printf(getset_def, " %s,\n", entry); @@ -4057,10 +4050,17 @@ public: quoted_symname = NewStringf("\"%s\"", symname); } String *quoted_tp_doc_str = NewStringf("\"%s\"", getSlot(n, "feature:python:tp_doc")); - char const *tp_init = builtin_tp_init ? Char(builtin_tp_init) : Swig_directorclass(n) ? "0" : "SwigPyBuiltin_BadInit"; + String *tp_init = NewString(builtin_tp_init ? Char(builtin_tp_init) : Swig_directorclass(n) ? "0" : "SwigPyBuiltin_BadInit"); String *tp_flags = NewString("Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_CHECKTYPES"); - String *py3_tp_flags = NewString("Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE"); + String *tp_flags_py3 = NewString("Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE"); + static String *tp_basicsize = NewStringf("sizeof(SwigPyObject)"); + static String *tp_dictoffset_default = NewString("offsetof(SwigPyObject, dict)"); + static String *tp_new = NewString("PyType_GenericNew"); + String *tp_as_number = NewStringf("&%s_type.as_number", templ); + String *tp_as_sequence = NewStringf("&%s_type.as_sequence", templ); + String *tp_as_mapping = NewStringf("&%s_type.as_mapping", templ); + String *tp_as_buffer = NewStringf("&%s_type.as_buffer", templ); Printf(f, "static PyHeapTypeObject %s_type = {\n", templ); @@ -4073,9 +4073,9 @@ public: printSlot(f, getSlot(), "ob_size"); Printv(f, "#endif\n", NIL); printSlot(f, quoted_symname, "tp_name"); - printSlot(f, "sizeof(SwigPyObject)", "tp_basicsize"); + printSlot(f, getSlot(n, "feature:python:tp_basicsize", tp_basicsize), "tp_basicsize"); printSlot(f, getSlot(n, "feature:python:tp_itemsize"), "tp_itemsize"); - printSlot(f, tp_dealloc, "tp_dealloc", "destructor"); + printSlot(f, getSlot(n, "feature:python:tp_dealloc", tp_dealloc_bad), "tp_dealloc", "destructor"); printSlot(f, getSlot(n, "feature:python:tp_print"), "tp_print", "printfunc"); printSlot(f, getSlot(n, "feature:python:tp_getattr"), "tp_getattr", "getattrfunc"); printSlot(f, getSlot(n, "feature:python:tp_setattr"), "tp_setattr", "setattrfunc"); @@ -4085,46 +4085,46 @@ public: printSlot(f, getSlot(n, "feature:python:tp_compare"), "tp_compare", "cmpfunc"); Printv(f, "#endif\n", NIL); printSlot(f, getSlot(n, "feature:python:tp_repr"), "tp_repr", "reprfunc"); - Printf(f, " &%s_type.as_number, /* tp_as_number */\n", templ); - Printf(f, " &%s_type.as_sequence, /* tp_as_sequence */\n", templ); - Printf(f, " &%s_type.as_mapping, /* tp_as_mapping */\n", templ); + printSlot(f, getSlot(n, "feature:python:tp_as_number", tp_as_number), "tp_as_number"); + printSlot(f, getSlot(n, "feature:python:tp_as_sequence", tp_as_sequence), "tp_as_sequence"); + printSlot(f, getSlot(n, "feature:python:tp_as_mapping", tp_as_mapping), "tp_as_mapping"); printSlot(f, getSlot(n, "feature:python:tp_hash"), "tp_hash", "hashfunc"); printSlot(f, getSlot(n, "feature:python:tp_call"), "tp_call", "ternaryfunc"); printSlot(f, getSlot(n, "feature:python:tp_str"), "tp_str", "reprfunc"); printSlot(f, getSlot(n, "feature:python:tp_getattro"), "tp_getattro", "getattrofunc"); printSlot(f, getSlot(n, "feature:python:tp_setattro"), "tp_setattro", "setattrofunc"); - Printf(f, " &%s_type.as_buffer, /* tp_as_buffer */\n", templ); + printSlot(f, getSlot(n, "feature:python:tp_as_buffer", tp_as_buffer), "tp_as_buffer"); Printv(f, "#if PY_VERSION_HEX >= 0x03000000\n", NIL); - printSlot(f, py3_tp_flags, "tp_flags"); + printSlot(f, getSlot(n, "feature:python:tp_flags", tp_flags_py3), "tp_flags"); Printv(f, "#else\n", NIL); - printSlot(f, tp_flags, "tp_flags"); + printSlot(f, getSlot(n, "feature:python:tp_flags", tp_flags), "tp_flags"); Printv(f, "#endif\n", NIL); printSlot(f, quoted_tp_doc_str, "tp_doc"); printSlot(f, getSlot(n, "feature:python:tp_traverse"), "tp_traverse", "traverseproc"); printSlot(f, getSlot(n, "feature:python:tp_clear"), "tp_clear", "inquiry"); - printSlot(f, richcompare_func, "feature:python:tp_richcompare", "richcmpfunc"); + printSlot(f, getSlot(n, "feature:python:tp_richcompare", richcompare_func), "tp_richcompare", "richcmpfunc"); printSlot(f, getSlot(n, "feature:python:tp_weaklistoffset"), "tp_weaklistoffset"); printSlot(f, getSlot(n, "feature:python:tp_iter"), "tp_iter", "getiterfunc"); printSlot(f, getSlot(n, "feature:python:tp_iternext"), "tp_iternext", "iternextfunc"); - printSlot(f, methods_name, "tp_methods"); + printSlot(f, getSlot(n, "feature:python:tp_methods", methods_name), "tp_methods"); printSlot(f, getSlot(n, "feature:python:tp_members"), "tp_members"); - printSlot(f, getset_name, "tp_getset"); + printSlot(f, getSlot(n, "feature:python:tp_getset", getset_name), "tp_getset"); printSlot(f, getSlot(n, "feature:python:tp_base"), "tp_base"); printSlot(f, getSlot(n, "feature:python:tp_dict"), "tp_dict"); printSlot(f, getSlot(n, "feature:python:tp_descr_get"), "tp_descr_get", "descrgetfunc"); printSlot(f, getSlot(n, "feature:python:tp_descr_set"), "tp_descr_set", "descrsetfunc"); - Printf(f, " (Py_ssize_t)offsetof(SwigPyObject, dict), /* tp_dictoffset */\n"); - printSlot(f, tp_init, "tp_init", "initproc"); + printSlot(f, getSlot(n, "feature:python:tp_dictoffset", tp_dictoffset_default), "tp_dictoffset", "Py_ssize_t"); + printSlot(f, getSlot(n, "feature:python:tp_init", tp_init), "tp_init", "initproc"); printSlot(f, getSlot(n, "feature:python:tp_alloc"), "tp_alloc", "allocfunc"); - printSlot(f, "0", "tp_new", "newfunc"); + printSlot(f, getSlot(n, "feature:python:tp_new", tp_new), "tp_new", "newfunc"); printSlot(f, getSlot(n, "feature:python:tp_free"), "tp_free", "freefunc"); - printSlot(f, getSlot(), "tp_is_gc", "inquiry"); - printSlot(f, getSlot(), "tp_bases", "PyObject*"); - printSlot(f, getSlot(), "tp_mro", "PyObject*"); - printSlot(f, getSlot(), "tp_cache", "PyObject*"); - printSlot(f, getSlot(), "tp_subclasses", "PyObject*"); - printSlot(f, getSlot(), "tp_weaklist", "PyObject*"); - printSlot(f, getSlot(), "tp_del", "destructor"); + printSlot(f, getSlot(n, "feature:python:tp_is_gc"), "tp_is_gc", "inquiry"); + printSlot(f, getSlot(n, "feature:python:tp_bases"), "tp_bases", "PyObject *"); + printSlot(f, getSlot(n, "feature:python:tp_mro"), "tp_mro", "PyObject *"); + printSlot(f, getSlot(n, "feature:python:tp_cache"), "tp_cache", "PyObject *"); + printSlot(f, getSlot(n, "feature:python:tp_subclasses"), "tp_subclasses", "PyObject *"); + printSlot(f, getSlot(n, "feature:python:tp_weaklist"), "tp_weaklist", "PyObject *"); + printSlot(f, getSlot(n, "feature:python:tp_del"), "tp_del", "destructor"); Printv(f, "#if PY_VERSION_HEX >= 0x02060000\n", NIL); printSlot(f, getSlot(n, "feature:python:tp_version_tag"), "tp_version_tag", "int"); Printv(f, "#endif\n", NIL); @@ -4132,13 +4132,13 @@ public: printSlot(f, getSlot(n, "feature:python:tp_finalize"), "tp_finalize", "destructor"); Printv(f, "#endif\n", NIL); Printv(f, "#ifdef COUNT_ALLOCS\n", NIL); - printSlot(f, getSlot(), "tp_allocs", "Py_ssize_t"); - printSlot(f, getSlot(), "tp_frees", "Py_ssize_t"); - printSlot(f, getSlot(), "tp_maxalloc", "Py_ssize_t"); + printSlot(f, getSlot(n, "feature:python:tp_allocs"), "tp_allocs", "Py_ssize_t"); + printSlot(f, getSlot(n, "feature:python:tp_frees"), "tp_frees", "Py_ssize_t"); + printSlot(f, getSlot(n, "feature:python:tp_maxalloc"), "tp_maxalloc", "Py_ssize_t"); Printv(f, "#if PY_VERSION_HEX >= 0x02050000\n", NIL); - printSlot(f, getSlot(), "tp_prev", "struct _typeobject*"); + printSlot(f, getSlot(n, "feature:python:tp_prev"), "tp_prev"); Printv(f, "#endif\n", NIL); - printSlot(f, getSlot(), "tp_next", "struct _typeobject*"); + printSlot(f, getSlot(n, "feature:python:tp_next"), "tp_next"); Printv(f, "#endif\n", NIL); Printf(f, " },\n"); @@ -4177,7 +4177,7 @@ public: Printv(f, "#endif\n", NIL); printSlot(f, getSlot(n, "feature:python:nb_int"), "nb_int", "unaryfunc"); Printv(f, "#if PY_VERSION_HEX >= 0x03000000\n", NIL); - printSlot(f, getSlot(n, "feature:python:nb_reserved"), "nb_reserved", "void*"); + printSlot(f, getSlot(n, "feature:python:nb_reserved"), "nb_reserved", "void *"); Printv(f, "#else\n", NIL); printSlot(f, getSlot(n, "feature:python:nb_long"), "nb_long", "unaryfunc"); Printv(f, "#endif\n", NIL); @@ -4226,13 +4226,13 @@ public: printSlot(f, getSlot(n, "feature:python:sq_repeat"), "sq_repeat", "ssizeargfunc"); printSlot(f, getSlot(n, "feature:python:sq_item"), "sq_item", "ssizeargfunc"); Printv(f, "#if PY_VERSION_HEX >= 0x03000000\n", NIL); - printSlot(f, getSlot(n, "feature:was_sq_slice"), "was_sq_slice", "void*"); + printSlot(f, getSlot(n, "feature:python:was_sq_slice"), "was_sq_slice", "void *"); Printv(f, "#else\n", NIL); printSlot(f, getSlot(n, "feature:python:sq_slice"), "sq_slice", "ssizessizeargfunc"); Printv(f, "#endif\n", NIL); printSlot(f, getSlot(n, "feature:python:sq_ass_item"), "sq_ass_item", "ssizeobjargproc"); Printv(f, "#if PY_VERSION_HEX >= 0x03000000\n", NIL); - printSlot(f, getSlot(n, "feature:was_sq_ass_slice"), "was_sq_ass_slice", "void*"); + printSlot(f, getSlot(n, "feature:python:was_sq_ass_slice"), "was_sq_ass_slice", "void *"); Printv(f, "#else\n", NIL); printSlot(f, getSlot(n, "feature:python:sq_ass_slice"), "sq_ass_slice", "ssizessizeobjargproc"); Printv(f, "#endif\n", NIL); @@ -4256,13 +4256,13 @@ public: Printf(f, " },\n"); // PyObject *ht_name, *ht_slots, *ht_qualname; - printSlot(f, getSlot(n, "feature:python:ht_name"), "ht_name", "PyObject*"); - printSlot(f, getSlot(n, "feature:python:ht_slots"), "ht_slots", "PyObject*"); + printSlot(f, getSlot(n, "feature:python:ht_name"), "ht_name", "PyObject *"); + printSlot(f, getSlot(n, "feature:python:ht_slots"), "ht_slots", "PyObject *"); Printv(f, "#if PY_VERSION_HEX >= 0x03030000\n", NIL); - printSlot(f, getSlot(n, "feature:python:ht_qualname"), "ht_qualname", "PyObject*"); + printSlot(f, getSlot(n, "feature:python:ht_qualname"), "ht_qualname", "PyObject *"); // struct _dictkeysobject *ht_cached_keys; - printSlot(f, getSlot(n, "feature:python:ht_cached_keys"), "ht_cached_keys", "struct _dictkeysobject*"); + printSlot(f, getSlot(n, "feature:python:ht_cached_keys"), "ht_cached_keys"); Printv(f, "#endif\n", NIL); Printf(f, "};\n\n"); @@ -4281,7 +4281,7 @@ public: String *clientdata_klass = NewString("0"); if (GetFlag(n, "feature:implicitconv")) { Clear(clientdata_klass); - Printf(clientdata_klass, "(PyObject*) &%s_type", templ); + Printf(clientdata_klass, "(PyObject *) &%s_type", templ); } Printf(f, "SWIGINTERN SwigPyClientData %s_clientdata = {%s, 0, 0, 0, 0, 0, (PyTypeObject *)&%s_type};\n\n", templ, clientdata_klass, templ); @@ -4295,7 +4295,7 @@ public: Printv(f_init, "#endif\n", NIL); Printv(f_init, " }\n", NIL); Printv(f_init, " Py_INCREF(builtin_pytype);\n", NIL); - Printf(f_init, " PyModule_AddObject(m, \"%s\", (PyObject*) builtin_pytype);\n", symname); + Printf(f_init, " PyModule_AddObject(m, \"%s\", (PyObject *)builtin_pytype);\n", symname); Printf(f_init, " SwigPyBuiltin_AddPublicSymbol(public_interface, \"%s\");\n", symname); Printv(f_init, " d = md;\n", NIL); @@ -4306,11 +4306,15 @@ public: Delete(mname); Delete(pmname); Delete(templ); - Delete(tp_dealloc); Delete(tp_flags); - Delete(py3_tp_flags); + Delete(tp_flags_py3); + Delete(tp_as_buffer); + Delete(tp_as_mapping); + Delete(tp_as_sequence); + Delete(tp_as_number); Delete(quoted_symname); Delete(quoted_tp_doc_str); + Delete(tp_init); Delete(clientdata_klass); Delete(richcompare_func); Delete(getset_name); @@ -4483,7 +4487,7 @@ public: SwigType_add_pointer(p_real_classname); String *mangle = SwigType_manglestr(p_real_classname); String *descriptor = NewStringf("SWIGTYPE%s", mangle); - Printv(none_comparison, "self->ob_type != ((SwigPyClientData*) (", descriptor, ")->clientdata)->pytype", NIL); + Printv(none_comparison, "self->ob_type != ((SwigPyClientData *)(", descriptor, ")->clientdata)->pytype", NIL); Delete(descriptor); Delete(mangle); Delete(p_real_classname); @@ -4510,12 +4514,12 @@ public: Printv(f_wrappers, " PyObject *obj;\n", NIL); if (modernargs) { if (fastunpack) { - Printv(f_wrappers, " if (!SWIG_Python_UnpackTuple(args,(char*)\"swigregister\", 1, 1,&obj)) return NULL;\n", NIL); + Printv(f_wrappers, " if (!SWIG_Python_UnpackTuple(args,(char *)\"swigregister\", 1, 1,&obj)) return NULL;\n", NIL); } else { - Printv(f_wrappers, " if (!PyArg_UnpackTuple(args,(char*)\"swigregister\", 1, 1,&obj)) return NULL;\n", NIL); + Printv(f_wrappers, " if (!PyArg_UnpackTuple(args,(char *)\"swigregister\", 1, 1,&obj)) return NULL;\n", NIL); } } else { - Printv(f_wrappers, " if (!PyArg_ParseTuple(args,(char*)\"O:swigregister\", &obj)) return NULL;\n", NIL); + Printv(f_wrappers, " if (!PyArg_ParseTuple(args,(char *)\"O:swigregister\", &obj)) return NULL;\n", NIL); } Printv(f_wrappers, @@ -4658,13 +4662,13 @@ public: int argcount = Getattr(n, "python:argcount") ? atoi(Char(Getattr(n, "python:argcount"))) : 2; String *ds = have_docstring(n) ? cdocstring(n, AUTODOC_FUNC) : NewString(""); if (check_kwargs(n)) { - Printf(builtin_methods, " { \"%s\", (PyCFunction) %s, METH_VARARGS|METH_KEYWORDS, (char*) \"%s\" },\n", symname, wname, ds); + Printf(builtin_methods, " { \"%s\", (PyCFunction) %s, METH_VARARGS|METH_KEYWORDS, (char *) \"%s\" },\n", symname, wname, ds); } else if (argcount == 0) { - Printf(builtin_methods, " { \"%s\", (PyCFunction) %s, METH_NOARGS, (char*) \"%s\" },\n", symname, wname, ds); + Printf(builtin_methods, " { \"%s\", (PyCFunction) %s, METH_NOARGS, (char *) \"%s\" },\n", symname, wname, ds); } else if (argcount == 1) { - Printf(builtin_methods, " { \"%s\", (PyCFunction) %s, METH_O, (char*) \"%s\" },\n", symname, wname, ds); + Printf(builtin_methods, " { \"%s\", (PyCFunction) %s, METH_O, (char *) \"%s\" },\n", symname, wname, ds); } else { - Printf(builtin_methods, " { \"%s\", (PyCFunction) %s, METH_VARARGS, (char*) \"%s\" },\n", symname, wname, ds); + Printf(builtin_methods, " { \"%s\", (PyCFunction) %s, METH_VARARGS, (char *) \"%s\" },\n", symname, wname, ds); } Delete(fullname); Delete(wname); @@ -4765,7 +4769,7 @@ public: Append(pyflags, "METH_VARARGS"); if (have_docstring(n)) { String *ds = cdocstring(n, AUTODOC_STATICFUNC); - Printf(builtin_methods, " { \"%s\", (PyCFunction) %s, %s, (char*) \"%s\" },\n", symname, wname, pyflags, ds); + Printf(builtin_methods, " { \"%s\", (PyCFunction) %s, %s, (char *) \"%s\" },\n", symname, wname, pyflags, ds); Delete(ds); } else { Printf(builtin_methods, " { \"%s\", (PyCFunction) %s, %s, \"\" },\n", symname, wname, pyflags); @@ -4967,12 +4971,10 @@ public: if (builtin && in_class) { Node *cls = Swig_methodclass(n); + // Use the destructor for the tp_dealloc slot unless a user overrides it with another method if (!Getattr(cls, "feature:python:tp_dealloc")) { - String *dealloc = Swig_name_destroy(NSPACE_TODO, symname); - String *wdealloc = Swig_name_wrapper(dealloc); - Setattr(cls, "feature:python:tp_dealloc", wdealloc); - Delete(wdealloc); - Delete(dealloc); + Setattr(n, "feature:python:slot", "tp_dealloc"); + Setattr(n, "feature:python:slot:functype", "destructor"); } } @@ -5552,9 +5554,9 @@ int PYTHON::classDirectorMethod(Node *n, Node *parent, String *super) { Append(w->code, "}\n"); Append(w->code, "#if defined(SWIG_PYTHON_DIRECTOR_VTABLE)\n"); Printf(w->code, "const size_t swig_method_index = %d;\n", director_method_index++); - Printf(w->code, "const char * const swig_method_name = \"%s\";\n", pyname); + Printf(w->code, "const char *const swig_method_name = \"%s\";\n", pyname); - Append(w->code, "PyObject* method = swig_get_method(swig_method_index, swig_method_name);\n"); + Append(w->code, "PyObject *method = swig_get_method(swig_method_index, swig_method_name);\n"); if (Len(parse_args) > 0) { if (use_parse || !modernargs) { Printf(w->code, "swig::SwigVar_PyObject %s = PyObject_CallFunction(method, (char *)\"(%s)\" %s);\n", Swig_cresult_name(), parse_args, arglist); @@ -5564,7 +5566,7 @@ int PYTHON::classDirectorMethod(Node *n, Node *parent, String *super) { } else { if (modernargs) { Append(w->code, "swig::SwigVar_PyObject args = PyTuple_New(0);\n"); - Printf(w->code, "swig::SwigVar_PyObject %s = PyObject_Call(method, (PyObject*) args, NULL);\n", Swig_cresult_name()); + Printf(w->code, "swig::SwigVar_PyObject %s = PyObject_Call(method, (PyObject *) args, NULL);\n", Swig_cresult_name()); } else { Printf(w->code, "swig::SwigVar_PyObject %s = PyObject_CallFunction(method, NULL, NULL);\n", Swig_cresult_name()); }