Solved! : static function not working well QResource::registerResource(const uchar * rccData, const QString & mapRoot)



  • Edit: Solved. The mapRoot is a DIRECTORY and not a file or some other identifier as first thought.
    Thanks Terence Simpson for pointing it out.
    See my second post for the correct code.
    Feel free to use this sample code for example documentation or snippets.

    Hi folks,

    I'm having a problem with the function QResource::registerResource(const uchar * rccData, const QString & mapRoot)

    I started using it, expecting to create data to qrc directly.
    I'm using it in an app where i need to decrypt data (also in qrc) to javascript and keep it somewhere safe, so keeping it in qrc memory would be ok.
    The problem is that it creates an empty file in QRC. Am i doing something wrong or it's a QT problem ?

    Follows the output of my code and a minimal code sample.

    My output result is the following, notice that there is no data and no size :(

    rccPath "/tmp/b.rcc"
    data_len 86
    ok true
    c_data: qres size: 4
    res.fileName() "/tmp_resource"
    res.size() 0
    res.data() 0x0
    res.isValid() true
    res.isCompressed() false
    QFile::exists(":"+res.fileName()) true
    resource_data ""

    @
    #include <QtCore>
    #include <QDebug>
    #include <Qt/qapplication.h>

    #include <QtCore/QFileInfo>
    #include <QtCore/QProcess>
    #include <QtGui/QFileDialog>
    #include <QtCore/QResource>

    #define Q(AAA) qDebug() << #AAA <<" " << AAA << endl;

    void print_res(QString in_res) {
    QResource res(in_res);
    Q(res.fileName());
    Q(res.size());
    Q(res.data());
    Q(res.isValid());
    Q(res.isCompressed());
    Q(QFile::exists(":"+res.fileName()));
    QByteArray resource_data((const char *)res.data());
    Q(resource_data);
    }

    int main(int argc, char** argv)
    {
    QString testFile = QDir::tempPath() + "/b.txt";
    {
    QFile file(testFile );
    file.open(QIODevice::WriteOnly | QIODevice::Text);
    QTextStream out(&file);
    out << "Qt rulez my world\n";
    file.close();
    }

    QString qrcFile = QDir::tempPath() + "/b.qrc";
    {
        QFile file&#40;qrcFile&#41;;
        file.open(QIODevice::WriteOnly | QIODevice::Text&#41;;
        QTextStream out(&file&#41;;
        out << "<!DOCTYPE RCC><RCC version=\"1.0\"><qresource prefix=\"/\"><file>b.txt</file></qresource></RCC>" << endl;
        file.close(&#41;;
    }
    
    QFileInfo qrcFileInfo(qrcFile);
    QString rccFileName = qrcFileInfo.baseName() + ".rcc";
    QString rccPath = qrcFileInfo.absolutePath() + "/" + rccFileName;
    
    QStringList args;
    
    args << qrcFile;
    args << "-binary";
    args << "-o" << rccPath;
    
    QProcess rccProc;
    QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
    QString qtDirPath = env.value("QTDIR");
    bool isLoaded = false;
    int ret = -1;
    
    rccProc.setWorkingDirectory(qtDirPath + "bin/");
    ret = rccProc.execute("rcc", args);
    
    if (ret == 0) // rcc executed successfully
    {
        Q(rccPath);
    

    // isLoaded = QResource::registerResource(rccPath);// this works fine, the following does not.

        static QString t_file&#40;rccPath&#41;;
    
        QFile bin_file(t_file&#41;;
        int data_len = bin_file.size(&#41;;
        Q(data_len &#41;;
        static uchar * c_data = new uchar[data_len];
    
        bool ok = false;
        if (bin_file.open(QIODevice::ReadOnly&#41;)
            ok = (data_len == (uint)bin_file.read((char*)c_data, data_len));
        if (!ok) {
            delete [] c_data;
            c_data = 0;
            data_len = 0;
            return -1;
        }
        Q(ok );
        printf ("\nc_data: %s size: %d \n",c_data,strlen((char*)c_data));
        bool b_registerResource = QResource::registerResource(c_data,"/tmp_resource");
        print_res("/tmp_resource"); // :( data == 0 and size == 0 :( should have data and size.
    }
    

    }

    @



  • Line 85 will print the length to the first zero byte in the binary data. In your case 4 because the binary compiled form of the QRC file always starts "qres" followed by a number that is likely to start with a zero byte.

    After line 86 you should be able to access file ":/b.txt" because you have grafted the binary data in to the virtual resource directory structure. A quick check of QFile::exists(":/b.txt") confirms this.

    In print_res() you are treating the path "/tmp_resource", which you have just created as a virtual directory in the resource system, as if it is the real path to an *.rcc file for QResource to load. It isn't, and consequently, QResource does not load it.

    This whole exercise seems horribly convoluted, and makes your application dependent on having the Qt development system to run. Why not just decrypt the data from your encrypted, built-in resource into a QByteArray or QBuffer?



  • The file is not grafted. It seems that it never gets copied over to the qrc: virtual filesystem. It is created alright, but it's contents are not copied.

    Follows the updated code that according to you would work.

    @
    #include <QtCore>
    #include <qdebug.h>
    #include <Qt/qapplication.h>
    #include <QtCore/qfileinfo.h>
    #include <QtCore/qprocess.h>
    #include <QtCore/qresource.h>

    #define Q(AAA) qDebug() << #AAA <<" " << AAA << endl;

    QByteArray readFile (QString in_file) {
    QFile a(in_file);
    if (!a.exists())
    {
    qWarning() << in_file << " does not exist";
    return "";
    }
    a.open(QIODevice::ReadOnly);
    Q(a.size());
    if (a.error()!=QFileDevice::NoError) {
    Q(a.errorString());
    return "";
    } else {
    QByteArray a_txt = a.readAll();
    Q(a_txt);
    Q(a_txt.size());
    a.close();
    return a_txt;
    }
    a.close();
    return "";
    }

    void print_res(QString in_res) {
    QResource res(in_res);
    Q(res.fileName());
    Q(res.size());
    Q(res.data());
    Q(res.isValid());
    Q(res.isCompressed());

    QByteArray resource_data((const char *)res.data());
    Q(resource_data);
    

    // QString virtual_path = ":"+res.fileName();
    Q(QFile::exists(res.fileName()));
    if (QFile::exists(res.fileName())) {
    readFile(res.fileName());
    }
    }

    int main(int argc, char** argv)
    {
    QString testFile = QDir::tempPath() + "/b.txt";
    {
    QFile file(testFile );
    file.open(QIODevice::WriteOnly | QIODevice::Text);
    QTextStream out(&file);
    out << "Qt rulez my world\n";
    file.close();
    }

    QString qrcFile = QDir::tempPath() + "/b.qrc";
    {
        QFile file&#40;qrcFile&#41;;
        file.open(QIODevice::WriteOnly | QIODevice::Text&#41;;
        QTextStream out(&file&#41;;
        out << "<!DOCTYPE RCC><RCC version=\"1.0\"><qresource prefix=\"/\"><file>b.txt</file></qresource></RCC>" << endl;
        file.close(&#41;;
    }
    
    QFileInfo qrcFileInfo(qrcFile);
    QString rccFileName = qrcFileInfo.baseName() + ".rcc";
    QString rccPath = qrcFileInfo.absolutePath() + "/" + rccFileName;
    
    QStringList args;
    
    args << qrcFile;
    args << "-binary";
    args << "-o" << rccPath;
    
    QProcess rccProc;
    QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
    QString qtDirPath = env.value("QTDIR");
    bool isLoaded = false;
    int ret = -1;
    
    rccProc.setWorkingDirectory(qtDirPath + "bin/");
    ret = rccProc.execute("rcc", args);
    
    if (ret == 0) // rcc executed successfully
    {
        Q(rccPath);
    

    // isLoaded = QResource::registerResource(rccPath);// this works fine, the following does not.

        static QString t_file&#40;rccPath&#41;;
    
        QFile bin_file(t_file&#41;;
        int data_len = bin_file.size(&#41;;
        Q(data_len &#41;;
        static uchar * c_data = new uchar[data_len];
    
        bool ok = false;
        if (bin_file.open(QIODevice::ReadOnly&#41;)
            ok = (data_len == (uint)bin_file.read((char*)c_data, data_len));
        if (!ok) {
            delete [] c_data;
            c_data = 0;
            data_len = 0;
            return -1;
        }
        Q(ok );
        printf ("\nc_data: %s size: %d \n",c_data,strlen((char*)c_data));
        bool b_registerResource = QResource::registerResource(c_data,"/b");
        d.cd(":/b/");
        Q(d.entryList());
    
        print_res(":/b/b.txt"); // :( data == 0 and size == 0 :( should have data and size.
    
    }
    

    }

    @



  • QResource::registerResource() is used to register a set of resources, ie: the "directory" rather than each "file". You do create your resource, as 'b_registerResource' will be true, but you place it in the prefix "/b.txt". So your file will actually be located at ":/b.txt/b.txt".



  • bq. Follows the updated code that according to you would work.

    No, the original code was working just fine and I didn't suggest you change it. It is just that you are misinterpreting what it does. Here is your original code with proof that the contents of the file were available after line 86:

    @
    #line 83
    Q(ok );
    printf ("\nc_data: %s size: %d \n",c_data,strlen((char*)c_data));
    bool b_registerResource = QResource::registerResource(c_data,"/tmp_resource");

        QFile f(":/tmp_resource/b.txt"); 
    

    // or QFile f(":/b.txt");
    QFileInfo fi(f);
    qDebug() << "Exists:" << fi.exists() << "Size:" << fi.size();
    if (f.open(QIODevice::ReadOnly)) {
    qDebug() << "Content:" << f.readAll();
    }

        // print_res("/tmp_resource"); // :( data == 0 and size == 0 :( should have data and size.
    }
    

    }
    @

    Output:

    @
    rccPath "/tmp/b.rcc"

    data_len 86

    ok true

    c_data: qres size: 4
    Exists: true Size: 18
    Content: "Qt rulez my world
    "
    @

    Interestingly, the text is available at the prefix specified in the registerResource() and at the prefix specified in the QRC file you built. I would have expected only the former (bug?).



  • The argument passes is prefixed to the root of each resource, so you can either use the default or place the resources in the specified root



  • Nice of ChrisW67 to point that out and of Terence to explain the rationale.
    That duality of location maybe is the one used in the QRC prefix parameter.

    Thanks for the support guys.


Log in to reply
 

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