script_helper.assert_python_ok("-c", script)
+class PyObjectRestypeTest(unittest.TestCase):
+ def test_restype_py_object_with_null_return(self):
+ # Test that a function which returns a NULL PyObject *
+ # without setting an exception does not crash.
+ PyErr_Occurred = ctypes.pythonapi.PyErr_Occurred
+ PyErr_Occurred.argtypes = []
+ PyErr_Occurred.restype = ctypes.py_object
+
+ # At this point, there's no exception set, so PyErr_Occurred
+ # returns NULL. Given the restype is py_object, the
+ # ctypes machinery will raise a custom error.
+ with self.assertRaisesRegex(ValueError, "PyObject is NULL"):
+ PyErr_Occurred()
+
+
if __name__ == '__main__':
unittest.main()
if (info->getfunc && !_ctypes_simple_instance(st, restype)) {
retval = info->getfunc(result, info->size);
/* If restype is py_object (detected by comparing getfunc with
- O_get), we have to call Py_DECREF because O_get has already
- called Py_INCREF.
+ O_get), we have to call Py_XDECREF because O_get has already
+ called Py_INCREF, unless the result was NULL, in which case
+ an error is set (by the called function, or by O_get).
*/
if (info->getfunc == _ctypes_get_fielddesc("O")->getfunc) {
- Py_DECREF(retval);
+ Py_XDECREF(retval);
}
}
else {