Extending and Embedding Python, Release 3.9.5 Chapter 2. Creating extensions without third party tools 6 which pulls in the Python API (you can add a comment describing the purpose of the module and a copyright notice if you like). Note: Since Python may define some pre-processor definitions which affect the standard headers on some systems, you must include$_{Python.h}$ before any standard headers are included. It is recommended to always define PY_SSIZE_T_CLEAN before including Python.h . See Extracting Parameters in Extension Functions for a description of this macro. All user-visible symbols defined by$_{Python.h}$ have a prefix of$_{Py}$ or$_{PY}$ , except those defined in standard header files. For convenience, and since they are used extensively by the Python interpreter,$_{"Python.h"}$ includes a few standard header files:$_{<stdio.h>}$ ,$_{<string.h>}$ ,$_{<errno.h>}$ , and$_{<stdlib.h>}$ . If the latter header file does not exist on your system, it declares the functions malloc() , free() and realloc() directly. The next thing we add to our module file is the C function that will be called when the Python expression spam. system(string) is evaluated (we’ll see shortly how it ends up being called): There is a straightforward translation from the argument list in Python (for example, the single expression$_{"ls -l"}$ ) to the arguments passed to the C function. The C function always has two arguments, conventionally named self and args . The self argument points to the module object for module-level functions; for a method it would point to the object instance. The args argument will be a pointer to a Python tuple object containing the arguments. Each item of the tuple corresponds to an argument in the call’s argument list. The arguments are Python objects — in order to do anything with them in our C function we have to convert them to C values. The function$_{PyArg_ParseTuple()}$ in the Python API checks the argument types and converts them to C values. It uses a template string to determine the required types of the arguments as well as the types of the C variables into which to store the converted values. More about this later. PyArg_ParseTuple() returns true (nonzero) if all arguments have the right type and its components have been stored in the variables whose addresses are passed. It returns false (zero) if an invalid argument list was passed. In the latter case it also raises an appropriate exception so the calling function can return$_{NULL}$ immediately (as we saw in the example). An important convention throughout the Python interpreter is the following: when a function fails, it should set an exception condition and return an error value (usually a NULL pointer). Exceptions are stored in a static global variable inside the interpreter; if this variable is$_{NULL}$ no exception has occurred. A second global variable stores the “associated value” of the exception (the second argument to$_{raise}$ ). A third variable contains the stack traceback in case the error originated in Python code. These three variables are the C equivalents of the result in Python of sys.exc_info() (see the section on module$_{sys}$ in the Python Library Reference). It is important to know about them to understand how errors are passed around. The Python API defines a number of functions to set various types of exceptions. 2.1.2 Intermezzo: Errors and Exceptions static PyObject * spam_system(PyObject *self, PyObject*args) { const char *command; int sts; if (!PyArg_ParseTuple(args, "s",&command)) return NULL ; sts =system(command); return PyLong_FromLong(sts); }