2016-04-15 21 views
2

Ich arbeite mit der seriellen Kommunikation, und ich 32bit Ganzzahlen in einem QByteArray, in 4 separaten Bytes (Little-Endian) gepackt. Ich versuche, den Wert aus dem 4 Bytes zu entpacken QByteArray::toLong() verwenden, aber es scheitert die Konvertierung und gibt die falsche Nummer:Wie Entpacken 32-Bit-Integer in einem QByteArray verpackt?

quint8 packed_bytes[] { 0x12, 0x34, 0x56, 0x78 }; 
QByteArray packed_array { QByteArray(reinterpret_cast<char*>(packed_bytes), 
            sizeof(packed_bytes)) }; 
bool isConversionOK; 
qint64 unpacked_value { packed_array.toLong(&isConversionOK) }; 
// At this point: 
// unpacked_value == 0 
// isConversionOK == false 

Das erwartete unpacked_value ist 0x78563412 (Little-Endian auspacken). Warum schlägt die Konvertierung fehl?

Antwort

3

Sie eine QDataStream Binärdaten lesen verwenden können.

quint8 packed_bytes[] { 0x12, 0x34, 0x56, 0x78 }; 
QByteArray packed_array { QByteArray(reinterpret_cast<char*>(packed_bytes), sizeof(packed_bytes)) }; 
QDataStream stream(packed_array); 
stream.setByteOrder(QDataStream::LittleEndian); 
int result; 
stream >> result; 
qDebug() << QString::number(result,16); 
3

toLong() konvertiert ein char * Ziffern string zu lang. Keine Bytes. Und Ihre Werte bilden wahrscheinlich nicht die Zeichenfolge "0x78563412" oder deren dezimales Äquivalent. Daher das Ergebnis 0.

Wenn Sie die Byte-Werte interpretiert, so lange brauchen, können Sie so etwas wie:

long value; 
value == *((long*)packed_bytes.data()); 

oder ein Array von Bytes, wie lange Array zuzugreifen:

long * values; 
values == (long*)packed_bytes.data(); 

values[0]; // contains first long 
values[1]; // contains second long 
... 

Ich weiß nicht, ob meine Beispiele funktionieren out of the box, aber es sollte das Prinzip klarstellen.

Schauen Sie sich dieses Beispiel:

char bytes[] = {255, 0}; 

QByteArray b(bytes, 2); 

QByteArray c("255"); 

qDebug() << b.toShort() << c.toShort(); 

qDebug() << *((short*)b.data()) << *((short*)c.data()); 

der Ausgang ist:

0 255 
255 13618 

Sie müssen die Byte-Reihenfolge auf dem Endianess abhängig ändern. Aber es tut was du brauchst.

+0

Vielen Dank für Ihre Antwort, aber Sie sehen in meinem Beitrag, dass ich mein Array in 'char *' umwandle, das die Ganzzahlen in eine Zeichenfolge umwandelt, wie Sie es beschreiben. Fehle ich etwas? Und warum schlägt die Konvertierung fehl (wie von der "Bool" angezeigt), anstatt nur ein falsches Ergebnis zurückzugeben? – DBedrenko

+0

Können Sie diese Zeichenfolge richtig drucken und sehen Sie den richtigen Wert geschrieben? Dann sollte es funktionieren. Aber wenn die Byte-Werte den Wert repräsentieren, und nicht ihre Ascii-Darstellungen, brauchen Sie etwas wie meinen Ansatz. – Aaron

+0

QByteArray :: toLong() interpretiert Ihre Bytes als eine mit \ 0 abgeschlossene Zeichenfolge. – Aaron

1

Sie können Ihre qint64 mit Bit Manipulatoren bauen:

#include <QtGlobal> 
#include <QByteArray> 
#include <QDebug> 

int main() 
{ 
    quint8 packed_bytes[] { 0x12, 0x34, 0x56, 0x78 }; 
    QByteArray packed_array { QByteArray(reinterpret_cast<char*>(packed_bytes), 
             sizeof(packed_bytes)) }; 

    qint64 unpacked_value = 0; 

    unpacked_value |= packed_array.at(0)  | 
         packed_array.at(1) << 8 | 
         packed_array.at(2) << 16 | 
         packed_array.at(3) << 24; 

    qDebug() << QString("0x%1").arg(unpacked_value, 0, 16); 
} 
+0

Danke für die Lösung, aber es ist eher niedrige Ebene, funktioniert nur um vorzeichenlose Zahlen zu produzieren, und ich bin mir nicht sicher, ob ich es verwenden kann, um z. 2-Byte- oder 3-Byte-Werte. Ein Framework, so groß wie Qt, hat bereits Funktionen, die Low-Level-Bitshifting abstrahieren? Außerdem müsste ich dafür Testfälle schreiben, also wäre es definitiv besser, etwas bereits in Qt zu verwenden. – DBedrenko