I'm trying to embed a Python (2.7) library in my C application and I'm using the Python/C API to call Python code from C. I need to call a Python method that takes keyword arguments. Semantically, I'm trying to achieve the equivalent of the following line in Python:
myobject.dosomething('blahdy blah', somearg=True)
By reading the documentation, I have managed to get as far as the following, but this doesn't pass in the keyword arguments:
PyObject_CallMethod(myobject, "dosomething", "s", "blahdy blah");
I'm not super familiar with Python and I'm kind of stuck at this point as the documentation is not entirely clear on this and Google searches didn't turn up much useful info either. I'd appreciate any help.
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.
There are two types of arguments in a function which are positional arguments (declared by a name only) and keyword arguments (declared by a name and a default value). When a function is called, values for positional arguments must be given.
To "call" means to make a reference in your code to a function that is written elsewhere. This function "call" can be made to the standard Python library (stuff that comes installed with Python), third-party libraries (stuff other people wrote that you want to use), or your own code (stuff you wrote).
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.
Tamas's answer will get the job done, but it will also leak memory. To avoid leaks, use
PyObject *args = Py_BuildValue("(s)", "blahdy blah");
PyObject *keywords = PyDict_New();
PyDict_SetItemString(keywords, "somearg", Py_True);
PyObject *myobject_method = PyObject_GetAttrString(myobject, "do something");
PyObject *result = PyObject_Call(myobject_method, args, keywords);
Py_DECREF(args);
Py_DECREF(keywords);
Py_DECREF(myobject_method);
// Do something with the result
Py_DECREF(result);
Of course, if there are any errors or exceptions in the Python code some of the PyObjects will be NULL and your program will probably crash. Checking for NULL results and/or using Py_DECREFX()
can help you avoid this.
In the end I used PyObject_Call to do this (thanks Bakuriu for the hint!). Just in case anyone wonders how to do that, here's my code:
PyObject *args = Py_BuildValue("(s)", "blahdy blah");
PyObject *keywords = PyDict_New();
PyDict_SetItemString(keywords, "somearg", Py_True);
PyObject_Call(PyObject_GetAttrString(myobject, "do something"), args, keywords);
Py_DECREF(args);
Py_DECREF(keywords);
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