2012-08-03 28 views
7

Tôi gặp khó khăn với một vấn đề có vẻ đơn giản. Có nhiều hàm C khác nhau mà tôi cần gọi từ mã Python. Hiện tại, tôi đang cố gắng thực hiện điều này thông qua ctypes. Tôi đang gặp vấn đề với việc triển khai ví dụ đơn giản mà tôi đang sử dụng để đảm bảo rằng mọi thứ hoạt động như dự định trước khi thay đổi các đoạn mã lớn hiện có. Các hàm C lấy một vài tham số, thực hiện các phép tính toán học khác nhau và sau đó trả về một giá trị kép. Đây là tệp C mà tôi đang sử dụng làm bài kiểm tra.Phát hành các giá trị trả lại từ hàm C được gọi từ Python

#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; 
} 

Trong chức năng kiểm tra thực tế của tôi Tôi đang in VAL1 VAL2 để đảm bảo họ đang nhận được giá trị. Mọi thứ đều tốt đẹp vào cuối. Python gọi hàm này là như sau.

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 

Khi điều này in kết quả trả về, nó thường đổ một số âm lớn. Đó là giả định của tôi rằng tôi cần phải làm một số chuyển đổi trước khi Python có thể xử lý giá trị, nhưng tôi không thể tìm thấy một câu trả lời cho điều đó cho cuộc sống của tôi. Tôi đã tìm kiếm mãi mãi, nhưng tôi không chắc chắn nếu tôi bị thiếu hiển nhiên, hoặc tìm kiếm thông tin sai.

Ngoài ra, nếu tôi thay đổi kiểu trả về của hàm thành int, các tính toán sẽ chính xác và một int được trả về và in như mong đợi. Nếu tôi thiết lập nó để tăng gấp đôi, các tính toán là chính xác trong mã C (tôi in chúng để kiểm tra), nhưng Python không thích kết quả trả về.

Bất kỳ ý tưởng nào tôi đang thiếu?

Trả lời

9

Bạn nên đặt loại đối số của hàm và kiểu trả về bằng Python sử dụng argtypesrestype thành viên:

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 

Sau đó, bạn có thể gọi nó như bạn đang thực hiện: xây dựng các mảng kiểu (ctypes.c_double * length) khởi tạo với giá trị của bạn và số result sẽ là double.

Xem thêm điều này ctypes tutorial, nó có rất nhiều thông tin hữu ích.

+0

Cảm ơn bạn rất nhiều vì giải pháp và liên kết. Hướng dẫn chính xác là những gì tôi đang tìm kiếm! – lively

Các vấn đề liên quan