Обратный вызов успеха Emscripten FETCH API в классе C ++ - PullRequest
1 голос
/ 17 июня 2020

Я работаю с WebAssembly и пытаюсь сделать HTTPS-запрос из C ++. Я видел решение Emscripten FETCH API и пытался его использовать.

Чтобы проверить это, я создал Test класс, в который я отправляю запрос следующим образом:

void Test::sendRequest() {
    emscripten_fetch_attr_t attr;
    emscripten_fetch_attr_init(&attr);
    strcpy(attr.requestMethod, "GET");
    attr.attributes = EMSCRIPTEN_FETCH_LOAD_TO_MEMORY;
    attr.onsuccess = &Test::onSuccess;
    attr.onerror = &Test::onError;
    emscripten_fetch(&attr, "http://127.0.0.1:5000/");
}

И мой обратный вызов onSuccess выглядит так:

void Test::onSuccess(struct emscripten_fetch_t *fetch) {
    printf("Finished downloading %llu bytes from URL %s.\n", fetch->numBytes, fetch->url);
    setText(QString::fromUtf8(fetch->data));
    emscripten_fetch_close(fetch); // Free data associated with the fetch.
}

Но когда я пытаюсь скомпилировать, у меня появляется сообщение об ошибке:

error: assigning to 'void (*)(struct emscripten_fetch_t *)' from incompatible type 'void
  (Test::*)(struct emscripten_fetch_t *)'
attr.onsuccess = &Test::onSuccess;
                 ^~~~~~~~~~~~~~~~

Кажется, я не могу поместить функцию обратного вызова в класс, но мне нужно получить доступ к классу, чтобы изменить текстовый атрибут экземпляра с ответом.

Я попытался определить класс Test с шаблоном Singleton и удалить функцию обратного вызова из класса. С помощью этого метода я могу изменить текстовый атрибут, получив уникальный экземпляр класса, но я хотел бы, если возможно, напрямую добавить функцию обратного вызова в класс.

1 Ответ

2 голосов
/ 17 июня 2020

Нестатистическую c функцию-член нельзя использовать в качестве обратного вызова напрямую.

Однако большинство интерфейсов обратного вызова имеют где-то поле «пользовательских данных» для обратной связи с отправителем.

emscripten_fetch_attr_t имеет член void* userData, в котором вы можете хранить любой указатель, который хотите.
Этот указатель передается как userData в аргументе обратных вызовов, и вам просто нужно вернуть его обратно в правильный тип.

Таким образом, вы можете использовать бесплатную функцию в качестве обратного вызова обертывания с объектом как «пользовательские данные»:

void onSuccess(struct emscripten_fetch_t *fetch) {
    auto test = static_cast<Test*>(fetch->userData);
    test->onSuccess(fetch);
}

void Test::sendRequest() {
    emscripten_fetch_attr_t attr;
    emscripten_fetch_attr_init(&attr);
    strcpy(attr.requestMethod, "GET");
    attr.attributes = EMSCRIPTEN_FETCH_LOAD_TO_MEMORY;
    attr.userData = this;
    attr.onsuccess = onSuccess;
    // ...

И убедитесь, что объект жив, когда срабатывает обратный вызов.

...