Endianess of QByteArray ?



  • How can i get the float Pi value of both castings below, by only modifying
    the line 13 @ result_big = reinterpret_cast<const float>(ba_bigPi.data()); @

    Not the QByteArray creation above !
    I assume that qFromBigEndian , qFromLittleEndian might do this job but i do
    not know how to apply.

    2nd Question:
    Do i need the static const char array to get the data correctly into the QByteArray ?

    @ float result_big, result_lit;

        static const char bigEn_Pi[] = {0x40, 0x49, 0x0F, 0xDB};
        static const char litEn_Pi[] = {0xDB, 0x0F, 0x49, 0x40};
    
        QByteArray ba_bigPi = QByteArray::fromRawData(bigEn_Pi, sizeof(bigEn_Pi));
        QByteArray ba_litPi = QByteArray::fromRawData(litEn_Pi, sizeof(litEn_Pi));
    
        qDebug() << (sizeof(result_big) == ba_bigPi.size());    // true
        qDebug() << ba_bigPi.toHex().toUpper();             // "40490FDB"
        qDebug() << ba_litPi.toHex().toUpper();             // "DB0F4940"
    
        result_big = *reinterpret_cast<const float*>(ba_bigPi.data());
    
        //    qFromBigEndian
        //    qFromLittleEndian
    
        result_lit = *reinterpret_cast<const float*>(ba_litPi.data());
    
        qDebug() << result_big;
        qDebug() << result_lit;
    
        qDebug() << QSysInfo::BigEndian;
        qDebug() << QSysInfo::LittleEndian;
    

    // output:
    // true
    // "40490FDB"
    // "DB0F4940"
    // -4.03315e+16
    // 3.14159
    // 0
    // 1@

    thank you :)



  • Hi,
    I'm not really sure what you want to do with the Endian stuff, but IYAM don't mess around with it unless you really need to. Qt and almost all other programming languages and most small ucontrollers use little endian, so stick to that.
    The conversion of a float to a bytearray is:
    QByteArray QByteArray::number(double n, char f = 'g', int prec = 6) [static]
    and
    toDouble() if you want to reconstruct the float.



  • Jeroen,

    i get little- and big- endian Bytestreams from a unusual device and need to
    process the data. Only floats coming in as data (no doubles) , rest is setting and protocol stuff i can manage already. For this reason i want to use a function like
    @float MainWindow::QBA2Float(QByteArray _ba, bool _bigEnd) {@
    If _bigEnd is false it should interprete the incoming QByteArray as liitleEndian. I might copy this QByteArray inside the function to an temporary QByteArray with reverse endianess.
    On the other hand I'm also curious how the suggested solution is implemented correctly* (qFromBigEndian , qFromLittleEndian)*



  • Hi,
    Using floats or doubles to be transported across devices is highly discouraged. A float may be constructed in different formats across different cpu's. Using a QByteArray should do the trick, simply switch the last with first byte ;-), but then the float construction might get lost and very strange values are 'decoded'.
    The QtEndian class clearly states that only integral values may be used! So, do so ;-)
    If you need some sort of float values to be transported, simply multiply the start value by 1000 or more and send data, then read in and divide again at the receiving end.
    Again, sending floats is NOT possible in a guaranteed way.


  • Moderators



  • Hi,
    Try to use QDataStream it works for me
    @
    float result_big, result_lit;
    static const char bigEn_Pi[] = {0x40, 0x49, 0x0F, 0xDB};
    static const char litEn_Pi[] = {0xDB, 0x0F, 0x49, 0x40};
    QByteArray ba_bigPi = QByteArray::fromRawData(bigEn_Pi, sizeof(bigEn_Pi));
    QByteArray ba_litPi = QByteArray::fromRawData(litEn_Pi, sizeof(litEn_Pi));
    QDataStream str(&ba_bigPi,QIODevice::ReadOnly);
    str.setFloatingPointPrecision(QDataStream::SinglePrecision);
    str.setByteOrder(QDataStream::BigEndian);
    QDataStream str2(&ba_litPi,QIODevice::ReadOnly);
    str2.setFloatingPointPrecision(QDataStream::SinglePrecision);
    str2.setByteOrder(QDataStream::LittleEndian);
    str >> result_big;
    str2 >> result_lit;
    qDebug()<<result_big;
    qDebug()<<result_lit;@
    Of course you must remember about floatingpointprecision to set it properly. Better way to send data with different endiness is to multiply and divide float to int and send it as int. Just as Jeroentje@home wrote.



  • Thank you diabolic !

    Here are some results i found and works for me.
    Maybe its of general interest, so i post here.
    I set some more comments as usual for better understanding.
    Any suggestions and remarks welcome.

    especially line 28 seems to work :

    @void MainWindow::on_pb_swap1_clicked()
    {

    // pi-big: "40490FDB"
    // on lit system:
    // dec int = 1 078 530 011
    // bin = 0b 01000000010010010000111111011011
    // float = -4.0331460896358400E16

    // Pi-lit: "DB0F4940" (Hexadecimal is little-endian (right-to-left)
    // on lit-system:
    // dec int = 3 675 212 096
    // bin = 0b 11011011000011110100100101000000 (negative as signed int)
    // float = 3.1415927410125732421875

    float result;
    quint32 tni_ip;
    
    QString str = "40490FDB";
    bool ok;
    quint32 pi_int = str.toUInt(&ok,16);
    
    result = *reinterpret_cast<float*>(&pi_int); // cast to little endian
    qDebug() << "1: " << result;    //  3.14159
    
    str = "DB0F4940";
    pi_int = str.toUInt(&ok,16);
    qToBigEndian<quint32>(quint32(pi_int),
    reinterpret_cast<unsigned char*>(&tni_ip));
    
    result = *reinterpret_cast<float*>(&tni_ip);
    qDebug() << "2: " << result;    // -4.03315e+16
    

    }

    void MainWindow::on_pb_swap2_clicked()
    {

    QByteArray ba = QByteArray::fromHex("FF0F40490FDBFF1FDB0F4940FFFF");
    
    float f;
    quint32 tmp_i;
    QByteArray ba_part = ba.mid(2, 4);
    
    QDataStream s1(ba_part); s1 >> tmp_i;
    f = *reinterpret_cast<float*>(&tmp_i);
    qDebug() << "1: " << f;
    
    ba_part = ba.mid(8, 4);
    QDataStream s2(ba_part);
    s2.setByteOrder(QDataStream::LittleEndian);
    s2 >> tmp_i;
    f = *reinterpret_cast<float*>(&tmp_i);
    qDebug() << "2: " << f ;
    

    }@

    output for both functions:
    @1: 3.14159
    2: 3.14159 @

    Is something similar like the following possible ?

    QDataStream >> float >> quint16 >> quint16 >> float



  • answering last question myself :)

    @void MainWindow::on_pb_split1_clicked()
    {

    QByteArray ba = QByteArray::fromHex("FF0F40490FDBFF1FDB0F4940FFFF");
    
    quint16 sh1, sh2, sh3;
    quint32 int1, int2;
    float f1,f2;
    
    QDataStream str_1(ba);
    str_1 >> sh1 >> int1 >> sh2 >> int2 >> sh3;
    qDebug() << sh1 << int1 << sh2 << int2 << sh3;
    
    QDataStream str_2(ba);
    str_2.setFloatingPointPrecision(QDataStream::SinglePrecision);
    str_2  >> sh1 >> f1 >> sh2 >> f2 >> sh3;
    qDebug()  << sh1 << f1 << sh2 << f2 << sh3;
    

    // output: "65295 1078530011 65311 3675212096 65535"
    // ( FF0F 40490FDB FF1F DB0F4940 FFFF )

    // output: 65295 3.14159 65311 -4.03315e+16 65535

    }@



  • to Moderator/ Admin:
    Please let me know if my kind of using the forum is unwanted

    Now trying to stream the data into a structure:
    I assume i need an "friend operator>> overloading" but i do not know how to.

    in mainwindow.h, public:
    @#pragma pack(1)
    typedef struct {
    quint8 sta; // 'CC'
    quint16 len; // size = 29
    quint8 cmd; // command type
    quint16 pref1; // prefix 1
    float temp; // temperature (pi IEEE754 bigEndian)
    quint16 pref2; // prefix 2
    float press; // pressure (pi IEEE754 littleEndian
    quint16 h_res; // 2 zero bytes reserve
    char h_dat[255]; // 0 to 255 bytes , "Hello World" here 11
    } packet;
    #pragma pack()@

    mainwindow.cpp:
    @void MainWindow::on_pb_split3_clicked()
    {

    // CC 1D00 05 FF0F 40490FDB FF1F DB0F4940 0000 48656C6C6F20576F726C64
    // 29* 5 bE Pi lE Pi 0 Hello World (11) *lE !!

    QByteArray ba = QByteArray::fromHex("CC1D0005FF0F40490FDBFF1FDB0F4940000048656C6C6F20576F726C64");
    QDataStream stream(&ba, QIODevice::WriteOnly);
    
    packet *serPac = new packet();
    
    qDebug() << sizeof(*serPac) ;  // 273-255 = 29-11 = 18
    
    ...
    stream ---&gt;>  serPac ???            
    ...
    
    qDebug() << serPac->sta;
    qDebug() << serPac->temp;
    

    }@



  • One step further
    Remains problems with the trailing data (payload)
    I need some help for line 11, 24 and 39. Thank you.

    in mainwindow.h, public:
    @#pragma pack(1)
    struct Packet {
    quint8 sta; // 'CC'
    quint16 len; // size = 29
    quint8 cmd; // command type
    quint16 pref1; // prefix 1
    float temp; // temperature (pi IEEE754 bigEndian)
    quint16 pref2; // prefix 2
    float press; // pressure (pi IEEE754 littleEndian
    quint16 res; // 2 zero bytes reserve
    QByteArray dat; // "Hello World" here 11

        friend QDataStream &operator<<(QDataStream &out, const Packet &_packet)
        {
            out.setFloatingPointPrecision(QDataStream::SinglePrecision);
            out << _packet.sta;
            out << _packet.len;
            out << _packet.cmd;
            out << _packet.pref1;
            out << _packet.temp;
            out << _packet.pref2;
            out << _packet.press;
            out << _packet.res;
            out << _packet.dat;
            return out;
        }
    
        friend QDataStream &operator>>(QDataStream &in, Packet &_packet)
        {
            in.setFloatingPointPrecision(QDataStream::SinglePrecision);
            in >> _packet.sta;
            in >> _packet.len;
            in >> _packet.cmd;
            in >> _packet.pref1;
            in >> _packet.temp;
            in >> _packet.pref2;
            in >> _packet.press;
            in >> _packet.res;
            in >> _packet.dat;
            return in;
        }
    };
    

    #pragma pack()@

    mainwindow.cpp:
    @void MainWindow::on_pb_split3_clicked()
    {

    // CC 1D00 05 FF0F 40490FDB FF1F DB0F4940 0000 48656C6C6F20576F726C64
    // 204 29* 5 bE Pi lE Pi 0 Hello World (11) *lE !!
    // 29 Bytes

    QByteArray ba = QByteArray::fromHex("CC1D0005FF0F40490FDBFF1FDB0F4940000048656C6C6F20576F726C64");
    
    QDataStream stream(&ba, QIODevice::ReadWrite);
    
    struct Packet serPac;           // = new Packet();
    qDebug() << sizeof(serPac) ;    // output 22 ?
    
    stream >> serPac;
    
    qDebug() << serPac.sta;     // CC = 204
    qDebug() << serPac.len;     // 1D00 (001D) = 7424 (29)
    qDebug() << serPac.cmd;     // 05 = 5
    qDebug() << serPac.pref1;   // FF0F = 65295
    qDebug() << serPac.temp;    // 40490FDB = 3.14159 ieee754, 32
    qDebug() << serPac.pref2;   // FF1F = 65311
    qDebug() << serPac.press;   // DB0F4940 = -4.03315e+16
    qDebug() << serPac.res;     // 00 00 = 0
    qDebug() << serPac.dat;     // ???
    

    }
    @
    output:
    22
    204
    7424
    5
    65295
    3.14159
    65311
    -4.03315e+16
    0
    ""



  • OK
    as for line 39 in above mainwindow.h this solution seems to work:

    substitute @in >> _packet.dat;@ by
    @// in >> _packet.dat;
    quint8 iByte;
    while (!in.atEnd()) {
    in >> iByte;
    _packet.dat.append(iByte);
    }@

    is this serious work or rubbish ?


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.