12

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.

2 Answers 2

7

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
Sign up to request clarification or add additional context in comments.

3 Comments

Thank you, works like a charm ! I actually tried that several times yesterday, for some reason it didn't work, but now it does.
Sorry for the double comment .... DO you happen to know how to pass numpy float array as an input in this case ? And return an array in the C function as well ? Thank you.
@Nicano, Check this out: docs.scipy.org/doc/numpy/reference/generated/… If you have more question, please post it as another question.
2

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.

Comments

Your Answer

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.