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 ;
}
Download the source code here.| « Calling functions | Tutorial index | Callbacks » |











I am a 
