[Development] Copying QJSValue arrays

Simon Hausmann simon.hausmann at digia.com
Mon Sep 29 09:20:00 CEST 2014


On Sunday 28. September 2014 15.17.34 Paul Lemire wrote:
> Hi guys,
> 
> 
> 
> 
> We're working on being able to set GLSL uniform arrays from QML.
> 
> Basically what we have is a QParameter QObject exposed to QML as Parameter.
> 
> 
> 
> 
> It contains a QString name property and a QVariant value property.
> 
> 
> 
> 
> Here's how it can be used for scalar types.
> 
> 
> 
> 
> Parameter { name : "uniformName"; value : 1.0; }
> 
> 
> 
> 
> What we want is to send a copy of value to our backend renderer, so that we
> won't have any problem with threading. For scalar types, the copy is done
> implicitly.
> 
> 
> 
> 
> For array types, we'd like to be able to do something like that:
> 
> 
> 
> 
> property var myArray : [1.0, 1.0, 1.0]
> 
> Parameter { name : "uniformArray"; value : myArray }
> 
> 
> 
> 
> However in that case, value is a QJSValue containing a JS Array object.
> 
> We need a way to be able to copy that object.
> 
> The tricky part there is that we can't check the QVariant to to see if it
> contains a QJSValue directly as we don't want to introduce a dependency to
> the QML module.
> 
> 
> 
> 
> We're thinking of maybe introducing a Qt.array helper function that would
> return us a copy of the array directly or retrieve a QVector<QVariant>.
> 
> 
> 
> 
> If you've got ideas around that issue, please step in.

If you don't want to depend on QtQml (which seems odd for a library that offers 
Qml bindings), then what you could do is utilize the conversion functions. So 
after checking your QVariant for all other types you're interested in 
supporting, you can try

    canConvert<QVariantList>()

and afterwards convert to that. This will trigger a registered conversion 
function that will convert the JavaScript array object, that the QJSValue 
wraps, into a QVariant list that is not dependent on the JS engine anymore.

A QJSValue wrapped in a QVariant is (through QVariant) API always convertible 
to a QVariantList and a QVariantMap - it's a shortcut to writing

    qvariant_cast<QJSValue>(variant).toVariant().value<TypeYouWant>();

without using QJSValue. Due to the custom conversion functions being 
unconditional you can however not distinguish between a regular JavaScript 
object or an array. Therefore if the property contains an object the 
conversion to an array will cause a loss of data.

If you don't want to loose any data, you're going to have to support the types 
the QVariant can contain, and that includes direct support for QJSValue.


Simon



More information about the Development mailing list