Reputation: 424
I am trying to figure out how to return 2 vales from a C function that I called in python. I have read through the material online and am using struct to output the two variables. I am able to output the variables when I call this function in the same C file. However, when I try to call it in python, it still only returns one value.
This is my C code:
struct re_val {
double predict_label;
double prob_estimates;
};
struct re_val c_func(const char* dir, double a, double b, double c, double d )
{
double x[] = {a,b,c,d};
printf ("x[0].index: %d \n", 1);
printf ("x[0].value: %f \n", x[0]);
printf ("x[1].index: %d \n", 2);
printf ("x[1].value: %f \n", x[1]);
printf ("x[2].index: %d \n", 3);
printf ("x[2].value: %f \n", x[2]);
printf ("x[3].index: %d \n", 4);
printf ("x[3].value: %f \n", x[3]);
printf ("\nThis is the Directory: %s \n", dir);
struct re_val r;
r.predict_label = 5.0;
r.prob_estimates = 8.0;
return r;
}
This is my Python code:
calling_function = ctypes.CDLL("/home/ruven/Documents/Sonar/C interface/Interface.so")
calling_function.c_func.argtypes = [ctypes.c_char_p, ctypes.c_double, ctypes.c_double, ctypes.c_double, ctypes.c_double]
calling_function.c_func.restype = ctypes.c_double
q = calling_function.c_func("hello",1.3256, 2.45, 3.1248, 4.215440)
print q
Currently, when I run my python file in the terminal it outputs this:
x[0].index: 1
x[0].value: 1.325600
x[1].index: 2
x[1].value: 2.450000
x[2].index: 3
x[2].value: 3.124800
x[3].index: 4
x[3].value: 4.215440
This is the Directory: hello
5.0
Instead,I would like it to output this:
x[0].index: 1
x[0].value: 1.325600
x[1].index: 2
x[1].value: 2.450000
x[2].index: 3
x[2].value: 3.124800
x[3].index: 4
x[3].value: 4.215440
This is the Directory: hello
5.0
8.0
Upvotes: 2
Views: 1508
Reputation: 4431
Your C code is fine, the problem you are experiencing is in how you use python ctypes. You should tell that the function returns a struct re_val
and not a double:
calling_function.c_func.restype = ctypes.c_double
The above makes the function return a single double value in the eyes of ctypes. You should tell python that the function returns a structure:
import ctypes as ct
# Python representation of the C struct re_val
class ReVal(ct.Structure):
_fields_ = [("predict_label", ct.c_double),("prob_estimates", ct.c_double)]
calling_function = ctypes.CDLL("/home/ruven/Documents/Sonar/C interface/Interface.so")
calling_function.c_func.argtypes = [ctypes.c_char_p, ctypes.c_double, ctypes.c_double, ctypes.c_double, ctypes.c_double]
# and instead of c_double use:
calling_function.c_func.restype = ReVal
This way you tell python's ctypes that the function returns a aggregate object that is a subclass of ctypes.Structure that matches the struct re_val
from the c library.
NOTE Be very carefull with argtypes and restype, if you use these incorrectly it is easy to crash the python interpreter. Then you get a segfault instead of a nice traceback.
Upvotes: 3