2

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
asked Jul 5, 2018 at 8:06
3
  • I don't know this code will work or not but. check this link. it may be helpful to you. gist.github.com/Overdrivr/cdd58cea15d7e28c50ea Commented Jul 5, 2018 at 8:29
  • 1
    The problem is incalling_function.c_func.restype = ctypes.c_double You are essentially telling to ctypes the the function result type is a c_double, whereas the function from you c library doesn't return a double, it returns a struct re_val. Commented Jul 5, 2018 at 9:02
  • @hetepeperfan I thought about that but i couldn't find a way to change calling_function.c_func.restype to return a struct as ctypes.c_struct does not exist. Commented Jul 5, 2018 at 9:12

1 Answer 1

3

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.

answered Jul 5, 2018 at 9:48
Sign up to request clarification or add additional context in comments.

2 Comments

Hi, unfortunately when I run the program it gives me the following message: <__main__.ReVal object at 0x7fb3bd1e0560>
Yes, that is right, but that is the struct as returned by ctypes, it is still an aggregate. So the returned object has two fields "predict_label" and "prob_estimates". So you can access them via q.predict_label and q.prob_estimates You generally need to take some extra steps to extract the values from the struct.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.