PDA

View Full Version : qml can not recognize the c++ parameters with &



stereoMatching
25th June 2013, 07:44
pass two arguments into the c++ api from qml site
when I add & on the api, the app can not recognize the signature
of the function.

.hpp


#ifndef TESTPARAM_HPP
#define TESTPARAM_HPP

#include <QList>
#include <QObject>
#include <QUrl>

class testParam : public QObject
{
Q_OBJECT
public:
explicit testParam(QObject *parent = 0);

signals:

public slots:
void test(QList<QUrl> &first, QList<QUrl> &second)
{

}

};

#endif // TESTPARAM_HPP



.cpp


#include "testParam.hpp"

testParam::testParam(QObject *parent) :
QObject(parent)
{
}


main.qml



import QtQuick 2.1
import QtQuick.Dialogs 1.0

import Test 1.0

Rectangle {
width: 100
height: 62

TestParam{
id: testParam
}

FileDialog{
id: fileDialog
//selectFolder: param.selectFolder
selectMultiple: true
nameFilters: [ "Image files (*.bmp *.jpg *.JPEG *.png *.ppm *.tiff *.xbm *.xpm)" ]
onAccepted: {
testParam.test(fileDialog.fileUrls, fileDialog.fileUrls);
}
}

MouseArea{
anchors.fill: parent

onClicked: {
fileDialog.open();
}
}
}


error message

Error: Unknown method parameter type: QList<QUrl>&

They are fine if
1 : strip the &
2 : reduce the parameters of “test” to a single parameter, that way you can preserve the &

Anyway to pass the parameters as reference into the “test” with two parameters?

wysota
25th June 2013, 10:07
QML has no notion of references. The data is always passed by value.

anda_skoa
25th June 2013, 10:08
Do you want to change the lists in the method?
I.e. why not use const &?

Cheers,
_

stereoMatching
25th June 2013, 10:50
Do you want to change the lists in the method?
I.e. why not use const &?

Cheers,
_

I tried it, like this



QList<QString> fileProcess::unique_strs(QList<QString> const &old_data, QList<QString> const &new_data)
{
//awkward solution and maybe meaningless, hope that in the future this could be solved
return set_difference_lazy(const_cast<QList<QString>&>(new_data), const_cast<QList<QString>&>(old_data));
}


There are two problems
1 : this solution is awkward
2 : I don't know the c++ sites would accept the parameters as reference or just copy them anyway?

wysota
25th June 2013, 11:02
You should first understand why QML does not like to accept references. If you have an object in QML, say.... "X" and you invoke your slot on it, it gets converted from the script representation to the C++ representation (to the "real" X type) and that gets passed to your slot. Which means that even if you modify that data in your slot, none of those modifications will be viisble from QML because the engine will not know to convert the "real" X type back to the script representation.

Another problem is using references as arguments to slots that can be ran in a different thread to that where the signal emission took place. This is an asynchronous call so you have no idea when the original variable is going to be accessed (and possibly modified). Qt takes a copy of the original object and stores that safely until the real invokation takes place. So again, a copy of the original structure is modified and has no influence on the initial variable which remains unchanged (hence again discarding any sense of using a non-const reference).

stereoMatching
25th June 2013, 16:19
In the conclusion, we must copy the data between qml and c++?

For me, no matter it may or may not an asynchronous call, we should
have the power to determine the parameters are pass by reference or value
It is the responsible of the programmers to handle the asynchronous issues
Is this another technicle difficulties of qml so they can't support?

wysota
25th June 2013, 16:47
First you should tell us why you want to pass those lists by non-const reference.

stereoMatching
25th June 2013, 18:07
First you should tell us why you want to pass those lists by non-const reference.

I am Using fileDialog to select a lot of files from qml(hundred, thousand, ten thousand and maybe more)
and need to do some post processing about the file names obtained by the fileDialog(sort, find out new strings between old strings and new strings,
prepend text, strip text and so on)

Even this is not a performance penalty yet, it is a waste to copy a bunch of strings, if it is possible, I would like to pass by reference

ps : pass by const reference is no use, I test it already, any alternation on the parameters pass into c++
would not affect the data of qml

wysota
25th June 2013, 20:01
and need to do some post processing about the file names obtained by the fileDialog(sort, find out new strings between old strings and new strings,
prepend text, strip text and so on)
So return the modified list instead of changing the original one. You'll be making a copy either way.

stereoMatching
25th June 2013, 21:34
So return the modified list instead of changing the original one. You'll be making a copy either way.
But before I can return the modified list, I need to get the data from qml site
It would be great if the return data could be moved(rvalue reference, rvo) to the qml site

What would you try to do if there are a lot of data need to transfer between c++ and qml?

From the view of technical, is it possible to make c++ and qml support pass by reference?

wysota
26th June 2013, 06:58
But before I can return the modified list, I need to get the data from qml site
It would be great if the return data could be moved(rvalue reference, rvo) to the qml site
It can't because C++ and QML use different representation for the data.


What would you try to do if there are a lot of data need to transfer between c++ and qml?
I would probably not move betweeen C++ and QML at all.

If you don't modify the lists then use const references but that will make a copy anyway.

anda_skoa
26th June 2013, 09:17
It is likely that the fileUrls property of FileDialog is actually of type QStringList, so passing the value to the C++ function might not involve any conversions.

In which case passing by const reference would not create a copy. Even passing by value would be cheap since QList is implicitly shared (reference counted) so copying is a relatively cheap operation.

Do you have any benchmark that shows the operation to be slow?

Cheers,
_

stereoMatching
26th June 2013, 11:18
It is likely that the fileUrls property of FileDialog is actually of type QStringList
I hope so, but it is QList<QUrl> but not QList<QString>
in the document of the FileDialog, there are nothing called fileUrl but filePath
and the qml type of filePath is list<string>
maybe this is because I am using 5.1RC, so the incoherent of the codes and the document still exist


Even passing by value would be cheap since QList is implicitly shared (reference counted)
Hard to said, because I need to modify the content of QList(sorting)


Do you have any benchmark that shows the operation to be slow?
No, it is not a bottleneck yet(maybe in the future, it is)
but the experience from c++(and c) make me feel nervous
when I have to copy the data which could be "moved" or take the reference usually

anda_skoa
27th June 2013, 09:05
I hope so, but it is QList<QUrl> but not QList<QString>

I see, should still be ok. Your slot has the same type for its arguments.



Hard to said, because I need to modify the content of QList(sorting)

Depends on the reference count at the time of modification. If the slot is the only one holding the list at that time it won't need to copy.
If there is another owner, then there will be a copy of the list. Since you don't change the url data the QUrl instances should still be the same.



No, it is not a bottleneck yet(maybe in the future, it is)
but the experience from c++(and c) make me feel nervous
when I have to copy the data which could be "moved" or take the reference usually

Due to the implicit sharing, copying is a lot like moving, actual copying happening on modification (copy on write).

Cheers,
_

wysota
27th June 2013, 10:42
Depends on the reference count at the time of modification. If the slot is the only one holding the list at that time it won't need to copy.
The reference count will not be 1 as the caller has a handle on the list as well.

stereoMatching
27th June 2013, 11:23
I see, should still be ok. Your slot has the same type for its arguments.
Because I want to make my question become easier to understand, I change the type of the example
the real type are a little bit tricky, one is "QUrl" and another one is "QString"
hope this could be fix in the release version