2013-05-22 28 views
8

Tôi đang cố sử dụng ctypes để tạo một mảng char * trong python được chuyển tới thư viện để điền chuỗi. Tôi mong đợi 4 chuỗi không quá 7 ký tự.Python sử dụng ctypes để chuyển mảng char * và điền vào các kết quả

đang py tôi trông như thế

testlib.py này

from ctypes import * 
primesmile = CDLL("/primesmile/lib.so") 

getAllNodeNames = primesmile.getAllNodeNames 
getAllNodeNames.argtypes = [POINTER(c_char_p)] 
results = (c_char_p * 4)(addressof(create_string_buffer(7))) 
err = getAllNodeNames(results) 

lib.cpp

void getAllNodeNames(char **array){ 
    DSL_idArray nodes; //this object returns const char * when iterated over 
    network.GetAllNodeIds(nodes); 
    for(int i = 0; i < (nodes.NumItems()); i++){ 
    strcpy(array[i],nodes[i]); 
    } 
} 

tôi tiếp tục nhận lỗi segmentation khi tôi cố gắng chạy mã này . Tôi đã tạo ra một thử nghiệm từ C hoạt động hoàn hảo nhưng trong Python tôi phải thiết lập các mảng con trỏ không chính xác hoặc một cái gì đó. Dường như nó đến nút thứ hai trong vòng lặp và sau đó có một vấn đề như tôi đã nhìn thấy từ việc phun ra dữ liệu vào dòng lệnh. Bất kỳ cái nhìn sâu sắc sẽ được nhiều đánh giá cao.

Trả lời

9

Các mã sau hoạt động:

thử nghiệm.py:

import ctypes 
lib = ctypes.CDLL("./libtest.so") 
string_buffers = [ctypes.create_string_buffer(8) for i in range(4)] 
pointers = (ctypes.c_char_p*4)(*map(ctypes.addressof, string_buffers)) 
lib.test(pointers) 
results = [s.value for s in string_buffers] 
print results 

test.c (biên soạn để libtest.so với gcc test.c -o libtest.so -shared -fPIC):

#include <string.h> 
void test(char **strings) { 
    strcpy(strings[0],"this"); 
    strcpy(strings[1],"is"); 
    strcpy(strings[2],"a"); 
    strcpy(strings[3],"test!"); 
} 

Như Aya nói, bạn nên chắc chắn có chỗ cho sự chấm dứt không. Nhưng tôi nghĩ vấn đề chính của bạn là bộ đệm chuỗi là rác được thu thập hoặc một cái gì đó tương tự, vì không có tham chiếu trực tiếp đến nó nữa. Hoặc một cái gì đó khác gây ra rắc rối trong quá trình tạo các bộ đệm chuỗi khi không có tài liệu tham khảo nào được lưu trữ cho chúng. Ví dụ: kết quả này trong bốn lần cùng một địa chỉ thay vì các địa chỉ khác nhau:

import ctypes 
pointers = [ctypes.addressof(ctypes.create_string_buffer(8)) for i in range(4)] 
print pointers 
+3

Bạn cũng có thể tạo mảng 2D cho bộ đệm: 'string_buffers = ((ctypes.c_char * 8) * 4)()'. Nó sẽ lặp lại giống nhau khi bạn định nghĩa 'con trỏ' trên dòng tiếp theo. – eryksun

2

tôi không thể (dễ dàng) kiểm tra mã, nhưng dựa trên những gì bạn đã nói, tôi đoán sẽ là vấn đề nằm trong dòng ...

results = (c_char_p * 4)(addressof(create_string_buffer(7))) 

Theo các tài liệu Python cho create_string_buffer() ...

init_or_size phải là số nguyên trong đó xác định kích thước của mảng, hoặc một chuỗi đó sẽ được sử dụng để khởi tạo các mục mảng.

Nếu chuỗi được chỉ định làm đối số đầu tiên, bộ đệm được tạo thành một mục lớn hơn chiều dài của chuỗi sao cho phần tử cuối cùng trong mảng là ký tự kết thúc NUL. Một số nguyên có thể được chuyển thành đối số thứ hai là cho phép xác định kích thước của mảng nếu không sử dụng độ dài của chuỗi.

... trong đó hàm ý nó tạo ra một char[7], nhưng một strcpy() sẽ cố gắng sao chép các NULL terminator cho một chuỗi, vì vậy nếu tối đa "tên nút" chiều dài của bạn là bảy ký tự, bạn sẽ cần một char[8] để giữ NULL, mặc dù bạn có thể lấy đi bằng cách sử dụng memcpy(array[i], nodes[i], 7) thay vì strcpy().

Dù bằng cách nào, có thể là an toàn nhất để sử dụng create_string_buffer(8) thay thế.

3

Trong dòng này:

results = (c_char_p * 4)(addressof(create_string_buffer(7))) 

Bạn đang tạo một bộ đệm duy nhất của 7 byte, sau đó cố gắng sử dụng nó để giữ 4 con trỏ ký tự (mà có lẽ là 4 byte mỗi), và sau đó cũng sao chép 4 Các chuỗi 8 byte vào các địa chỉ ngẫu nhiên mà nó có thể xảy ra để trỏ đến. Bạn cần cấp phát một bộ đệm cho mỗi chuỗi và cũng phân bổ mảng con trỏ. Một cái gì đó như thế này:

s = [] 
for i in range(4): 
    s[i] = create_string_buffer(8) 
results = (c_char_p * 4)(s); 
Các vấn đề liên quan