How to pass floats into a ctypes function on python


How to pass floats into a ctypes function on python



To give some background, I have a C code as follows:


int c_func(const char* dir, float a, float b, float c, float d )
{
printf("%sn", dir);
printf("%fn",a);
printf("%fn",b);
printf("%fn",c);
printf("%fn",d);

return 0;
}



This is a simple function that takes in a string and 4 floats as arguments and prints them out as I am trying to test my phython/C interface. My python code is as follows:


calling_function = ctypes.CDLL("/home/ruven/Documents/Sonar/C interface/Interface.so")
calling_function.c_func.argtypes = [ctypes.c_char_p, ctypes.c_float, ctypes.c_float, ctypes.c_float, ctypes.c_float]

for _fv in _testFV:
_predOut = calling_function.c_func("hello",_fv[0], _fv[1], _fv[2], _fv[3])
exit(1)



To clarify, _fv[0], _fv[1], _fv[2], _fv[3] are [1.969591, 112.7779, 1.8701470000000002, 111.7575] respectively. And _testFV is a list of 117 other lists. I am just looking to extract the first list from _testFV.


_fv[0], _fv[1], _fv[2], _fv[3]


[1.969591, 112.7779, 1.8701470000000002, 111.7575]



After running this code, I am able to correctly print the string but the floats seem to be large random numbers instead of the actual values of _fv[0], _fv[1], _fv[2], _fv[3]. So to check if I am passing the right values into the calling_function.c_func function,I included a print statement to print the value of _fv[0], _fv[1], _fv[2], _fv[3] and their types. I checked and the values are floats and the correct numbers are being inputted into the function. Therefore, I am not really sure what is going on. Any help would be much appreciated. Thanks!


_fv[0], _fv[1], _fv[2], _fv[3]


calling_function.c_func


_fv[0], _fv[1], _fv[2], _fv[3]



*Note that I have changed my previous question of how to input an array from python to C to how to input floats from python to C.





There's no such thing as a list in C. All you can have is an aray, or a pointer, in both case common practice is to give an extra parameter indicating the length of the array. To transform a Python list into a C array, I think this question might help you.
– joH1
22 hours ago





Python, C and liststs... you'll get a job next week.
– purec
22 hours ago





calling_function.c_func("hello",*[1,2,3,4]) works with no changes. Note you are using %d in your printf. You want %f` for floats. To pass them correctly, set the .argtypes e.g. c_func.argtypes = c_char_p,c_float,c_float,c_float,c_float. Right now you are passing them default c_int which is why %d seems to work.
– Mark Tolonen
15 hours ago



calling_function.c_func("hello",*[1,2,3,4])


%d


. You want


.argtypes


c_func.argtypes = c_char_p,c_float,c_float,c_float,c_float


c_int


%d





@MarkTolonen Thank you for your reply. I have editted my code but still seem to have an issue with the python/C interface. I have updated my original question to reflect the new issue. Please do let me know if you are able to help. Thanks.
– Ruven Guna
2 mins ago




1 Answer
1



How do I code a C function to accept a list as its arguments?



Short answer, you can't.



Long answer: C does not have lists, but has arrays and pointers.



You have several options then:


int c_func(const char *dir, float abcd[4]) { // using an array with explicit size

int c_func(const char *dir, float abcd) { // Using an array (will decay to a pointer at compile-time)

int c_func(const char *dir, float *abcd) { // Using a pointer.



If you will only ever receive 4 floats, I'd suggest the first form, which enforces the size of the array, any user (and mainly your future self) of your function will know to give only an array of four elements.



Calling your function from Python:


floats = [1.0, 2.0, 3.0, 4.0] # Or whatever values you want to pass, but be sure to give only 4
FloatArray4 = ctypes.c_float * 4 # Define a 4-length array of floats
parameter_array = FloatArray4(*floats) # Define the actual array to pass to your C function



I don't know if passing more than 4 floats to FloatArray4 raises an error -- I guess so, but I can't check right now.


FloatArray4



As for your second question, if you want dynamic sized arrays (more than 4 elements), you'll have to you one of the other two profiles for your C function, in which case I advise you to put an extra int argument for the size of the array:


int


int c_func(const char *dir, float floats, int size) {



or


int c_func(const char *dir, float *floats, int size) {



You can also use the standard size_t instead of int, it's designed just for that.


size_t


int



I you want to pass a multidimensional array, you add another pair of brackets:


int c_func(const char *dir, float floats[4]) { // Note the explicit size for second dimension



but remember that for a C array, for all dimensions but the first, the dimensions must be explicitly specified. If the value is constant it wont be an issue, however if not you will have to use a pointer instead:


int c_func(const char *dir, float *floats) {



or


int c_func(const char *dir, float **floats) {



which are two identical syntaxs (the array will decay to a pointer). Once again, if your dimensions are dynamic, I suggest to add parameters for the size.



If you want supplementary dimensions, just repeat that last step.





Thanks for taking the time to reply me and for clearing my doubts!
– Ruven Guna
21 hours ago





Glad I could help! If you have any remarks or something's still unclear I can edit my answer :)
– joH1
21 hours ago





Sorry to bother you, but I have another question. Instead of putting it here, I edited my original question as it is rather long. Please do let me know if you are able to answer it. Thank you.
– Ruven Guna
6 mins ago







By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Comments

Popular posts from this blog

paramiko-expect timeout is happening after executing the command

how to run turtle graphics in Colaboratory

Export result set on Dbeaver to CSV