How would I wait a frame? (GDExtension, cpp)

Godot Version

4.3

Question

I’m working on a GDExtension addon and need to use HTTP Requests. How can I simulate async calls like in C# or GDScript?

I have been trying and am still trying cpr. The basic async calls do not behave asynchronously at least in Godot. The callbacks do work but are very limited as I can’t access global variables or functions.

So that has resorted me to using Godot’s HTTP client class. I just need a way to pause a frame asynchronously in a while loop. I can’t find anything other than just making and using my own threads (yikes).

Example of the default (non-callback) request.

void AuthenticationService::sign_in_with_username_password(const String &username, const String &password)
{
    String url = AUTH_URL.utf8() + "/v1/authentication/usernamepassword/sign-in";
    Dictionary dict;
    dict["username"] = username;
    dict["password"] = password;
    String json_string = JSON::stringify(dict);

    cpr::AsyncResponse response = cpr::PostAsync(cpr::Url{url.utf8()},
                                                 cpr::Header{{"ProjectId", project_id.utf8()},
                                                             {"UnityEnvironment", environment.utf8()},
                                                             {"Content-Type", "application/json"}},
                                                 cpr::Body{json_string.utf8()});
    auto result = response.get(); // freezes game (response.wait() also)
    if (result.status_code == 200)
    {
        sign_in_response->from_dict(JSON::parse_string(result.text.c_str()));
        save_cache();
        emit_signal("on_signed_in");
        signed_in = true;
    }
    else
    {
        Ref<CoreExceptionContent> parsed_content = memnew(CoreExceptionContent(result.text.c_str()));
        ERR_FAIL_MSG(parsed_content->get_message());
    }
}

Seems like you will have to find a way to use callbacks, cpr isn’t made with Godot’s async in mind, but cpr boasts lambda captures work well.

Can’t find exactly what I’m looking for, maybe async support in a newer gdextension version.

Just used the current singleton within itself.

void AuthenticationService::sign_in_with_username_password(const String &username, const String &password)
{
    String url = AUTH_URL.utf8() + "/v1/authentication/usernamepassword/sign-in";
    Dictionary dict;
    dict["username"] = username;
    dict["password"] = password;
    String json_string = JSON::stringify(dict);

    cpr::PostCallback([](const cpr::Response &response)
                      {
                        if (response.status_code == 200)
                        {
                            instance->sign_in_response->from_dict(JSON::parse_string(response.text.c_str()));
                            instance->save_cache();
                            instance->emit_signal("on_signed_in");
                            instance->signed_in = true;
                        }
                        else
                        {
                            Ref<CoreExceptionContent> parsed_content = memnew(CoreExceptionContent(response.text.c_str()));
                            ERR_FAIL_MSG(parsed_content->get_message());
                        } },
                      cpr::Url{url.utf8()},
                      cpr::Header{{"ProjectId", (std::string)project_id.utf8()},
                                  {"UnityEnvironment", (std::string)environment.utf8()},
                                  {"Content-Type", "application/json"}},
                      cpr::Body{json_string.utf8()});
}

1 Like

u can also pass this into the lambda!!!

session->PostCallback([this](const cpr::Response &response)
                          { this->handle_sign_in_response(response.status_code, response.text.c_str()); });
1 Like

That’s the capture part yeah, if you want to go wild you can put & in it to automatically reference anything used in the lambda. Some warn against it for shadowing and harder to track stack expansion.

session->PostCallback([&](const cpr::Response &response)
                          { handle_sign_in_response(response.status_code, response.text.c_str()); });

Putting = will automatically copy anything used, which is more dangerous for similar stack expansion reasons.

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.