Konvertieren eines Python-String-Objekts in c char* mit ctypes
Lesezeit: 3 Minuten
Kleiner
Ich versuche, 2 Zeichenfolgen von Python (3.2) mit ctypes an C zu senden. Dies ist ein kleiner Teil meines Projekts auf meinem Raspberry Pi. Um zu testen, ob die C-Funktion die Strings korrekt empfangen hat, lege ich einen davon in eine Textdatei.
Python-Code
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))
C-Code
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..
}
Das Problem
Nur der erste Buchstabe der Zeichenfolge erscheint in der Textdatei.
Ich habe viele Möglichkeiten ausprobiert, um das Python-String-Objekt mit ctypes zu konvertieren.
ctypes.c_char_p
ctypes.c_wchar_p
ctypes.create_string_buffer
Bei diesen Konvertierungen bekomme ich immer wieder den Fehler “falscher Typ” oder “Bytes oder Integer-Adresse statt Str-Instanz erwartet”.
Ich hoffe jemand kann mir sagen wo es schief geht. Danke im Voraus.
Satz my_c_function.argtypes = [ctypes.c_char_p, ctypes.c_char_p]. Dann, weil die Parameter sind constnennen Sie es einfach als my_c_function(b_string1, b_string2).
– Eryk Sonne
25. November 2014 um 14:38 Uhr
FYI, ein wörtliches Backslash-Zeichen muss mit Escapezeichen versehen werden "\\", ist aber für einen Schrägstrich nicht erforderlich. Es ist nur "/home/pi/Desktop/out.txt".
– Eryk Sonne
25. November 2014 um 14:42 Uhr
@eryksun Danke für deine Antwort. Es funktioniert jetzt, ich habe total vergessen, dass ich argtypes noch auf c_wchar_p gesetzt hatte. Was die Schrägstriche angeht, verwechsle ich sie immer.
– Kleiner
25. November 2014 um 15:03 Uhr
Benutz nur buf = ctypes.create_string_buffer(bstr) wenn die Funktion die Zeichenfolge ändert. Es ist gleichbedeutend mit buf = (ctypes.c_char * (len(bstr) + 1))();buf.value = bstr.
– Eryk Sonne
25. November 2014 um 15:12 Uhr
Kleiner
Dank Eryksun die Lösung:
Python-Code
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)
my_c_function.argtypes = [ctypes.c_char_p, ctypes_char_p] Was meinen Sie my_c_function.argtypes = [ctypes.c_char_p, ctypes.char_p] (Notiz . Anstatt von _)?
– Hallo
18. November 2019 um 3:54 Uhr
Haha, nach 5 Jahren ist es jemandem aufgefallen oder hat sich die Mühe gemacht, darauf hinzuweisen. Danke dafür, ich habe es in der Antwort bearbeitet.
Ich denke, Sie müssen nur c_char_p() anstelle von create_string_buffer() verwenden.
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))
Wenn Sie veränderliche Zeichenfolgen benötigen, verwenden Sie create_string_buffer() und wandeln Sie diese mit ctypes.cast() in c_char_p um.
Haben Sie darüber nachgedacht, zu verwenden SCHLUCK? Ich habe es nicht selbst ausprobiert, aber so würde es aussehen, ohne Ihre C-Quelle zu ändern:
Dies würde Ihre Python-Quelle so einfach machen wie (Kompilierung überspringen):
import mymodule
string1 = "my string 1"
string2 = "my string 2"
my_c_function(string1, string2)
Hinweis Ich bin mir nicht sicher .encode('utf-8') ist erforderlich, wenn Ihre Quelldatei bereits UTF-8 ist.
Denken Sie für Python 3 daran, swig’s zu verwenden -py3 Möglichkeit. Der Wrapper codiert eine Python 3-Zeichenfolge als UTF-8, indem er verwendet PyUnicode_AsUTF8String und dann PyBytes_AsStringAndSize. Vorbeigehen bytes erhebt a TypeError.
– Eryk Sonne
25. November 2014 um 18:21 Uhr
13855800cookie-checkKonvertieren eines Python-String-Objekts in c char* mit ctypesyes
Satz
my_c_function.argtypes = [ctypes.c_char_p, ctypes.c_char_p]
. Dann, weil die Parameter sindconst
nennen Sie es einfach alsmy_c_function(b_string1, b_string2)
.– Eryk Sonne
25. November 2014 um 14:38 Uhr
FYI, ein wörtliches Backslash-Zeichen muss mit Escapezeichen versehen werden
"\\"
, ist aber für einen Schrägstrich nicht erforderlich. Es ist nur"/home/pi/Desktop/out.txt"
.– Eryk Sonne
25. November 2014 um 14:42 Uhr
@eryksun Danke für deine Antwort. Es funktioniert jetzt, ich habe total vergessen, dass ich argtypes noch auf c_wchar_p gesetzt hatte. Was die Schrägstriche angeht, verwechsle ich sie immer.
– Kleiner
25. November 2014 um 15:03 Uhr
Benutz nur
buf = ctypes.create_string_buffer(bstr)
wenn die Funktion die Zeichenfolge ändert. Es ist gleichbedeutend mitbuf = (ctypes.c_char * (len(bstr) + 1))();
buf.value = bstr
.– Eryk Sonne
25. November 2014 um 15:12 Uhr