2014-11-25 19 views
10

Sto cercando di inviare 2 stringhe da Python (3.2) a C usando i tipi. Questa è una piccola parte del mio progetto sul mio Raspberry Pi. Per verificare se la funzione C ha ricevuto correttamente le stringhe, ne inserisco una in un file di testo.Conversione di oggetto stringa python in c char * utilizzando i tipi di carattere

codice Python

string1 = "my string 1" 
string2 = "my string 2" 

# create byte objects from the strings 
b_string1 = string1.encode('utf-8') 
b_string2 = string2.encode('utf-8') 

# send strings to c function 
my_c_function(ctypes.create_string_buffer(b_string1), 
       ctypes.create_string_buffer(b_string2)) 

codice C

void my_c_function(const char* str1, const char* str2) 
{ 
    // Test if string is correct 
    FILE *fp = fopen("//home//pi//Desktop//out.txt", "w"); 
    if (fp != NULL) 
    { 
     fputs(str1, fp); 
     fclose(fp); 
    } 

    // Do something with strings.. 
} 

Il problema

solo la prima lettera della stringa compare nel file di testo.

Ho provato molti modi per convertire l'oggetto stringa Python con ctypes.

  • ctypes.c_char_p
  • ctypes.c_wchar_p
  • ctypes.create_string_buffer

Con queste conversioni continuo a ricevere l'errore "tipo sbagliato" o "byte o indirizzo intero attesi invece di esempio str ".

Spero che qualcuno possa dirmi dove va male. Grazie in anticipo.

+6

Imposta 'my_c_function.argtypes = [ctypes.c_char_p, ctypes.c_char_p]'. Quindi, poiché i parametri sono 'const', chiamalo semplicemente come' my_c_function (b_string1, b_string2) '. – eryksun

+2

FYI, un carattere letterale backslash deve essere salvato come '" \\ "', ma non è richiesto per una barra diretta. È solo "" /home/pi/Desktop/out.txt "'. – eryksun

+1

@eryksun Grazie per la risposta. Funziona ora, ho completamente dimenticato che avevo ancora argtypes su c_wchar_p. Riguardo ai tagli, li faccio sempre confondere. – LittleOne

risposta

10

Grazie alla Eryksun la soluzione:

codice Python

string1 = "my string 1" 
string2 = "my string 2" 

# create byte objects from the strings 
b_string1 = string1.encode('utf-8') 
b_string2 = string2.encode('utf-8') 

# send strings to c function 
my_c_function.argtypes = [ctypes.c_char_p, ctypes_char_p] 
my_c_function(b_string1, b_string2) 
1

Hai pensato di usare SWIG? Non ho provato io stesso, ma ecco quello che sarebbe simile, senza cambiare la sorgente C:

/*mymodule.i*/ 

%module mymodule 
extern void my_c_function(const char* str1, const char* str2); 

Ciò renderebbe la sorgente Python semplice come (compilation saltare):

import mymodule 

string1 = "my string 1" 
string2 = "my string 2" 
my_c_function(string1, string2) 

Nota Non sono sicuro che .encode('utf-8') sia necessario se il tuo file sorgente è già UTF-8.

+2

Per Python 3 ricordati di usare l'opzione '-py3' di swig. Il wrapper codifica una stringa Python 3 come UTF-8, usando ['PyUnicode_AsUTF8String'] (https://docs.python.org/3/c-api/unicode.html#c.PyUnicode_AsUTF8String) e poi [' PyBytes_AsStringAndSize'] (https://docs.python.org/3/c-api/bytes.html#c.PyBytes_AsStringAndSize). Il passaggio di 'bytes' genera un' TypeError'. – eryksun

4

Penso che sia necessario utilizzare c_char_p() invece di create_string_buffer().

string1 = "my string 1" 
string2 = "my string 2" 

# create byte objects from the strings 
b_string1 = string1.encode('utf-8') 
b_string2 = string2.encode('utf-8') 

# send strings to c function 
my_c_function(ctypes.c_char_p(b_string1), 
       ctypes.c_char_p(b_string2)) 

Se avete bisogno di stringhe mutevoli quindi utilizzare create_string_buffer() e lanciare quelle c_char_p utilizzando ctypes.cast().