2012-08-03 12 views
7

Mam problem z pozornie prostym problemem. Istnieją różne funkcje C, które muszę wywołać z kodu Pythona. Obecnie próbuję to zrobić poprzez ctypes. Mam problemy z prostą przykładową implementacją, której używam, aby upewnić się, że wszystko działa zgodnie z oczekiwaniami przed zmianą dużych fragmentów istniejącego kodu. Funkcje C pobierają kilka parametrów, wykonują różne obliczenia matematyczne, a następnie zwracają podwójną wartość. Jest to plik C, którego używam jako testu.Problem z zwracaniem wartości z funkcji C wywołanej z Pythona

#include "Python.h" 

double eval(double* args, int length, double* rands, int randLength, int debug) 
{ 
    double val1 = args[0]; 
    double val2 = rands[0]; 
    double ret = val1 + val2; 
    return ret; 
} 

W moim rzeczywistej funkcji testowej mam drukowania VAL1 i wart2 aby upewnić się, że otrzymujesz wartości. W tym celu wszystko jest w porządku. Python wywołujący tę funkcję jest następujący.

test = ctypes.CDLL("/home/mjjoyce/Dev/C2M2L/AquaticWavesModel.so") 
rand = Random(); 

args = [2] 
argsArr = (ctypes.c_double * len(args))() 
argsArr[:] = args 

argsRand = [rand.random()] 
argsRandArr = (ctypes.c_double * len(argsRand))() 
rgsRandArr[:] = argsRand 

result = test.eval(argsArr, len(argsArr), argsRandArr, len(argsRandArr), 0) 
print "result", result 

Po wydrukowaniu zwróconego wyniku zwykle zrzuca dużą liczbę ujemną. Zakładam, że muszę przeprowadzić jakąś konwersję, zanim Python poradzi sobie z wartością, ale nie mogę znaleźć na to odpowiedzi dla mojego życia. Szukałem na zawsze, ale nie jestem pewien, czy brakuje mi oczywistości, czy szukałem niewłaściwych informacji.

Ponadto, jeśli zmienię typ zwracanej funkcji na int, obliczenia są prawidłowe, a int jest zwracane i drukowane zgodnie z oczekiwaniami. Jeśli ustawię ją na podwójną, obliczenia są poprawne w kodzie C (wydrukuję je do sprawdzenia), ale Python nie lubi zwracanego wyniku.

Jakieś pomysły, których mi brakuje?

Odpowiedz

9

należy ustawić typy argumentów tej funkcji, czyli i typ zwracany w Pythonie przy użyciu argtypes i restype członków:

test.eval.argtypes = [ctypes.POINTER(ctypes.c_double), 
         ctypes.c_int, 
         ctypes.POINTER(ctypes.c_double), 
         ctypes.c_int, 
         ctypes.c_int] 
test.eval.restype = ctypes.c_double 

Następnie można nazwać jak robisz: skonstruować tablice typu (ctypes.c_double * length) zainicjowane ze swoimi wartościami , a result będzie to double.

Zobacz także ten ctypes tutorial, ma wiele przydatnych informacji.

+0

Dziękuję bardzo za rozwiązanie i link. Samouczek jest dokładnie tym, czego szukałem! – lively