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..6258534c7 --- /dev/null +++ b/Examples/test-suite/python/python_builtin_runme.py @@ -0,0 +1,26 @@ +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()") + diff --git a/Examples/test-suite/python_builtin.i b/Examples/test-suite/python_builtin.i new file mode 100644 index 000000000..977b57ec7 --- /dev/null +++ b/Examples/test-suite/python_builtin.i @@ -0,0 +1,74 @@ +// 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"; + } +}; +%} + diff --git a/Lib/python/builtin.swg b/Lib/python/builtin.swg index 5767a1422..abf5f71cb 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; \ }