Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

I need help with my Deno Qt/QML bindings - QGuiApplication::exec is blocking



  • Hello,

    I've been working on my QML bindings for Deno, the new JavaScript runtime. You can view them here: https://deno.land/x/qml@v0.1.5
    But there are problems.

    First off, some things you need to know.

    • Deno has a new (unstable) FFI API for calling native code.
    • Only C functions can be used. No C++ classes.
    • Buffers (aka strings) can be passed as input parameters, but they cannot be return values.
    • Because of this, the only way to make Qt work at this time is to declare a thread_local std::unique_ptr<App> global class and initialize QGuiApplication in an init() function.
    • FFI blocks the entire Deno event loop until the function returns.
    • It uses QGuiApplication and QQmlApplicationEngine.

    The problem is that int exec() { return qGuiApp->exec(); } is blocking. I need to replace it with something like:

    while (true) {
        processQtEvents();
        if (isDone()) break;
    }
    

    No matter how hard I tried, I can't figure out how to do it!

    Things I've tried:

    QEventLoop loop;
    while (loop.isRunning()) {
        loop.processEvents(QEventLoop::AllEvents | QEventLoop::WaitForMoreEvents | QEventLoop::EventLoopExec);
    }
    
    while (true) {
        qGuiApp->processEvents(QEventLoop::AllEvents, 6000);
        if (qGuiApp->closingDown()) break;
    }
    
    qGuiApp->eventDispatcher()->processEvents(QEventLoop::AllEvents);
    

    None of them work. The most common problem is that when the window is closed, the application still keeps running (aka the only way to end it is with CTRL+C). Signals such as QQmlApplicationEngine::quit and QQmlApplicationEngine::exit do not fire either.

    I even tried making everything live in a global C++ thread class (not QThread) and passing data using mutexes and conditional variables, so that I could just have qGuiApp->exec() running in a separate thread and call isDone() from Deno. Still doesn't work. ThreadedApplication::operator()() and ThreadedApplication::setData() are in different threads, which Qt hates.

    In simplest terms: can QGuiApplication::exec() be replaced with a while() loop?

    I apologize if I'm not being clear about something. I'm at wits end to try and figure this out.


  • Lifetime Qt Champion

    Hi and welcome to devnet,

    Did you try to integrate Qt's event loop with the one from Deno ?

    AFAIK, QAbstractEventDispatcher is the starting for that.



  • @SGaist Thanks for the reply. Unfortunately, Deno's event loop isn't exposed, at all. It's just calling functions from a C ABI using dlopen().


Log in to reply