Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. Converting array of byte values to c++ vector<unsigned char>

Converting array of byte values to c++ vector<unsigned char>

Scheduled Pinned Locked Moved Solved QML and Qt Quick
4 Posts 3 Posters 3.0k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • P Offline
    P Offline
    pderocco
    wrote on last edited by pderocco
    #1

    I'm using the QmlMidi package, but its output side only supports short messages, not System Exclusive messages, which are potentially large arrays of bytes. Underneath, it uses the RtMidi package, which represents all MIDI messages as vector<unsigned char>. I'd like to add a Q_INVOCABLE function to the QmlMidi module that can convert some form of JavaScript array into a vector<unsigned char>.

    I was wondering if QML supports ArrayBuffer and typed arrays, so I did some searching. There is no official documentation of this, but I found this bug report: https://bugreports.qt.io/browse/QTBUG-45574?attachmentOrder=asc which shows that it kinda sorta works. The bug report test code is:

    function runTests() {
        var i;
        var buffer = new ArrayBuffer(12);
        for(i = 0; i < buffer.byteLength; i++)
            buffer[i] = i;
    
        console.log("Values of ArrayBuffer are:")
        for(i = 0; i < buffer.byteLength; i++) {
            console.log("["+i+"]: "+buffer[i]);
        }
    
        var srcBuffer = new Uint8Array( buffer, 4, 4 );
        console.log("Values of Uint8Array are:")
        for(i = 0; i < srcBuffer.length; i++) {
            console.log("["+i+"]: "+srcBuffer[i]);
        }
    }
    

    I tried this code in 5.11, and it proves that there is indeed an ArrayBuffer type, and a Uint8Array type, but the "bug" is that the latter array is filled with 0 instead of being a window into the former. The bug report was dismissed as "invalid", without saying why, although one commenter points out that you're not supposed to be able to use indexing directly on the ArrayBuffer, and that is indeed what the ECMAScript standard says. However, the first two pieces of the code work--you can treat an ArrayBuffer as an array of unsigned bytes, at least in the QML version of JavaScript. I also modified it to create a Uint8Array without an ArrayBuffer, and initialize it in the same way, and that works too, without violating the standard.

    So Since I only need unsigned bytes, I'd be happy to use either Uint8Array or ArrayBuffer in QML. But if I want to pass this into a method written in C++, what do I declare it as on the C++ side?

    JonBJ JKSHJ 2 Replies Last reply
    0
    • P pderocco

      I'm using the QmlMidi package, but its output side only supports short messages, not System Exclusive messages, which are potentially large arrays of bytes. Underneath, it uses the RtMidi package, which represents all MIDI messages as vector<unsigned char>. I'd like to add a Q_INVOCABLE function to the QmlMidi module that can convert some form of JavaScript array into a vector<unsigned char>.

      I was wondering if QML supports ArrayBuffer and typed arrays, so I did some searching. There is no official documentation of this, but I found this bug report: https://bugreports.qt.io/browse/QTBUG-45574?attachmentOrder=asc which shows that it kinda sorta works. The bug report test code is:

      function runTests() {
          var i;
          var buffer = new ArrayBuffer(12);
          for(i = 0; i < buffer.byteLength; i++)
              buffer[i] = i;
      
          console.log("Values of ArrayBuffer are:")
          for(i = 0; i < buffer.byteLength; i++) {
              console.log("["+i+"]: "+buffer[i]);
          }
      
          var srcBuffer = new Uint8Array( buffer, 4, 4 );
          console.log("Values of Uint8Array are:")
          for(i = 0; i < srcBuffer.length; i++) {
              console.log("["+i+"]: "+srcBuffer[i]);
          }
      }
      

      I tried this code in 5.11, and it proves that there is indeed an ArrayBuffer type, and a Uint8Array type, but the "bug" is that the latter array is filled with 0 instead of being a window into the former. The bug report was dismissed as "invalid", without saying why, although one commenter points out that you're not supposed to be able to use indexing directly on the ArrayBuffer, and that is indeed what the ECMAScript standard says. However, the first two pieces of the code work--you can treat an ArrayBuffer as an array of unsigned bytes, at least in the QML version of JavaScript. I also modified it to create a Uint8Array without an ArrayBuffer, and initialize it in the same way, and that works too, without violating the standard.

      So Since I only need unsigned bytes, I'd be happy to use either Uint8Array or ArrayBuffer in QML. But if I want to pass this into a method written in C++, what do I declare it as on the C++ side?

      JonBJ Offline
      JonBJ Offline
      JonB
      wrote on last edited by
      #2

      @pderocco said in Converting array of byte values to c++ vector<unsigned char>:

      Uint8Array

      Should you be reading https://stackoverflow.com/questions/35998503/typed-arrays-in-qml-qbytearray-to-js-uint8array-back-and-forth-interop, possibly http://doc.qt.io/qt-5/qbytearray.html too ?

      P 1 Reply Last reply
      0
      • P pderocco

        I'm using the QmlMidi package, but its output side only supports short messages, not System Exclusive messages, which are potentially large arrays of bytes. Underneath, it uses the RtMidi package, which represents all MIDI messages as vector<unsigned char>. I'd like to add a Q_INVOCABLE function to the QmlMidi module that can convert some form of JavaScript array into a vector<unsigned char>.

        I was wondering if QML supports ArrayBuffer and typed arrays, so I did some searching. There is no official documentation of this, but I found this bug report: https://bugreports.qt.io/browse/QTBUG-45574?attachmentOrder=asc which shows that it kinda sorta works. The bug report test code is:

        function runTests() {
            var i;
            var buffer = new ArrayBuffer(12);
            for(i = 0; i < buffer.byteLength; i++)
                buffer[i] = i;
        
            console.log("Values of ArrayBuffer are:")
            for(i = 0; i < buffer.byteLength; i++) {
                console.log("["+i+"]: "+buffer[i]);
            }
        
            var srcBuffer = new Uint8Array( buffer, 4, 4 );
            console.log("Values of Uint8Array are:")
            for(i = 0; i < srcBuffer.length; i++) {
                console.log("["+i+"]: "+srcBuffer[i]);
            }
        }
        

        I tried this code in 5.11, and it proves that there is indeed an ArrayBuffer type, and a Uint8Array type, but the "bug" is that the latter array is filled with 0 instead of being a window into the former. The bug report was dismissed as "invalid", without saying why, although one commenter points out that you're not supposed to be able to use indexing directly on the ArrayBuffer, and that is indeed what the ECMAScript standard says. However, the first two pieces of the code work--you can treat an ArrayBuffer as an array of unsigned bytes, at least in the QML version of JavaScript. I also modified it to create a Uint8Array without an ArrayBuffer, and initialize it in the same way, and that works too, without violating the standard.

        So Since I only need unsigned bytes, I'd be happy to use either Uint8Array or ArrayBuffer in QML. But if I want to pass this into a method written in C++, what do I declare it as on the C++ side?

        JKSHJ Offline
        JKSHJ Offline
        JKSH
        Moderators
        wrote on last edited by
        #3

        @pderocco said in Converting array of byte values to c++ vector<unsigned char>:

        I was wondering if QML supports ArrayBuffer and typed arrays, so I did some searching. There is no official documentation of this

        QML currently supports ECMAScript 5.1. The upcoming Qt 5.12 will support ECMAScript 7.

        The bug report was dismissed as "invalid", without saying why, although one commenter points out that you're not supposed to be able to use indexing directly on the ArrayBuffer, and that is indeed what the ECMAScript standard says.

        The bolded part explains why the bug report was invalid.

        However, the first two pieces of the code work--you can treat an ArrayBuffer as an array of unsigned bytes

        No, you cannot.

        var buffer = new ArrayBuffer(4);
        buffer[0] = 42;
        var view = new Uint8Array(buffer);
        
        console.log(buffer);
        console.log(buffer[0]);
        console.log(view);
        

        Output:

        ArrayBuffer { byteLength: 4, '0': 42 }
        42
        Uint8Array [ 0, 0, 0, 0 ]
        

        buffer[0] = 42 adds a new property in the buffer object. It does not update the buffer itself!

        You'll get this behaviour in QML or any other standards-compliant JavaScript environment, like node.js

        at least in the QML version of JavaScript.

        There is no such thing as "QML version of JavaScript". QML follows the JavaScript standard.

        If something in QML differs from the JavaScript standard, that means there is a bug in QML.

        So Since I only need unsigned bytes, I'd be happy to use either Uint8Array or ArrayBuffer in QML. But if I want to pass this into a method written in C++, what do I declare it as on the C++ side?

        See @JonB's links

        Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

        1 Reply Last reply
        2
        • JonBJ JonB

          @pderocco said in Converting array of byte values to c++ vector<unsigned char>:

          Uint8Array

          Should you be reading https://stackoverflow.com/questions/35998503/typed-arrays-in-qml-qbytearray-to-js-uint8array-back-and-forth-interop, possibly http://doc.qt.io/qt-5/qbytearray.html too ?

          P Offline
          P Offline
          pderocco
          wrote on last edited by
          #4

          @JonB
          I had already found the first link. It asks if there is a way to convert between a JavaScript Uint8Array and a Qt QByteArray. By the end of the topic, that question remains unanswered. The second link describes QByteArray but makes no mention of accessing it from QML.

          However, I just found this one-liner in the docs:

          The QML engine provides automatic type conversion between QByteArray values and JavaScript ArrayBuffer objects.

          That suggests that I should be able to rewrite the QmlMidi package so that on MIDI input it converts the vector<unsigned char> to a QByteArray, which JavaScript will see as an ArrayBuffer, and which I can then use to construct a Uint8Array; and on output, I could create a QByteArray, then pass its buffer to the QmlMidi module which would see it as a QByteArray, and convert that back to a vector<unsigned char>. That seems an adequate solution, a bit of excessive copying, but certainly way better than dealing with variant arrays.

          @JKSH
          By "version" I meant "implementation". Browsers have their own implementations, which attempt with varying degrees of success to live up to a standard. And QML has its own, since there are a few documented differences. It appeared to me that the authors had perhaps added array indexing to the ArrayBuffer type, but I see now why it appeared to work but really didn't. Thanks.

          1 Reply Last reply
          3

          • Login

          • Login or register to search.
          • First post
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • Users
          • Groups
          • Search
          • Get Qt Extensions
          • Unsolved