I try to implement a Python function using the Python C API, that has a functionality similar to (this implementation is simplified and does not include things like NULL check of keywds):
def my_func(arg1, arg2 = 2, **kwargs):
if arg2 == 1:
# expect certain parameters to be in kwargs
if arg2 == 2:
# expect different parameters to be in kwargs
if arg2 == 3:
# call a Python function with the kwargs (whats in the kwargs is unknown)
PythonFunc(**kwargs)
arg1 and arg2 can be both named and unnamed arguments.
The best I came up with was the following:
PyObject* my_func(PyObject* /*self*/, PyObject* args, PyObject* keywds) {
PyObject* arg1, arg2;
switch(PyTuple_Size(args)) {
case 0:
arg1 = PyDict_GetItemString(keywds, "arg1");
if (arg2) PyDict_DelItemString(keywds, "arg1");
else // throw TypeError
arg2 = PyDict_GetItemString(keywds, "arg2");
if (arg2) PyDict_DelItemString(keywds, "arg2");
break;
case 1:
arg1 = PyTuple_GET_ITEM(args, 0);
if (PyDict_GetItemString(keywds, "arg1")) // throw TypeError
arg2 = PyDict_GetItemString(keywds, "arg2");
if (arg2) PyDict_DelItemString(keywds, "arg2");
break;
case 2:
arg1 = PyTuple_GET_ITEM(args, 0);
if (PyDict_GetItemString(keywds, "arg1")) // throw TypeError
arg2 = PyTuple_GET_ITEM(args, 1);
if (PyDict_GetItemString(keywds, "arg2")) // throw TypeError
break;
default:
// throw TypeError
}
if (...) // parse remaining keywds according to requirements
else // call Python functions using the remaining keyword arguments
}
This can become quite extensive when the functions have more arguments. Is there a simpler way to achieve this behaviour e.g. using PyArg_ParseTupleAndKeywords
?