QQueue to QByteArray? C# to C++



  • In C# I had;
    @
    foreach(byte _b in _fileData){
    _buffer.Enqueue(_b);
    }
    byte[] _packet = _buffer.ToArray();@

    C++;
    @foreach(char _b, _fileData){
    _buffer.enqueue(_b);
    }
    QByteArray _packet = _buffer;@

    _buffer is QQueue.
    What would _buffer.toArray be in C++?





  • Oh, im so sorry. I shouldve known what "QBuffer" was and that I was supposed to look for it. My mistake.



  • The Qt API docs are quite good - they top most of the other docs I've come over. Just in case you do not know yet: Every Qt installation comes with a good documentation browser called "Qt Assistant", it has good search functions, etc. I find it more convenient to use than the online docs.



  • Except that page doesnt mention QQueue at all, so for someone who is trying to learn, that QBuffer page is completely useless. All it is for me is more information thats irrelevant to what im trying to do, because I dont see how QBuffer helps me QByteArray = QQueue.toArray()



  • Why should QBuffer mention QQueue or vice versa? They are unrelated in any means!

    Learn reading docs and understanding inheritance!

    QQueue inherits from QList. Both do not have a toArray() method, and this is a good thing™.

    And, please, think about the problem, before requesting useless method additions. I can imagine multiple variants of even converting a list of ints into a byte array already - which one do you think is the right? And as QQueue and QList work on arbitrary types, how should these container classes ever know how to convert your fancy class?



  • Did you find anything in the documentation? I assume you checked QQueue?



  • [quote author="Volker" date="1302350394"]Why should QBuffer mention QQueue or vice versa? They are unrelated in any means!

    Learn reading docs and understanding inheritance!

    QQueue inherits from QList. Both do not have a toArray() method, and this is a good thing™.

    And, please, think about the problem, before requesting useless method additions. I can imagine multiple variants of even converting a list of ints into a byte array already - which one do you think is the right? And as QQueue and QList work on arbitrary types, how should these container classes ever know how to convert your fancy class?[/quote]

    All I am doing is trying to port over my C# code to C++ line by line, I dont know C++, im trying to learn C++. You mentioned QBuffer in the first place, not me.

    That is why im here, im trying to ask what the C++ equivelant of the C# code would be.

    [quote author="Alexandra" date="1302350792"]Did you find anything in the documentation? I assume you checked QQueue?[/quote]

    If http://doc.qt.nokia.com/latest/qqueue.html, then yes.

    What im trying to do is TCP send the contents of QQueue _buffer, QTcpSocket.write takes QByteArray.



  • Hi,
    perhaps you should think of the class you want to use. QQueue is a QLIst and QList is a linked list.
    But it seams you want to use arrays, so QVector, QBuffer or QByteArray would fit better.

    My first question would be:

    Why do you use a Queue? Only because you uise it in C#?

    If you need a QByteArray for the interfaces / classes you are using, then fill the data into a QByteArray in the for each loop.



  • [quote author="Gerolf" date="1302352548"]Hi,
    perhaps you should think of the class you want to use. QQueue is a QLIst and QList is a linked list.
    But it seams you want to use arrays, so QVector, QBuffer or QByteArray would fit better.

    My first question would be:

    Why do you use a Queue? Only because you uise it in C#?

    If you need a QByteArray for the interfaces / classes you are using, then fill the data into a QByteArray in the for each loop.[/quote]

    Yeah, the only reason I was using Queue was because I used it in C#.
    Though, I think ive got this working, I used std::stringstream instead of QQueue, seems to be working.



  • Ah, ok. Sorry - you did not mention that lacking experience in C++, that explains a lot. And I'm sorry if my first answers sounded a bit rude. It was not my intention to expel you out of the Qt world :-)

    You might consider working on a C++ tutorial first, it's sometimes easier to learn the simple things (templates, see below) with simple examples :-)

    Regarding your actual problem:

    As you're from a C# background, I might assume your kind of familiar with inheritance and subclassing?

    QQueue is a subclass of QList. So QQueue basically is a QList with some additional methods. Both are so called template classes (metaprogramming in other languages, I don't know if C# has a similar construct), which take a type parameter if you want to create an instance of them. This way you write the code only once, and can use it with different types and can create lists (or queues) of ints, doubles, strings or whatever object else you have (including your own object types of course).

    The rationale behind there is no "toArray" method in the list/queue is simple: as you can put in so different classes, there is simply no general way to represent these classes as a byte array. So you will have to iterate over the contents of the list/queue convert the contents into a byte array and append this to another byte array.

    As you use a byte type (char) to your queue it seems to be logical to have a toArray method that returns a QByteArray. But as you now know, QList would have to handle any arbitrary complex object type to be converted to a byte array - that's the showstopper here.

    A QBuffer is basically a QByteArray which can be treated like a file (you have read/write/append/seek methods).

    So, if you have a QQueue of bytes, you need to append them to the byte array/buffer one bye one:

    @
    QQueue<char> inputQueue = methodToFillTheQueue();
    QBuffer buffer;
    foreach(char b, inputQueue) {
    buffer.append(b);
    }
    QByteArray ba = buffer.data();
    @

    This is what your code does. The question is now, do you need the additional methods of the queue (pull from the start of the list, append to the end) and of the buffer (file I/O like methods like read, write). If you do, the queue is not emptied upen the conversion process and you might consider this snippet:

    @
    QQueue<char> inputQueue = methodToFillTheQueue();
    QBuffer buffer;
    while(!inputQueue.isEmpty()) {
    // get the first entry, remove it from the queue
    // and append it to the buffer
    buffer.append(inputQueue.dequeue());
    }
    QByteArray ba = buffer.data();
    @

    But I suppose this is not the case, so the above code could be changed to this:

    @
    QList<char> inputList = methodToFillTheQueue();
    QByteArray buffer;
    foreach(char b, inputList) {
    buffer.append(b);
    }
    @

    You can of course mix the queue with the buffer replaces by a QByteArray directly or vice versa.

    In the end, you have a byte array that you can hand over to the QTcpSocket's write method.

    Please feel free to ask further questions if you need advice on which class to use in your use case.



  • [quote author="azkay" date="1302352827"]Yeah, the only reason I was using Queue was because I used it in C#.
    Though, I think ive got this working, I used std::stringstream instead of QQueue, seems to be working.
    [/quote]

    Can you give us some more hints on what types you work on (you mentioned bytes and strings), we can point you to some convenient Qt classes then - there's almost everything here :-)



  • What ive done seems to not be working either.
    Maybe itll be easier if I give you everything ive done so far;
    Also, sorry for sounding too bad, been working on this for hours and its getting frustrated.
    Ive coded in lots of different languages, but everytime I try to learn C++ again, I end up doing it for a couple of days, getting annoyed and moving on for a few months, always coming back, though.

    I thought using the stringstream would fix it, but I guess not.
    What im doing is, using "Smartcam":http://sourceforge.net/projects/smartcam/files/smartcam_windows/SmartCam_v1_4/ as the server, I coded up a "client":http://talk.maemo.org/showthread.php?t=71452 for the Nokia N900 (in C#) to stream the N900s camera to it.
    People suggested I learn some C++ and try to port it over, to save having to install all the mono libs on the n900 just to run it.

    So thats the background.
    This part of the code is what im trying to port over, which is basically the "heart" of it.
    It encodes the jpeg with the smartcam headers, then sends them to the smartcam server.
    Biggest problem has been trying to get a BitConverter.GetBytes() equivalent, which in the c++ code is sort of working/sort of broken, most probably very wrong but its the closest I got while getting annoyed at it all.

    C#: http://pastebin.com/EqxKk4H0
    C++: http://pastebin.com/XW8WPZH0

    If im making no sense, sorry.



  • Thanks for the detailed infos. What you want to achieve should be easy in Qt. I'll have a look at it later and will come back with some sample code for you. I just need to do some gardening first ;-)

    I can understand that you are frustrated. C++ is a very powerful tool with the cost that you can easily shoot you in the foot. Maybe it's a bit hard to learn both C++ and the use of some 3rdparty libraray together with the more advanced parts of Qt (say networking for example) all in one step :)



  • Unfortunately, the pastebin files are no longer available, can you please paste the code here. I have some solution at hand but want to check that it actually fits the original C# algorithms.



  • Sorry, here:
    @
    using System;
    using System.IO;
    using System.Collections.Generic;

    namespace enqueue{
    class MainClass {
    public static void Main (string[] args){
    Queue<byte> _buffer = new Queue<byte>();
    byte[] _fileData = File.ReadAllBytes("test.jpg");
    byte[] _tmpSize = BitConverter.GetBytes(_fileData.length());

            _buffer.Enqueue(1);
            _buffer.Enqueue(_tmpSize[2]);
            _buffer.Enqueue(_tmpSize[1]);
            _buffer.Enqueue(_tmpSize[0]);
    
            foreach(byte _b in _fileData){
                _buffer.Enqueue(_b);
            }
    
            byte[] _packet = _buffer.ToArray();
            //tcp sending would be here
        }
    }
    

    }
    @



  • Hi azkay,

    a possible Qt code for you C# would be this:

    @
    #include <QtCore/QBuffer>
    #include <QtCore/QFile>

    int foo()
    {
    QFile file("test.jpg");
    if(file.open(QFile::ReadOnly))
    {
    QByteArray _fileData = file.readAll();
    QByteArray _buffer;
    qint32 nLength = _fileData.length();

        _buffer.append(1);
        // this doies the same a C# BitConverter.GetBytes(_fileData.length()); and then adding array[2], array[1] array[0]
        _buffer.append((nLength >> 16) & 0xFF);
        _buffer.append((nLength >> 8) & 0xFF);
        _buffer.append(nLength & 0xFF);
        _buffer.append(_fileData);
         
        //tcp sending would be here
    }
    

    }
    @

    The only tricky thing is converting the result of this:

    @
    BitConverter.GetBytes(_fileData.length());
    @

    Instead of having two byte arrays, you could also work with only one:

    @
    #include <QtCore/QBuffer>
    #include <QtCore/QFile>

    int foo()
    {
    QFile file("test.jpg");
    if(file.open(QFile::ReadOnly))
    {
    QByteArray _buffer = file.readAll();
    qint32 nLength = _buffer.length();

        // this does the same a C# BitConverter.GetBytes(_fileData.length()); and then adding array[2], array[1] array[0]
        _buffer.prepend(nLength & 0xFF);
        _buffer.prepend((nLength >> 8) & 0xFF);
        _buffer.prepend((nLength >> 16) & 0xFF);
        _buffer.prepend(1);
        
        //tcp sending would be here
    }
    

    }
    @



  • That is amazing, thank you all so much.



  • Prepending data on a QByteArray is a costly operation, as the content of the existing byte array must be copied.

    As you will eventually send the data via a QTcpSocket, there is no need to buffer the data in a QByteArray. Just do some sanity checks (file.length() must not be greater than 2^24 = 256256256 = 16777216) and the write the data directly to the socket:

    @
    QFile file("test.jpg");
    qint64 fileSize = file.size();

    // 3 bytes = 24 bits:
    // 2^24 = 256256256 = 16777216
    if(fileSize > 16777216) {
    qDebug() << "file too big";
    return;
    }

    if(!file.open(QFile::ReadOnly)) {
    qDebug() << "file cannot be opened";
    return;
    }

    QByteArray fileContents = file.readAll();
    file.close();

    _tcpSocket.write(1); // the type
    _tcpSocket.write((fileSize >> 16) & 0xFF);
    _tcpSocket.write((fileSize >> 8) & 0xFF);
    _tcpSocket.write(fileSize & 0xFF);
    _tcpSocket.write(fileContents);
    @



  • Ok, that's better, you are right.
    I left out the socket part and thought, if you want to post process it, the it would be better top have the content in the array.

    you could also first put the first 4 bytes in and then append the file content , but that also copies the content around...

    And perhaps you want to put the tcp stuff in a separate function....



  • Thanks again, ive successfully (after a few more issues that I sorted out) gotten it to stream from my phones camera to the smartcam server.

    Next step, making the GUI. Once all the bugs are fixed, step after that will be looking at recoding my own smartcam server/webcam filter to support higher resolutions and maybe other things, which I have a feeling will be a lot more trouble than this was.


Log in to reply
 

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