2015-05-21 16 views
5

Đây là mã C của tôi, tôi đã tạo một thư điện tử dùng chung. Khi tôi tải lib được chia sẻ trong Python và thực thi mã Python bên dưới, tôi gặp sự cố. Tại sao?Tại sao Python gặp sự cố khi trả về chuỗi C?

extern "C" { 
PyObject* foo2(char* b) 
{ 
    return Py_BuildValue("s", b); 
} 

} 

Và đây là những gì tôi đang làm bằng Python:

from ctypes import * 
    d = cdll.LoadLibrary('./foo.so') 
    d.foo2.restype = c_char_p 
    v = d.foo2('hello world') 
    print pythonapi.PyString_Size(v) 

Nếu nó giúp, tôi đang ở python2.6.

+1

'c_char_p' - không có nghĩa là' char * '? bạn không ** trả về 'char *'… –

+1

Tại sao bạn sử dụng 'ctypes' để mở một thư viện có sử dụng Python API, thay vì làm cho thư viện đó là một mô-đun mở rộng Python? – interjay

Trả lời

4

Bạn đang nói cdll rằng hàm trả về char* nhưng thực tế nó trả về một PyObject*. Cả hai cần phải đồng ý.

9

Vấn đề của bạn là bạn đang nói dối về kiểu trả về:

d.foo2.restype = c_char_p 

Kiểu trả về thực tế là PyObject *. Nhưng ctypes sẽ thấy rằng c_char_p, hãy đúc PyObject * thành char * và sau đó cố gắng chuyển đổi char * thành chuỗi bằng PyString_FromString, sẽ đọc ai biết byte nào tùy ý cho đến khi nó đạt đến ký tự NUL.

Cách chỉ định PyObject * là với py_object.

Ngoài ra, bạn có thể muốn đặt argtype s. Và lần này, nó thực sự một c_char_p:

d = cdll.LoadLibrary('./foo.so') 
d.foo2.argtypes = [c_char_p] 
d.foo2.restype = py_object 

Nhưng, như interjay chỉ ra trong một chú thích, đó là một chút ngớ ngẩn được xây dựng một thư viện C có sử dụng API Python C và sau đó gọi nó qua ctypes. Đây là thỉnh thoảng hữu ích, nhưng thông thường, giải pháp là chỉ cần hoàn thành việc xây dựng mô-đun mở rộng C thay vì làm 80% công việc vì không có lợi ích nào…

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