I've been trying to learn how to write C-extensions for Python and want to be sure I understand how PyArg_ParseTupleAndKeywords works.
I believe that the first argument is a PyObject pointer that points to an array of the arguments being passed into the C-extension function in the order they were passed. The second argument is a list of keywords that were passed, the positions at which they were passed and, very likely, some sort of indicator flag telling at which position the keywords begin and position becomes irrelevant.
PyArg_ParseTupleAndKeywords then uses its list of keywords (4th argument) to map between arguments specified with a keyword and both the format string (3rd argument) and addresses of C variables (5th & + arguments) to which the appropriate values should be copied.
Is my understanding correct? When I read through the online documentation, all I see are references to "positional arguments and keyword arguments", which leave me feeling a little bit in the dark. Where is the file for the Python interpreter that handles PyArg_ParseTupleAndKeywords?
PyObject is an object structure that you use to define object types for Python. All Python objects share a small number of fields that are defined using the PyObject structure. All other object types are extensions of this type. PyObject tells the Python interpreter to treat a pointer to an object as an object.
Keyword arguments (or named arguments) are values that, when passed into a function, are identifiable by specific parameter names. A keyword argument is preceded by a parameter and the assignment operator, = . Keyword arguments can be likened to dictionaries in that they map a value to a keyword. A.
Python has a built-in function str() which converts the passed argument into a string format. The str() function returns a string version of an object. The object can be int , char , or a string . If the object is not passed as an argument, then it returns an empty string.
To emulate the following in python:
def keywords(a, b, foo=None, bar=None, baz=None):
pass
The following will work:
static PyObject *keywords(PyObject *self, PyObject *args, PyObject *kwargs)
{
char *a;
char *b;
char *foo = NULL;
char *bar = NULL;
char *baz = NULL;
// Note how "a" and "b" are included in this
// even though they aren't supposed to be in kwargs like in python
static char *kwlist[] = {"a", "b", "foo", "bar", "baz", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss|sss", kwlist,
&a, &b, &foo, &bar, &baz))
{
return NULL;
}
printf("a is %s\n", a);
printf("b is %s\n", b);
printf("foo is %s\n", foo);
printf("bar is %s\n", bar);
printf("baz is %s\n", baz);
Py_RETURN_NONE;
}
// ...
static PyMethodDef SpamMethods[] =
{
// ...
{"keywords", (PyCFunction) keywords, METH_VARARGS | METH_KEYWORDS, "practice kwargs"},
{NULL, NULL, 0, NULL}
// ...
}
And to use it:
from spam import keywords
keywords() # Fails, require a and b
keywords('a') # fails, requires b
keywords('a', 'b')
keywords('a', 'b', foo='foo', bar='bar', baz='baz')
keywords('a', 'b','foo', 'bar', 'baz')
keywords(a='a', b='b', foo='foo', bar='bar', baz='baz')
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With