I've tried all the solutions mentioned on the internet so far nothing worked for me.
I have a python code, to speed it up, I want that my code runs the heavy calculations in a C function. I already wrote this C function.
Then, to share the library, I did this in the terminal :
gcc -shared -Wl,-install_name,testlib.so -o testlib.so -fPIC myModule.c
which returns no error. The problem; comes when i try to launch the C function in python. Let's consider the following simple function in C :
int multiplier(int a, int b)
{
int lol = 0;
lol = a*b;
return lol;
}
I launch python3 (3.5.2), and then :
import ctypes
zelib = ctypes.CDLL("/Users/longeard/Desktop/Codes/DraII/testlib.so",ctypes.RTLD_GLOBAL)
The library should be ready to use in python by doing :
res = zelib.multiplier(2,3)
When doing that, it works and python returns
6
Problem is, that the function i want to use ( the multiplier function I use is just for the example ) is supposed to take floats as input and return a float. But if I now consider the same multiplier function as before but with float :
float multiplier(float a, float b)
{
float lol = 0.0;
lol = a*b;
return lol;
}
I recompile using gcc, I reimport ctypes and re-do ctypes.CDLL, and I do in python3 :
zelib.multiplier(ctypes.c_float(2),ctypes.c_float(3))
(the types.c_float are here to convert the 2 in python into a float in C ), python will return :
2
This is weird because if I add a printf within the function to print lol, python will print :
6.0
but still return 2, or 18 sometimes. Even though I printf and return the same variable "lol".
I tried a lot of things, and none of it worked. Do somebody have a idea please ? Thank You.
You need to specify restype
, argtypes
of the function:
zelib = ctypes.CDLL('...')
zelib.multiplier.restype = ctypes.c_float # return type
zelib.multiplier.argtypes = [ctypes.c_float, ctypes.c_float] # argument types
According to Specifying the required argument types (function prototypes):
It is possible to specify the required argument types of functions exported from DLLs by setting the
argtypes
attribute.
and Return types in ctypes
module documentation:
By default functions are assumed to return the C int type. Other return types can be specified by setting the
restype
attribute of the function object.
# without specifying types
>>> import ctypes
>>> zelib = ctypes.CDLL('testlib.so')
>>> zelib.multiplier(2, 3)
0
# specifying types
>>> zelib.multiplier.restype = ctypes.c_float
>>> zelib.multiplier.argtypes = [ctypes.c_float, ctypes.c_float]
>>> zelib.multiplier(2, 3)
6.0
While @falsetru's answer is the better way of doing it an alternative is to simply write your C function to use doubles.
Floats are automatically promoted to double when calling a function without a parameter list.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With