c_int python c ctypes

python - c_int()



Pasando una lista de cadenas desde python/ctypes a la funciĆ³n C que espera char** (4)

Utilizando ctypes

crear lista de caducidad (cadenas)

expiries = ["1M", "2M", "3M", "6M","9M", "1Y", "2Y", "3Y","4Y", "5Y", "6Y", "7Y","8Y", "9Y", "10Y", "11Y","12Y", "15Y", "20Y", "25Y", "30Y"]

Lógica para enviar matriz de cadenas.

convertir la matriz de cadenas en matriz de bytes haciendo un bucle en la matriz

expiries_bytes = [] for i in range(len(expiries)): expiries_bytes.append(bytes(expiries[i], ''utf-8''))

Tipos de lógica para iniciar un puntero con una longitud de matriz

expiries_array = (ctypes.c_char_p * (len(expiries_bytes)+1))()

asignando la matriz de bytes en el puntero

expiries_array[:-1] = expiries_bytes

Tengo una función C que espera una lista / 0 cadenas terminadas como entrada:

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

Desde python (con ctypes) me gustaría llamar a esta función basada en 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 de Python? Observe que garantizo que la función C NO alterará el contenido de las cadenas en string_list.

Saludos

Joakim


Muchas gracias; Eso funcionó a la perfección. También hice una variación alternativa como esta:

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 la función C iteré a través de la lista (char **) hasta que encontré un NULL.


Solo lo hago usando el mapa de tipos SWIG

1.write mapa de tipo personalizado en el archivo de interfaz demo.i

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

2.generar extensión

$ 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.Importe el módulo en python.

>>> from demo import yourfunction


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