Calling and binding conventions

As explained in the A closer look at Python/C API section, the ml_flags bit field of the PyMethodDef structure contains flags for calling and binding conventions. Calling convention flags are as follows:

A function that accepts keywords is described either with METH_KEYWORDS or bitwise combinations of calling convention flags in the form of METH_VARARGS | METH_KEYWORDS. If so, it should parse its arguments with PyArg_ParseTupleAndKeywords() instead of PyArg_ParseTuple() or PyArg_UnpackTuple().

Here is an example module with a single function that returns None and accepts two named keyword arguments that are printed on standard output:

#include <Python.h> 
 
static PyObject* print_args(PyObject *self, PyObject *args, 
PyObject *keywds) { char *first; char *second; static char *kwlist[] = {"first", "second", NULL}; if (!PyArg_ParseTupleAndKeywords(args, keywds, "ss", kwlist, &first, &second)) return NULL; printf("%s %s\n", first, second); Py_INCREF(Py_None); return Py_None; } static PyMethodDef module_methods[] = { {"print_args", (PyCFunction)print_args, METH_VARARGS | METH_KEYWORDS, "print provided arguments"}, {NULL, NULL, 0, NULL} }; static struct PyModuleDef module_definition = { PyModuleDef_HEAD_INIT, "kwargs", "Keyword argument processing example", -1, module_methods }; PyMODINIT_FUNC PyInit_kwargs(void) { return PyModule_Create(&module_definition); }

Argument parsing in Python/C API is very elastic and is extensively described in the official documentation at https://docs.python.org/3.7/c-api/arg.html. The format argument in PyArg_ParseTuple() and PyArg_ParseTupleAndKeywords() allows fine-grained control over argument number and types. Every advanced calling convention known from Python can be coded in C with this API including the following:

The binding convention flags METH_CLASS, METH_STATIC, and METH_COEXIST are reserved for methods and cannot be used to describe module functions. The first two are quite self-explanatory. They are C counterparts of classmethod and staticmethod decorators and change the meaning of the self argument passed to the C function.

METH_COEXIST allows loading a method in place of the existing definition. It is useful very rarely. This is mostly in the case when you would like to provide an implementation of the C method that would be generated automatically from the other features of the type that was defined. The Python documentation gives the example of the __contains__() wrapper method that would be generated if the type has the sq_contains slot defined. Unfortunately, defining own classes and types using Python/C API is beyond the scope of this introductory chapter.

Let's take a look at exception handling in the next section.