Code Monkey home page Code Monkey logo

Comments (4)

danvratil avatar danvratil commented on August 16, 2024 1

Hi,

thanks for the report. Indeed we allow constructing an empty invalid QCoro::Task, so awaiting it shouldn't crash (not sure what it should do, though). I'll try to fix it, and probably deprecate the default constructor as it serves no real purpose. An empty QCoro::Task makes little sense.

As a side note, you ran into the problem because you are using QCoro wrong (at least from what I can see from the minimal sample). Just returning a QmlTask doesn't magically make your slowOperation() function non-blocking. Your implementation will still block the main thread for 1s.

You need to have your "slow operation" implemented as a proper real coroutine, then you just wrap the returned QCoro::Task (which represents the running coroutine) into QCoro::QmlTask which makes it work in QML.

class TestQmlType : public QObject
{
    Q_OBJECT
    QML_ELEMENT
public:
    explicit TestQmlType(QObject *parent = nullptr);
    Q_INVOKABLE QCoro::QmlTask slowOperation();

private:
    // A real coroutine with QCoro::Task<> return type
    QCoro::Task<QVariant> doSlowOperation();
};
QCoro::QmlTask TestQmlType::slowOperation()
{
    return QCoro::QmlTask(doSlowOperation());
}

QCoro::Task<QVariant> TestQmlType::doSlowOperation()
{
    qInfo() << "Slow operation start";
    co_await QCoro::sleepFor(1s);
    qInfo() << "Slow operation end";

    co_return 42;
}

from qcoro.

kelteseth avatar kelteseth commented on August 16, 2024

Ahh, thanks! I was a bit confused by the docs then. Is there a way to move this into a single function?

    return QCoro::QmlTask([]() -> QCoro::Task<QVariant> {
        qInfo() << "Slow operation end";
        co_return 42;
    });

gives me:

C:\Users\Ryzen-7950X\Documents\CoroTest\TestQmlType.cpp(8): error C2440: '<function-style-cast>': cannot convert from 'TestQmlType::slowOperation::<lambda_1>' to 'QCoro::QmlTask'
C:\Users\Ryzen-7950X\Documents\CoroTest\TestQmlType.cpp(8): note: 'QCoro::QmlTask::QmlTask': no overloaded function could convert all the argument types
C:\Users\Ryzen-7950X\Documents\CoroTest\ThirdParty\qcoro\QCoro\qml\qcoroqmltask.h(37): note: could be 'QCoro::QmlTask::QmlTask(QCoro::Task<QVariant> &&)'
C:\Users\Ryzen-7950X\Documents\CoroTest\TestQmlType.cpp(8): note: 'QCoro::QmlTask::QmlTask(QCoro::Task<QVariant> &&)': cannot convert argument 1 from 'TestQmlType::slowOperation::<lambda_1>' to 'QCoro::Task<QVariant> &&'
C:\Users\Ryzen-7950X\Documents\CoroTest\TestQmlType.cpp(11): note: Reason: cannot convert from 'TestQmlType::slowOperation::<lambda_1>' to 'QCoro::Task<QVariant>'
C:\Users\Ryzen-7950X\Documents\CoroTest\TestQmlType.cpp(11): note: No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
C:\Users\Ryzen-7950X\Documents\CoroTest\ThirdParty\qcoro\QCoro\qml\qcoroqmltask.h(68): note: or       'QCoro::QmlTask::QmlTask(QCoro::Task<void> &&)'
C:\Users\Ryzen-7950X\Documents\CoroTest\ThirdParty\qcoro\QCoro\qml\qcoroqmltask.h(59): note: or       'QCoro::QmlTask::QmlTask(T &&)'
C:\Users\Ryzen-7950X\Documents\CoroTest\ThirdParty\qcoro\QCoro\qml\qcoroqmltask.h(44): note: or       'QCoro::QmlTask::QmlTask(QCoro::Task<T> &&)'
C:\Users\Ryzen-7950X\Documents\CoroTest\TestQmlType.cpp(8): note: while trying to match the argument list '(TestQmlType::slowOperation::<lambda_1>)'

Also looks like the FetchContent_Populate I use is not fully correct, because I cannot include #include "QCoro/core/qcorotimer.h"

C:\Users\Ryzen-7950X\Documents\CoroTest\ThirdParty\qcoro\qcoro\core\qcorotimer.h:8: error: C1083: Cannot open include file: 'qcorocore_export.h': No such file or directory

from qcoro.

danvratil avatar danvratil commented on August 16, 2024

Well, the documentation is far from perfect :-) I'll try to update it later...

You are on the right track, but you have to call the lambda so that you obtain the QCoro::Task<> that can be passed into QmlTask. In your case, the coroutine is synchronous (there's no co_await) so when called it will run, finish, store its result into a QCoro::Task and return that to you. You pass it to QmlTask and QmlTask will extract the result and provide it into QML (by invoking your .then() callback in JS).

If your lambda was a coroutine that suspends, then you would call it, the coroutine would run as a regular function until it would reach co_await - at that point it would suspend and return the QCoro::Task holding a reference to the suspended coroutine, which you then pass to QmlTask again. Once the thing being awaiting is finished, the coroutine would be resumed and run to its completion, storing the result to the QCoro::Task object you already have and that in turn would once again trigger the JS callback in your QML code.

Also looks like the FetchContent_Populate I use is not fully correct, because I cannot include #include "QCoro/core/qcorotimer.h"

Are you linking against the QCoro::Core target in your CMakeLists? That should pull in all the correct include paths.

from qcoro.

kelteseth avatar kelteseth commented on August 16, 2024

Are you linking against the QCoro::Core target in your CMakeLists? That should pull in all the correct include paths.

Yes, this is from the attached test project: https://github.com/danvratil/qcoro/files/13634187/CoroTest.zip

EDIT: Ok looks like I was wrong. Normally I would expect the QCoro6::Qml to have an public dependency to QCoro6::Core :)

include(FetchContent)

FetchContent_Populate(
    QCoro
    GIT_REPOSITORY https://github.com/danvratil/qcoro.git
    GIT_TAG 12c052e8e29b9f976ea1c02af7c845573bd8efa3
    # Workaround because: 1. QtCreator cannot handle QML_ELEMENT stuff when it is in bin folder
    # https://bugreports.qt.io/browse/QTCREATORBUG-27083
    SOURCE_DIR ThirdParty/qcoro)

add_subdirectory(ThirdParty/qcoro)
# Does not work, needs to set(CMAKE_CXX_STANDARD 23)
qcoro_enable_coroutines()

qt_add_qml_module(appCoroTest
    URI CoroTest
    VERSION 1.0
    QML_FILES Main.qml
    SOURCES TestQmlType.h TestQmlType.cpp
)


target_link_libraries(appCoroTest
    PRIVATE Qt6::Quick QCoro6::Qml
)

from qcoro.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.