Calling a python method from C/C++, and extracting its return value
As explained before, using PyRun_SimpleString seems to be a bad idea.
You should definitely use the methods provided by the C-API (http://docs.python.org/c-api/).
Reading the introduction is the first thing to do to understand the way it works.
First, you have to learn about PyObject that is the basic object for the C API. It can represent any kind of python basic types (string, float, int,...).
Many functions exist to convert for example python string to char* or PyFloat to double.
First, import your module :
PyObject* myModuleString = PyString_FromString((char*)"mytest");PyObject* myModule = PyImport_Import(myModuleString);
Then getting a reference to your function :
PyObject* myFunction = PyObject_GetAttrString(myModule,(char*)"myabs");PyObject* args = PyTuple_Pack(1,PyFloat_FromDouble(2.0));
Then getting your result :
PyObject* myResult = PyObject_CallObject(myFunction, args)
And getting back to a double :
double result = PyFloat_AsDouble(myResult);
You should obviously check the errors (cf. link given by Mark Tolonen).
If you have any question, don't hesitate. Good luck.
Here is a sample code I wrote (with the help of various online sources) to send a string to a Python code, then return a value.
Here is the C code call_function.c
:
#include <Python.h>#include <stdlib.h>int main(){ // Set PYTHONPATH TO working directory setenv("PYTHONPATH",".",1); PyObject *pName, *pModule, *pDict, *pFunc, *pValue, *presult; // Initialize the Python Interpreter Py_Initialize(); // Build the name object pName = PyString_FromString((char*)"arbName"); // Load the module object pModule = PyImport_Import(pName); // pDict is a borrowed reference pDict = PyModule_GetDict(pModule); // pFunc is also a borrowed reference pFunc = PyDict_GetItemString(pDict, (char*)"someFunction"); if (PyCallable_Check(pFunc)) { pValue=Py_BuildValue("(z)",(char*)"something"); PyErr_Print(); printf("Let's give this a shot!\n"); presult=PyObject_CallObject(pFunc,pValue); PyErr_Print(); } else { PyErr_Print(); } printf("Result is %d\n",PyInt_AsLong(presult)); Py_DECREF(pValue); // Clean up Py_DECREF(pModule); Py_DECREF(pName); // Finish the Python Interpreter Py_Finalize(); return 0;}
Here is the Python code, in file arbName.py
:
def someFunction(text): print 'You passed this Python program '+text+' from C! Congratulations!' return 12345
I use the command gcc call_function.c -I/usr/include/python2.6 -lpython2.6 ; ./a.out
to run this process. I'm on redhat. I recommend using PyErr_Print(); for error checking.
A complete example of calling a Python function and retrieving the result is located at http://docs.python.org/release/2.6.5/extending/embedding.html#pure-embedding:
#include <Python.h>intmain(int argc, char *argv[]){ PyObject *pName, *pModule, *pDict, *pFunc; PyObject *pArgs, *pValue; int i; if (argc < 3) { fprintf(stderr,"Usage: call pythonfile funcname [args]\n"); return 1; } Py_Initialize(); pName = PyString_FromString(argv[1]); /* Error checking of pName left out */ pModule = PyImport_Import(pName); Py_DECREF(pName); if (pModule != NULL) { pFunc = PyObject_GetAttrString(pModule, argv[2]); /* pFunc is a new reference */ if (pFunc && PyCallable_Check(pFunc)) { pArgs = PyTuple_New(argc - 3); for (i = 0; i < argc - 3; ++i) { pValue = PyInt_FromLong(atoi(argv[i + 3])); if (!pValue) { Py_DECREF(pArgs); Py_DECREF(pModule); fprintf(stderr, "Cannot convert argument\n"); return 1; } /* pValue reference stolen here: */ PyTuple_SetItem(pArgs, i, pValue); } pValue = PyObject_CallObject(pFunc, pArgs); Py_DECREF(pArgs); if (pValue != NULL) { printf("Result of call: %ld\n", PyInt_AsLong(pValue)); Py_DECREF(pValue); } else { Py_DECREF(pFunc); Py_DECREF(pModule); PyErr_Print(); fprintf(stderr,"Call failed\n"); return 1; } } else { if (PyErr_Occurred()) PyErr_Print(); fprintf(stderr, "Cannot find function \"%s\"\n", argv[2]); } Py_XDECREF(pFunc); Py_DECREF(pModule); } else { PyErr_Print(); fprintf(stderr, "Failed to load \"%s\"\n", argv[1]); return 1; } Py_Finalize(); return 0;}