Juan Bravo Juan Bravo - 1 month ago 7
C Question

Call function from python with tuple return in c

I'm trying to call a python function from my C script. I success to return a double variable from the python function and print it in my C script. The problem I have now is that I need to return multiple variables (tuple) from python. How can I success that? My code with a single variable return is as follows:

#include <python2.7/Python.h>

int main(){
PyObject *pName, *pModule, *pDict, *pFunc;
PyObject *pArgs, *pValue;
int i;
double read;

Py_Initialize();
PyObject* sysPath = PySys_GetObject((char*)"path");
PyList_Append(sysPath, PyString_FromString("."));
pName = PyString_FromString("eadata"); //Primer posible error
pModule = PyImport_Import(pName);
Py_DECREF(pName);

if(pModule != NULL){
pFunc = PyObject_GetAttrString(pModule,"lectura");
if(pFunc && PyCallable_Check(pFunc)){
pValue = PyObject_CallObject(pFunc,NULL);
if(pValue != NULL){
printf("Result of call: %lf \n", PyFloat_AsDouble(pValue));
Py_DECREF(pValue);
}
else{
Py_DECREF(pFunc);
Py_DECREF(pModule);
PyErr_Print();
fprintf(stderr,"Call failed\n");
return 1;
}
}
}
else{
PyErr_Print();
fprintf(stderr, "Error al cargar eadata.py \n");
}
}


My python script is:

def lectura():

device = '/dev/ttyUSB0'
baudrate = 115200
mt=mtdevice1.MTDevice(device, baudrate)

ax=mtdevice1.acx
ay=mtdevice1.acy
az=mtdevice1.acz

wx=mtdevice1.wx
wy=mtdevice1.wy
wz=mtdevice1.wz

mx=mtdevice1.mx
my=mtdevice1.my
mz=mtdevice1.mz

roll = mtdevice1.roll
pitch = mtdevice1.pitch
yaw = mtdevice1.yaw
pc = mtdevice1.pc

return ax


This works, but I want to return other variables at the same time such as ay,az, and so on. Is my first time using embedded python and I really don't know how to do this.

Answer

With a small caveat, you can use PyArg_ParseTuple to take apart the tuple returned by the function you call.

This will work fine as long as the returned tuple matches the format string you provide to PyArg_ParseTuple. If there is a mismatch, the error produced by PyArg_ParseTuple will be misleading because it assumes that the tuple is an argument tuple.

A less convenient but more general approach is to use the tuple API.