2016-10-18 3 views
11

Ich habe alle im Internet genannten Lösungen ausprobiert, bisher hat nichts für mich funktioniert.Verwenden einer C-Funktion in Python

Ich habe einen Python-Code, um es zu beschleunigen, möchte ich, dass mein Code die schweren Berechnungen in einer C-Funktion ausführt. Ich habe diese C-Funktion bereits geschrieben.

Dann die Bibliothek zu teilen, ich habe dies in der Klemme:

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

, die keinen Fehler zurückgibt. Das Problem; kommt, wenn ich versuche, die C-Funktion in Python zu starten. Lassen Sie uns die folgende einfache Funktion in C berücksichtigen:

int multiplier(int a, int b) 
{ 

int lol = 0; 

lol = a*b; 

return lol; 
} 

I starten python3 (3.5.2) und dann:

:

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

Die Bibliothek sollte in Python verwenden, indem Sie bereit sein,

res = zelib.multiplier(2,3) 

Wenn das zu tun, es funktioniert und python kehrt

6 

Problem ist, dass die Funktion, die ich verwenden möchte (die Multiplikatorfunktion, die ich verwende, nur für das Beispiel ist), Floats als Eingabe nehmen und einen Float zurückgeben soll. Aber wenn ich jetzt die gleiche Multiplikator-Funktion betrachten wie zuvor, aber mit float:

float multiplier(float a, float b) 
{ 

float lol = 0.0; 

lol = a*b; 

return lol; 
} 

ich gcc rekompilieren verwenden, wieder importieren ich ctypes und wieder tun ctypes.CDLL, und ich in python3:

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

(die types.c_float sind hier die 2 in python in einen Schwimmer in C konvertieren), wird python zurück:

2 

das ist seltsam, denn wenn ich eine printf innerhalb der Funktion hinzufügen lol zu drucken, python Druck:

6.0 

aber immer noch 2, oder 18 manchmal zurück. Obwohl ich printf und die gleiche Variable "lol" zurückgeben.

Ich habe viele Dinge ausprobiert, und nichts davon hat funktioniert. Hat jemand eine Idee? Danke.

Antwort

2

Während @ falsetru Antwort ist der bessere Weg, es eine Alternative zu tun ist, einfach Ihre C-Funktion schreiben verdoppelt zu verwenden.

Floats werden beim Aufruf einer Funktion ohne Parameterliste automatisch auf Double hochgestuft.

7

Sie benötigen restype, argtypes der Funktion zu spezifizieren:

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

Nach Specifying the required argument types (function prototypes):

Es ist möglich, die erforderlichen Argumenttypen von Funktionen aus DLLs exportiert angeben, indem Sie die argtypes Einstellung Attribut.

und Return types in ctypes module documentation:

standardmäßig Funktionen sind davon ausgegangen, den C-Typ int zurück.Andere Rückgabetypen können über das Attribut restype des Funktionsobjekts angegeben werden.


# 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

Danke, funktioniert wie ein Charme! Ich habe das gestern schon mehrmals versucht, aus irgendeinem Grund hat es nicht funktioniert, aber jetzt tut es das. – Nicano

+0

Entschuldigung für den doppelten Kommentar .... Wissen Sie zufällig, wie man in diesem Fall ein numpiges Float-Array als Eingabe übergibt? Und ein Array in der C-Funktion auch zurückgeben? Vielen Dank. – Nicano

+0

@ Nicano, überprüfen Sie dies: http://docs.scipy.org/doc/numpy/reference/generated/numpy.darray.ctypes.html Wenn Sie mehr Frage haben, bitte posten Sie es als eine andere Frage. – falsetru

Verwandte Themen