Estoy tratando de utilizar ctypes para crear un char * matriz en python para pasarse a una biblioteca para rellenar con cadenas. Estoy esperando 4 cadenas de vuelta no más de 7 caracteres de longitud cada uno.

Mi py código como se muestra en este

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]);
    }
}

Sigo recibiendo la segmentación de los fallos cuando trato de ejecutar este código. He creado una prueba de C que funciona perfectamente, pero en Python me debe configurar el puntero del array de forma incorrecta o algo. Parece que para el segundo nodo en el bucle y, a continuación, tienen un problema, como yo lo he visto de escupir de datos en la línea de comandos. Cualquier visión sería muy apreciada.

InformationsquelleAutor bitwit | 2013-05-22

3 Comentarios

  1. 10

    El siguiente código funciona:

    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

    de la prueba.c (compilado a libtest.así que con 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!");
    }

    Como Aya dicho, debe asegurarse de que hay espacio para la terminación de cero. Pero creo que su principal problema era que el búfer de cadena fue el recolector de basura o algo similar, ya que no había ninguna referencia directa a ella más. O hay algo más que está causando problemas en el proceso de creación de la cadena de búferes cuando no hay referencias son almacenados para ellos. Por ejemplo, esto se traduce en cuatro veces la misma dirección, en lugar de direcciones diferentes:

    import ctypes
    pointers = [ctypes.addressof(ctypes.create_string_buffer(8)) for i in range(4)]
    print pointers
    • También puede crear una matriz 2D para el búfer: string_buffers = ((ctypes.c_char * 8) * 4)(). Lo voy a repetir lo mismo al definir pointers en la línea siguiente.
    • No tenemos que extern "C" de C? ¿
    • sólo es necesario decirle a C++ para crear C-compatible símbolos (ver C++ nombre de destrozarlo).
  2. 4

    En esta línea:

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

    Está creando un único búfer de 7 bytes, tratando de utilizar para mantener la 4 punteros a caracteres (que probablemente son de 4 bytes cada uno), y luego también la copia 4 de 8 cadenas de bytes en el azar de las direcciones que podría suceder a punto. Usted necesita asignar un búfer para cada cadena, y también asignar la matriz de punteros. Algo como esto:

    s = []
    for i in range(4):
        s[i] = create_string_buffer(8)
    results = (c_char_p * 4)(s);
  3. 2

    Yo no puedo (fácilmente) probar el código, pero basado en lo que he dicho, mi conjetura sería que el problema se encuentra en la línea de…

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

    De acuerdo con el Python docs para create_string_buffer()

    init_or_size debe ser un entero que especifica el tamaño de la matriz,
    o una cadena que se utiliza para inicializar los elementos de matriz.

    Si se especifica una cadena como primer argumento, el búfer se hace uno
    el elemento más grande que la longitud de la cadena, de modo que el último elemento en
    la matriz es un NUL carácter de terminación. Un número entero puede ser pasado como
    el segundo argumento que permite especificar el tamaño de la matriz si el
    la longitud de la cadena no debe ser utilizado.

    …lo que implica que la creación de un char[7], pero un strcpy() intentará copiar el NULL el terminador de una cadena, por lo que si el máximo de su «nombre de nodo» longitud es de siete caracteres, usted necesitará un char[8] para mantener la NULL, aunque usted puede conseguir lejos con usar memcpy(array[i], nodes[i], 7) en lugar de strcpy().

    De cualquier manera, es probablemente más seguro usar create_string_buffer(8) lugar.

Dejar respuesta

Please enter your comment!
Please enter your name here