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. Javascript string array to QVariant in C++ API
Forum Update on Monday, May 27th 2025

Javascript string array to QVariant in C++ API

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
8 Posts 4 Posters 1.2k 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.
  • B Offline
    B Offline
    Bob64
    wrote on 12 Nov 2019, 13:54 last edited by
    #1

    I have a C++ backend API in my QML application which contains a function that expects to receive an argument of differing basic types. It is currently defined as accepting a QVariant. (The function itself does not really care what the value type is as it passes it along to an RPC mechanism that converts the variant to a JSON string to make a remote call.)

    Q_INVOKABLE void f(const QVariant& v) const;
    

    This has worked so far, but I have just encountered a problem in trying to call this function from QML Javascript code in the case where the value is a JS string array:

    var value = ["a"];
    myApi.f(value);
    

    In the Qt Creator debug environment, the value of the parameter shows as "<not accessible>". The debugger does seem to be aware that it should be a single element array but shows nothing for the [0] element. Higher up the call-stack, things get opaque but it looks like the argument is actually null (0x0).

    Am I missing something about how array values are converted between Javascript and C++ in QML?

    O 1 Reply Last reply 12 Nov 2019, 14:02
    0
    • B Bob64
      12 Nov 2019, 13:54

      I have a C++ backend API in my QML application which contains a function that expects to receive an argument of differing basic types. It is currently defined as accepting a QVariant. (The function itself does not really care what the value type is as it passes it along to an RPC mechanism that converts the variant to a JSON string to make a remote call.)

      Q_INVOKABLE void f(const QVariant& v) const;
      

      This has worked so far, but I have just encountered a problem in trying to call this function from QML Javascript code in the case where the value is a JS string array:

      var value = ["a"];
      myApi.f(value);
      

      In the Qt Creator debug environment, the value of the parameter shows as "<not accessible>". The debugger does seem to be aware that it should be a single element array but shows nothing for the [0] element. Higher up the call-stack, things get opaque but it looks like the argument is actually null (0x0).

      Am I missing something about how array values are converted between Javascript and C++ in QML?

      O Offline
      O Offline
      ODБOï
      wrote on 12 Nov 2019, 14:02 last edited by
      #2

      @Bob64 hi
      can this page help ?

      1 Reply Last reply
      0
      • B Offline
        B Offline
        Bob64
        wrote on 12 Nov 2019, 15:18 last edited by
        #3

        Thanks for the suggestion, but I had already read that page and it seemed to support my expectation that this should just work. I forgot to mention that I am on 5.9.6 in case anything new had been added in this area in more recent releases.

        I do have a small update in that, having been inspired by a mention of it in a StackOverflow article that I found, I tried messing about with using QJSValue on the C++ side and that does seem to provide a route for passing the string list value from Javascript to the C++ side. I am exploring doing something like this:

        Q_INVOKABLE void f(const QVariant& v) const;
        Q_INVOKABLE void f(const QJSValue& v) const;
        

        where the second overload delegates to the first, using v.toVariant() as argument.

        1 Reply Last reply
        0
        • G Offline
          G Offline
          GrecKo
          Qt Champions 2018
          wrote on 12 Nov 2019, 18:01 last edited by GrecKo 11 Dec 2019, 18:01
          #4

          Are you sure it's not just just an issue with the debugger view?
          It should work. What does qDebug() << v; outputs?

          1 Reply Last reply
          0
          • B Offline
            B Offline
            Bob64
            wrote on 13 Nov 2019, 10:58 last edited by
            #5

            Hi @GrecKo

            No - I should have said, but I only started digging in the debugger because there was a genuine issue in my application.

            I made a small example to test this (listed below). If I pass a simple string value ("Hello, World!") to my api function, the debug output is:

            QVariant(QString, "Hello, World!")

            If I pass an array, ["Hello, World!"], the output is:

            QVariant(QJSValue, )

            As mentioned earlier, I can work around this by adding an API function that accepts a QJSValue and then performing toVariant on it.

            I also confirmed this behaviour in 5.12.1 (which I have installed but cannot use in production at the moment). I am surprised that I cannot find more discussion of this and still wonder if there is something I am missing.

            api.h:

            #pragma once
            #include <QObject>
            #include <QVariant>
            class Api : public QObject
            {
                Q_OBJECT
            public:
                explicit Api(QObject *parent = nullptr);
                Q_INVOKABLE QString strVal(QVariant v);
            };
            

            main.cpp:

            #include "api.h"
            
            #include <QGuiApplication>
            #include <QQmlApplicationEngine>
            #include <QQmlContext>
            #include <QtDebug>
            
            Api::Api(QObject *parent) : QObject(parent) {}
            
            QString Api::strVal(QVariant v) {
                qDebug() << v;
                return v.toString();
            }
            
            int main(int argc, char *argv[])
            {
                QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
                QGuiApplication app(argc, argv);
                QQmlApplicationEngine engine;
            
                Api api;
                auto context = engine.rootContext();
                context->setContextProperty("api", &api);
            
                const QUrl url(QStringLiteral("qrc:/main.qml"));
                engine.load(url);
            
                return app.exec();
            }
            

            main.qml:

            import QtQuick 2.9
            import QtQuick.Window 2.2
            Window {
                visible: true; width: 640; height: 480
                title: api.strVal("Hello, World!")
            }
            
            1 Reply Last reply
            0
            • B Offline
              B Offline
              Bob64
              wrote on 6 Jan 2020, 14:40 last edited by
              #6

              I'm giving this one a bump. I won't make a habit of doing this, but I was a little surprised that I didn't get more feedback on this one from some of the QML experts out there as it seems like quite a fundamental thing not to be working. Still keen to understand whether this is a bug in Qt, expected behaviour in Qt or something I am getting wrong.

              1 Reply Last reply
              0
              • F Offline
                F Offline
                FKosmale
                wrote on 6 Jan 2020, 20:51 last edited by
                #7

                I currently only have very recent versions of Qt at hand (5.14 and later), but there, the array gets treated correctly. Using

                    if (v.canConvert<QJSValue>()) {
                        auto jsval = v.value<QJSValue>();
                        if (jsval.isArray()) {
                            QString s = v.value<QJSValue>().property(0).toString();
                            qDebug() << s;
                            return s;
                        }
                    }
                    return v.toString();
                

                , I'll get the correct value.

                B 1 Reply Last reply 7 Jan 2020, 10:19
                2
                • F FKosmale
                  6 Jan 2020, 20:51

                  I currently only have very recent versions of Qt at hand (5.14 and later), but there, the array gets treated correctly. Using

                      if (v.canConvert<QJSValue>()) {
                          auto jsval = v.value<QJSValue>();
                          if (jsval.isArray()) {
                              QString s = v.value<QJSValue>().property(0).toString();
                              qDebug() << s;
                              return s;
                          }
                      }
                      return v.toString();
                  

                  , I'll get the correct value.

                  B Offline
                  B Offline
                  Bob64
                  wrote on 7 Jan 2020, 10:19 last edited by Bob64 1 Jul 2020, 11:33
                  #8

                  @FKosmale Thanks - maybe what I was missing was that we expected to see QJSValue involved here. I suppose I was expecting that a string list source would automatically have been converted to a QVariantList with QString elements and that is what I would have seen passed to the C++.

                  Certainly, if I understand it correctly, your solution is better than mine where I added an overload in the API to accept a QJSValue. At least the QJSValue is hidden in the implementation using your approach.

                  1 Reply Last reply
                  0

                  • Login

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