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) вместо.