unicode - utf-8

Python in C/C++ embedden, C-Module, ctypes, Cython, SWIG, SIP etc sind hier richtig.
Antworten
Benutzeravatar
lightos
User
Beiträge: 39
Registriert: Montag 12. Dezember 2011, 19:39
Wohnort: Raum Bruchsal
Kontaktdaten:

Such eine elegante Lösung für folgendes Problem:

Dll/so enthält C-Funktionen die unter Windows WCHAR und unter Linux utf-8 verwenden (Windows somit 2-Byte-Zeichen, Linux 1-Byte)

Im C-Code ist das über typedef umgeschaltet und damit ändert sich auch das API.

Wie kann man das nun elegant in Python abbilden: (ohne if-Konstruktion)

Die API-Wrapper müssen an bestimmten Stellen zwischen
ctypes.c_wchar unter Windows
ctypes.c_char unter Linux

umgesetzt werden.

Ideen?
BlackJack

@lightos: Ganz ohne Fallunterscheidung wirst Du nicht auskommen. Im Grunde musst Du wie bei C auch ein Alias erstellen das je nach System den entsprechenden Typ beinhaltet:

Code: Alles auswählen

char_type = ctypes.c_wchar if windows else ctypes.c_char
Benutzeravatar
lightos
User
Beiträge: 39
Registriert: Montag 12. Dezember 2011, 19:39
Wohnort: Raum Bruchsal
Kontaktdaten:

OK. Klasse. Das hab ich gesucht.
Benutzeravatar
lightos
User
Beiträge: 39
Registriert: Montag 12. Dezember 2011, 19:39
Wohnort: Raum Bruchsal
Kontaktdaten:

Ergänzung zur Optimierung:

Aktuell haben die so/Dlls eine Funktion, um die Size von char abfragen zu können.
In Python kann so die korrekte Umsetzung dynamisch im wrapper erfolgen.
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

@lightos:
Übrigens ist es ein Fehler, für ein UTF-8 Zeichen per se ein c_char einzuräumen. UTF-8 ist ein variables Multibyte-Encoding mit bis zu 4 Byte pro Zeichen.
Benutzeravatar
lightos
User
Beiträge: 39
Registriert: Montag 12. Dezember 2011, 19:39
Wohnort: Raum Bruchsal
Kontaktdaten:

Ja danke. Aber die Strings sind 0-Zeichen terminiert. Es gibt hier keine Annahme über 1 Zeichen pro Byte.
Benutzeravatar
lightos
User
Beiträge: 39
Registriert: Montag 12. Dezember 2011, 19:39
Wohnort: Raum Bruchsal
Kontaktdaten:

Ergänzende Frage dazu:

Unter Windows ist die API entweder ctypes.c_wchar * N oder unter Linux ctypes.c_char * N.
Das Ziel ist nun möglichst simple einen Python-String zu konvertieren.
Der Buffer der von der API zurück kommt ist Null-Terminiert.

Aktuell ist das mit einem "if" gelöst, da ich noch keine passende Python-Konversion gefunden habe. Idee?
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

@lightos
Eine Fallunterscheidung ist immer nötig, wenn man in Abhängigkeit von der Umgebung (hier: Betriebssystem) programmiert. Wenn es dir darum geht, grundsätzlich mit verschiedenen Code-Varianten zu arbeiten, dann wäre dies z.B. in dieser Art möglich:

Code: Alles auswählen

if on_windows:
    def convert_string(s):
        # Windows-specific implementation
else:
    def convert_string(s):
        # Non-Windows implementation
Für den Anwender ist dann immer nur eine Variante von `convert_string()` ersichtlich. Dies wäre ja so in etwas das, was man in C häufig mittels `#ifdef`-Abfragen bastelt. Bei sehr vielen Unterscheidungen könnte man auch zwei unterschiedliche Module erstellen und je nach Betriebssytem das passende Modul importierten.
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

@lightos:
Das hier sollte sowohl für char/wchar-Pointer als auch Arrays unter Python 2.x funktionieren:

Code: Alles auswählen

def convert_cstring(s, encoding='utf-8'):
    res = s.value
    return res.decode(encoding) if isinstance(res, str) else res
Antworten