Error returning values ​​from a C function called from Python

I have problems with a seemingly simple problem. There are various C functions that I need to call from Python code. I am currently trying to do this through ctypes. I am having problems with a simple example implementation that I use to ensure that everything works as planned before changing large chunks of existing code. C functions take several parameters, perform various mathematical calculations, and then return a double value. This is the C file that I use as a test.

#include "Python.h" double eval(double* args, int length, double* rands, int randLength, int debug) { double val1 = args[0]; double val2 = rands[0]; double ret = val1 + val2; return ret; } 

In my actual test function, I print val1 and val2 to make sure they get the values. Everything is fine for this purpose. The Python that calls this function is as follows.

 test = ctypes.CDLL("/home/mjjoyce/Dev/C2M2L/AquaticWavesModel.so") rand = Random(); args = [2] argsArr = (ctypes.c_double * len(args))() argsArr[:] = args argsRand = [rand.random()] argsRandArr = (ctypes.c_double * len(argsRand))() rgsRandArr[:] = argsRand result = test.eval(argsArr, len(argsArr), argsRandArr, len(argsRandArr), 0) print "result", result 

When printing the result, a large negative number usually appears. This is my assumption that I need to do some conversions before Python can handle this value, but I cannot find an answer for this for me. I searched forever, but I'm not sure if I am missing the obvious or looking for the wrong information.

Also, if I change the return type of the function to int, the calculations are correct, and the int is returned and printed as expected. If I double it, the calculations are correct in the C code (I print them out to check), but Python doesn't like the returned result.

Any ideas what I am missing?

+7
source share
1 answer

You must set the function argument types and return type in Python using the argtypes and restype :

 test.eval.argtypes = [ctypes.POINTER(ctypes.c_double), ctypes.c_int, ctypes.POINTER(ctypes.c_double), ctypes.c_int, ctypes.c_int] test.eval.restype = ctypes.c_double 

Then you can call it the way you do: build arrays of type (ctypes.c_double * length) , initialized with your values, and the result will be double .

See also this ctypes tutorial , it contains a lot of useful information.

+9
source

All Articles