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:
- METH_VARARGS: This is a typical convention for the Python function or method that accepts only arguments as its parameters. The type provided as the ml_meth field for such a function should be PyCFunction. The function will be provided with two arguments of the PyObject* type. The first is either the self object (for methods) or the module object (for module functions). A typical signature for the C function with that calling convention is PyObject* function(PyObject* self, PyObject* args).
- METH_KEYWORDS: This is the convention for the Python function that accepts keyword arguments when called. Its associated C type is PyCFunctionWithKeywords. The C function must accept three arguments of the PyObject* type—self, args, and a dictionary of keyword arguments. If combined with METH_VARARGS, the first two arguments have the same meaning as for the previous calling convention, otherwise, args will be NULL. The typical C function signature is—PyObject* function(PyObject* self, PyObject* args, PyObject* keywds).
- METH_NOARGS: This is the convention for Python functions that do not accept any other argument. The C function should be of the PyCFunction type, so the signature is the same as that of the METH_VARARGS convention (self and args arguments). The only difference is that args will always be NULL, so there is no need to call PyArg_ParseTuple(). This cannot be combined with any other calling convention flag.
- METH_O: This is the shorthand for functions and methods accepting single object arguments. The type of C function is again PyCFunction, so it accepts two PyObject* arguments: self and args. Its difference from METH_VARARGS is that there is no need to call PyArg_ParseTuple() because PyObject* provided as args will already represent the single argument provided in the Python call to that function. This also cannot be combined with any other calling convention flag.
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:
- Functions with default values for arguments
- Functions with arguments specified as keyword-only
- Functions with variable numbers of arguments
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.