Reputation: 278
I'm have difficulty with a seeming simple problem. There are various C functions that I need to call from Python code. Currently, I'm trying to do this through ctypes. I'm having issues with a simple example implementation that I'm using to ensure that everything works as intended before changing large chunks of existing code. The C functions take a few parameters, do various mathematical calculations, and then return a double value. This is the C file that I'm using 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'm printing val1 and val2 to ensure they're receiving values. Everything is fine on that end. The Python that calls this function is the following.
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 this prints the returned result, it usually dumps a large negative number. It's my assumption that I need to do some converting before Python can handle the value, but I can't find an answer for that for the life of me. I've searched forever, but I'm not certain if I'm missing the obvious, or searching for the wrong information.
Also, if I change the return type of the function to int, the calculations turn out correct and an int is returned and printed as expected. If I set it to double, the calculations are correct in the C code (I print them to check), but Python doesn't like the returned result.
Any ideas what I'm missing?
Upvotes: 9
Views: 8913
Reputation: 400146
You should set the function's argument types and return type in Python using the argtypes
and restype
members:
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 like you're doing: construct arrays of type (ctypes.c_double * length)
initialized with your values, and the result
will be a double
.
See also this ctypes tutorial, it has lots of useful info.
Upvotes: 16