2010-08-16 4 views
17

Ich habe eine C-Funktion, die eine Liste \ 0 terminierte Strings als Eingabe erwartet:eine Liste von Strings aus Python/ctypes bis C Funktion übergeben erwartet char **

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

Von Python (mit ctypes) I möchte diese Funktion auf eine Liste von python-Strings basierend nennen:

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

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

Irgendwelche Tipps, wie Sie die Datenstruktur auf der python-Seite aufzubauen? Beachten Sie, dass ich garantiere, dass die C-Funktion den Inhalt der Strings in string_list NICHT ändert.

Grüße

joakim

+0

Wie weiß die C-Funktion, dass sie das Ende der Sequenz von 'const char *' erreicht hat? – habnabit

+0

Gut; im Allgemeinen weiß es natürlich nicht. Meine Absicht war, es mit einem NULL zu beenden, alternativ kann ich eine Länge sowie den Zeiger (char **) übergeben - ich habe die volle Kontrolle über die betreffende C-Bibliothek. Joakim –

+0

Wenn es nicht weiß, das ist ziemlich nutzlos. Du musst es irgendwie sagen und sag * uns * damit wir dir Code geben können, der funktioniert. – habnabit

Antwort

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

Vielen Dank; das hat wie Charme funktioniert. Ich habe auch eine alternative Variante wie folgt aus:

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

Und dann in C-Funktion, die ich wiederholt durch die (char **) Liste, bis ich einen NULL gefunden.

Joakim

1

ich es nur SWIG mit machen typemap

1.Write angepasst typemap in demo.i Interface-Datei.

%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.generate Verlängerungs

$ 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 das Modul in Python.

>>> from demo import yourfunction 
Verwandte Themen