Python использует ctypes для передачи массива char * и заполнения результатов
Я пытаюсь использовать ctypes для создания массива char * в python для передачи в библиотеку для заполнения строками. Я ожидаю 4 строки назад не более 7 символов в длину каждый.
мой код py выглядит так
testlib.py
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]);
}
}
Я продолжаю получать ошибки сегментации при попытке запустить этот код. Я создал тест из C, который отлично работает, но в Python я должен неправильно настраивайте массив указателей или что-то в этом роде. Кажется, он добирается до второго узла в цикле, а затем имеет проблему, как я видел, выплевывая данные в командную строку. Любое понимание будет высоко ценится.
3 ответов
работает следующий код:
test.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
в этой строке:
results = (c_char_p * 4)(addressof(create_string_buffer(7)))
вы создаете один буфер из 7 байтов, затем пытаетесь использовать его для хранения 4 символьных указателей (которые, вероятно, составляют 4 байта каждый), а затем также копируете 4 8-байтовые строки в случайные адреса, на которые это может указывать. Вам нужно выделить буфер для каждой строки, а также выделить массив указателей. Что-то вроде этого:--3-->
s = []
for i in range(4):
s[i] = create_string_buffer(8)
results = (c_char_p * 4)(s);
Я не могу (легко) проверить код, но, основываясь на том, что вы сказали, я предполагаю, что проблема заключается в строке...
results = (c_char_p * 4)(addressof(create_string_buffer(7)))
согласно документам Python для create_string_buffer()
...
init_or_size
должно быть целое число, указывающее размер массива, или строку, которая будет использоваться для инициализации элементов массива.если в качестве первого аргумента указана строка, буфер становится одним элемента больше, чем длина строки так, чтобы последний элемент в массив является символом завершения NUL. Целое число может быть передано как второй аргумент, который позволяет указать размер массива, если длина строки не должна использоваться.
...что означает, что он создает char[7]
, но a strcpy()
попытается скопировать NULL
terminator для строки, поэтому, если ваша максимальная длина "имени узла" составляет семь символов, вам понадобится char[8]
провести NULL
, хотя вы могли бы получить долой использование memcpy(array[i], nodes[i], 7)
вместо strcpy()
.
в любом случае, это, вероятно, безопаснее использовать create_string_buffer(8)
вместо.