Any robust code needs to handle error conditions, so we'll add some simple examples of how to return errors back to the calling Python code.
Using a standard Python exception
As an example, let's change our code to disallow negative values:
PyObject* py_add( PyObject* pSelf, PyObject* pArgs ) { // extract the arguments int val1, val2 ; if ( ! PyArg_ParseTuple( pArgs, "ii", &val1, &val2 ) ) return NULL ; // check the value if ( val1 < 0 || val2 < 0 ) { PyErr_SetString( PyExc_ValueError, "Can't handle negative values." ) ; return NULL ; } // add the numbers int result = val1 + val2 ; return PyLong_FromLong( result ) ; }
If either of the values is negative, we call PyErr_SetString() to specify the type of exception we want to return to the caller (ValueError), and an error message.
Build and install the extension as before, and we can see it in action:
Note that this is equivalent to throw'ing a ValueError exception in Python code, and so it can be caught as such:
try: print( demo.add( 5, -2 ) ) except ValueError as ex: print( "ERROR: {}".format( ex ) )
Defining a custom exception class
If you want to use your own custom exception class, this needs to be set up when the module is loaded:
PyObject* gpZeroError = NULL ; PyMODINIT_FUNC PyInit_demo() { // create the Python module PyObject* pModule = PyModule_Create( &gModuleDef ) ; if ( pModule == NULL ) return NULL ; // create our custom exception gpZeroError = PyErr_NewException( "demo.ZeroError", NULL, NULL ) ; PyModule_AddObject( pModule, "ZeroError", gpZeroError ) ; return pModule ; }
We call PyErr_NewException() to create a new exception class, then add it to the module.
This new exception class can now be used as any other:
if ( val1 == 0 || val2 == 0 ) { PyErr_SetString( gpZeroError, "Can't handle zero." ) ; return NULL ; }

« Calling functions | Tutorial index | Callbacks » |