2016-10-18 18 views
11

Próbowałem wszystkich rozwiązań wymienionych w internecie, jak dotąd nic nie działało dla mnie.Używanie funkcji języka C w języku Python

Mam kod Pythona, aby przyspieszyć, chcę, aby mój kod wykonywał ciężkie obliczenia w funkcji C. Już napisałem tę funkcję C.

Następnie, aby udostępnić bibliotekę, zrobiłem to w terminalu:

gcc -shared -Wl,-install_name,testlib.so -o testlib.so -fPIC myModule.c 

która zwraca żadnego błędu. Problem; przychodzi, gdy próbuję uruchomić funkcję C w python. Rozważmy następującą prostą funkcję w C:

int multiplier(int a, int b) 
{ 

int lol = 0; 

lol = a*b; 

return lol; 
} 

ja uruchomić python3 (3.5.2), a następnie:

import ctypes 
zelib = ctypes.CDLL("/Users/longeard/Desktop/Codes/DraII/testlib.so",ctypes.RTLD_GLOBAL) 

Biblioteka powinna być gotowa do użycia w Pythonie, wykonując:

res = zelib.multiplier(2,3) 

Kiedy robi, że to działa i Python powraca

6 

Problem polega na tym, że funkcja, której chcę użyć (funkcja mnożnika, której używam jest właśnie dla przykładu) powinna przyjmować wartości pływające jako dane wejściowe i zwracać wartość zmiennoprzecinkową. Ale jeśli teraz rozważyć taką samą funkcję mnożnika jak wcześniej, ale z pływakiem:

float multiplier(float a, float b) 
{ 

float lol = 0.0; 

lol = a*b; 

return lol; 
} 

I ponownie skompilować przy użyciu gcc, ja ponownie importować ctypes i ponownie zrobić ctypes.CDLL, a ja w python3:

zelib.multiplier(ctypes.c_float(2),ctypes.c_float(3)) 

(the types.c_float tutaj, aby przekształcić 2 w Pythonie do pływaka w C), pyton powróci:

2 

to dziwne, bo jeśli dodać printf wewnątrz funkcji, aby wydrukować lol, Python drukuj:

6.0 

ale nadal zwraca 2 lub 18 czasami. Mimo, że printf i zwraca tę samą zmienną "lol".

Próbowałem wielu rzeczy i nic z tego nie zadziałało. Czy ktoś ma pomysł, proszę? Dziękuję Ci.

Odpowiedz

2

Podczas użytkownika @ falsetru odpowiedź jest lepszy sposób to zrobić alternatywą jest po prostu napisać funkcję C do używania podwójnych.

Pływaki są automatycznie promowane do podwójnego podczas wywoływania funkcji bez listy parametrów.

7

musisz określić restype, argtypes funkcji:

zelib = ctypes.CDLL('...') 
zelib.multiplier.restype = ctypes.c_float # return type 
zelib.multiplier.argtypes = [ctypes.c_float, ctypes.c_float] # argument types 

według Specifying the required argument types (function prototypes):

Jest możliwe, aby określić żądane typy argumentów funkcji eksportowanych z DLL ustawiając argtypes atrybut.

i Return types w ctypes module documentation:

przez funkcje domyślne zakłada powrót typ C int.Inne typy powrotów można określić, ustawiając atrybut restype obiektu funkcji.


# 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 
+1

Dziękuję, działa jak urok! Próbowałem tego kilka razy wczoraj, z jakiegoś powodu nie zadziałało, ale teraz tak jest. – Nicano

+0

Przepraszam za podwójny komentarz .... Czy zdajesz sobie sprawę, jak przekazać numpy float array jako dane wejściowe w tym przypadku? I zwróci tablicę również w funkcji C? Dziękuję Ci. – Nicano

+0

@Nicano, sprawdź to: http://docs.scipy.org/doc/numpy/reference/generated/numpy.ndarray.ctypes.html Jeśli masz więcej pytań, opublikuj to jako kolejne pytanie. – falsetru