2014-11-25 17 views
10

Próbuję wysłać 2 ciągi znaków z Pythona (3.2) do C za pomocą ctypes. To niewielka część mojego projektu na moim Raspberry Pi. Aby sprawdzić, czy funkcja C poprawnie odebrała łańcuchy, umieszczam jeden z nich w pliku tekstowym.Konwertowanie obiektu napisowego Pythona na c char * przy użyciu ctypów

kod 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)) 

kod 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.. 
} 

Problem

tylko pojawi się pierwsza litera napisu w pliku tekstowym.

Próbowałem na wiele sposobów, aby przekonwertować obiekt łańcuchowy Python na ctypes.

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

Z tymi konwersjami ciśgle błąd "niewłaściwy typ" lub „bajtów lub adres całkowitą oczekiwane zamiast str instancji ".

Mam nadzieję, że ktoś może mi powiedzieć, gdzie jest źle. Z góry dzięki.

+6

Zestaw 'my_c_function.argtypes = [ctypes.c_char_p, ctypes.c_char_p]'. Następnie, ponieważ parametry są "const", po prostu wywołaj je jako 'my_c_function (b_string1, b_string2)'. – eryksun

+2

FYI, literalna ukośnik odwrotny musi zostać zmieniony jako '\\" ', ale nie jest wymagany dla ukośnika. To po prostu '" /home/pi/Desktop/out.txt "'. – eryksun

+1

@eryksun Dziękujemy za odpowiedź. Działa to teraz, zupełnie zapomniałem, że wciąż mam ustawione atrybuty c_wchar_p. O odcinkach, zawsze je pomieszam. – LittleOne

Odpowiedz

10

Dzięki Eryksun rozwiązanie:

kodu Pythona

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

Czy bierzesz za pomocą SWIG? Nie próbowałem go samodzielnie, ale tutaj jest to, co to będzie wyglądać, bez zmiany źródła C:

/*mymodule.i*/ 

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

byłoby to uczynić źródło Python tak proste jak (kompilacji skakanie):

import mymodule 

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

Note Nie jestem pewien, czy .encode('utf-8') jest konieczne, jeśli twój plik źródłowy jest już UTF-8.

+2

Dla Pythona 3 pamiętaj o użyciu opcji -pypy 'swig. Opakowanie koduje ciąg znaków Python 3 jako UTF-8, używając ['PyUnicode_AsUTF8String'] (https://docs.python.org/3/c-api/unicode.html#c.PyUnicode_AsUTF8String), a następnie [' PyBytes_AsStringAndSize'] (https://docs.python.org/3/c-api/bytes.html#c.PyBytes_AsStringAndSize). Przekazanie 'bytes' podnosi' TypeError'. – eryksun

4

Myślę, że wystarczy użyć c_char_p() zamiast 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)) 

Jeśli potrzebujesz zmienne ciągi następnie użyć create_string_buffer() i rzucić te do c_char_p użyciu ctypes.cast().

Powiązane problemy