Frage

Ich versuche, eine Python-C-Erweiterung zu schreiben, die binären Daten gepackt liest (als structs von structs gespeichert ist) und dann in Python-Objekte analysiert werden. Alles funktioniert wie auf eine 32-Bit-Maschine erwartet (die binären Dateien sind immer auf 32-Bit-Architektur geschrieben), aber nicht auf einem 64-Bit-Feld. Gibt es einen „bevorzugten“ Weg, dies zu tun?


Es wäre eine Menge Code zu schreiben, sondern als Beispiel:

struct
{
    WORD    version;
    BOOL    upgrade;
    time_t  time1;
            time_t  time2;
} apparms;

File *fp;
fp = fopen(filePath, "r+b");
fread(&apparms, sizeof(apparms), 1, fp);
return Py_BuildValue("{s:i,s:l,s:l}",
  "sysVersion",apparms.version,
  "powerFailTime", apparms.time1,
  "normKitExpDate", apparms.time2
 );

Jetzt auf einem 32-Bit-System funktioniert dies gut, aber auf einen 64-Bit meiner Time_t Größen sind unterschiedlich (32bit vs 64-Bit-Long-Positionen).


Verdammt, sind Sie Menschen schnell.

Patrick, ich begann ursprünglich die Struktur-Paket verwenden, aber es einfach viel für meine Bedürfnisse zu verlangsamen gefunden. Plus I wurde nach einer Entschuldigung suchen eine Python-Erweiterung zu schreiben.

Ich weiß, dass dies eine dumme Frage, aber welche Arten muss ich achten?

Danke.

War es hilfreich?

Lösung

Explizit angeben, dass Ihre Datentypen (z ganze Zahlen) sind 32-Bit. Andernfalls, wenn Sie zwei ganzen Zahlen nebeneinander, wenn Sie sie lesen, werden sie als eine 64-Bit-Integer gelesen werden.

Wenn Sie mit plattformübergreifenden Fragen zu tun haben, die beiden wichtigsten Dinge zu achten gilt, sind:

  1. Bitness. Wenn Ihre gepackten Daten mit 32-Bit ints geschrieben wird, dann müssen alle Ihre Code explizit 32-Bit ints angeben beim Lesen und Schreiben.
  2. Byte-Reihenfolge. Wenn Sie Ihren Code von Intel-Chips zu PPC oder SPARC bewegen, wird Ihre Byte-Reihenfolge falsch sein. Sie müssen Ihre Daten importieren und dann Byte-Flip, so dass es mit der aktuellen Architektur zusammenpasst. Ansonsten 12 (0x0000000C) als 201.326.592 (0x0C000000) gelesen werden.

Wir hoffen, das hilft.

Andere Tipps

Die ‚Struktur‘ Modul sollte in der Lage sein, dies zu tun, obwohl die Ausrichtung von Strukturen in der Mitte der Daten immer ein Problem. Es ist nicht sehr schwer, es richtig zu machen, aber: herauszufinden, (einmal), was Grenze der structs-in-structs ausrichten Pad, dann (manuell, mit dem ‚x‘ spezifizierer) an diese Grenze. Sie können Ihre Polsterung durch einen Vergleich struct.calcsize () mit Ihrem aktuellen Daten Doppelprüf. Es ist sicherlich einfacher als eine C-Erweiterung für sie zu schreiben.

Um wie die Verwendung von Py_BuildValue () zu halten, haben Sie zwei Möglichkeiten. Sie können die Größe von Time_t bei compiletime bestimmen (in Bezug auf den Grundtypen, so ‚ein int‘ oder ‚lange‘ oder ‚ein ssize_t‘) und dann die richtige Format Zeichen Py_BuildValue verwenden - ‚i‘ für einen int, ‚L‘ für eine lange, ‚n‘ für eine ssize_t. Oder Sie können PyInt_FromSsize_t () verwenden, manuell, wobei in diesem Fall der Compiler tut das Upcasting für Sie, und verwenden Sie dann die ‚O‘ Format Zeichen das Ergebnis Py_BuildValue zu übergeben.

Sie müssen sicherstellen, dass Sie Architektur unabhängige Mitglieder für Ihre Struktur verwenden. Zum Beispiel kann ein 32-Bit-int auf einer Architektur und 64 Bits auf einem anderen. Wie andere vorgeschlagen haben, verwenden Sie die int32_t Stiltypen statt. Wenn Ihre Struktur nicht ausgerichtete Elemente enthält, müssen Sie möglicherweise mit Polsterung auch vom Compiler hinzugefügt behandeln.

Ein weiteres häufiges Problem mit Cross-Architektur Daten endianness. Intel i386-Architektur ist Little-Endian, aber wenn Sie auf einer ganz anderen Maschine gerade lesen (beispielsweise ein Alpha oder Sparc), werden Sie über diese kümmern.

Die Python-Struktur-Modul befasst sich mit diesen beiden Situationen, das Präfix als Teil des Format-String übergeben werden.

  • @ - Verwendung nativer Größe, endianness und Ausrichtung. i = sizeof (int), l = sizeof (long)
  • = - Verwendung nativer Endian, aber Standardgrößen und Ausrichtung (i = 32 Bits, l = 64 Bit)
  • <- Little-Endian-Standardgrößen / Ausrichtung
  •   
        
    • Big-Endian-Standardgrößen / Ausrichtung
    •   
dh -

In der Regel, wenn die Daten Ihre Maschine ausgeben, sollten Sie die Endian und die Größe / padding-Format etwas Bestimmtes zu. verwenden „<“ oder „>“ als Format. Wenn Sie dies in Ihrem C-Erweiterung behandeln möchten, müssen Sie einen Code hinzuzufügen, um damit zu umgehen.

Was ist Ihr Code der binären Daten zum Lesen? Stellen Sie sicher, dass Sie das Kopieren der Daten in der richtigen Größe Typen wie int32_t statt nur int.

Warum nicht verwenden Sie das struct Paket?

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top