2010-08-16 9 views
17

tengo una función C, que espera una lista de \ 0 Series terminadas como entrada:pasar una lista de cadenas a partir de pitón/ctypes a la función C esperando char **

void external_C(int length , const char ** string_list) { 
    // Inspect the content of string_list - but not modify it. 
} 

De pitón (con ctypes) I le gustaría llamar a esta función en base a una lista de cadenas de Python:

def call_c(string_list): 
    lib.external_C(??) 

call_c(["String1" , "String2" , "The last string"]) 

Algún consejo sobre cómo construir la estructura de datos en el lado pitón? Observe que garantizo que la función C NO alterará el contenido de las cadenas en string_list.

Saludos

Joakim

+0

¿Cómo sabe la función C que ha llegado al final de la secuencia de 'const char *'? – habnabit

+0

Bueno; en general, no sabe, por supuesto. Mi intención era terminarlo con un NULL, alternativamente puedo pasar una longitud igual que el puntero (char **) - tengo control total sobre la biblioteca C en cuestión. Joakim –

+0

Si no lo sabe, es bastante inútil. Necesitas contarlo de alguna manera y decirnos * para que podamos darte un código que funcione. – habnabit

Respuesta

20
def call_c(L): 
    arr = (ctypes.c_char_p * len(L))() 
    arr[:] = L 
    lib.external_C(len(L), arr) 
5

Muchas gracias; eso funcionó como el encanto. También hice una variante alternativa de esta manera:

def call_c(L): 
    arr = (ctypes.c_char_p * (len(L) + 1)))() 
    arr[:-1] = L 
    arr[ len(L) ] = None 
    lib.external_C(arr) 

Y luego, en función de C-I iterado a través de la lista (char **) hasta que encontré un NULL.

Joakim

1

que sólo lo hacen utilizando el TRAGO typemap

1.Escribir typemap personalizada en demo.i archivo de interfaz.

%module demo 

/* tell SWIG to treat char ** as a list of strings */ 
%typemap(in) char ** { 
    // check if is a list 
    if(PyList_Check($input)) 
    { 
     int size = PyList_Size($input); 
     int i = 0; 
     $1 = (char **)malloc((size + 1)*sizeof(char *)); 
     for(i = 0; i < size; i++) 
     { 
      PyObject * o = PyList_GetItem($input, i); 
      if(PyString_Check(o)) 
       $1[i] = PyString_AsString(o); 
      else 
      { 
       PyErr_SetString(PyExc_TypeError, "list must contain strings"); 
       free($1); 
       return NULL; 
      } 
     } 
    } 
    else 
    { 
     PyErr_SetString(PyExc_TypeError, "not a list"); 
     return NULL; 
    } 
} 

// clean up the char ** array 
%typemap(freearg) char ** { 
    free((char *) $1); 
} 

extensión 2.generate

$ swig -python demo.i // generate wrap code 
$ gcc -c -fpic demo.c demo_wrap.c 
$ gcc -shared demo.o demo_wrap.o -o _demo.so 

3.Import el módulo en Python.

>>> from demo import yourfunction 
Cuestiones relacionadas