回调在C++中

huangapple go评论106阅读模式
英文:

Callback in C++

问题

  1. 我正在进行一个wasm项目,在其中我需要在C++头文件中定义一个empscripten fetch回调,因为我需要更新一个成员变量。
  2. 有人可以帮我解决在C++中如何定义一个回调函数,以便我能够更新一个局部成员变量吗?
  3. 在我的MyClass.CPP,我有以下方法:
  4. ```cpp
  5. void MyClass::Register()
  6. {
  7. emscripten_fetch_attr_t attr;
  8. emscripten_fetch_attr_init(&attr);
  9. attr.onsuccess = DownloadSucceeded;
  10. attr.onerror = DownloadFailed;
  11. }

我在头文件中定义了DownloadSucceededDownloadFailed

  1. void DownloadSucceeded(emscripten_fetch_t* fetch)
  2. {
  3. printf("从URL %s 下载完成 %llu 字节。\n", fetch->url, fetch->numBytes);
  4. emscripten_fetch_close(fetch); // 释放与fetch关联的数据。
  5. m_unlocked = true;
  6. }
  7. void DownloadFailed(emscripten_fetch_t* fetch)
  8. {
  9. printf("从URL %s 下载失败,HTTP失败状态码:%d。\n", fetch->url, fetch->status);
  10. emscripten_fetch_close(fetch); // 失败时也释放数据。
  11. m_unlocked = false;
  12. }

我得到了以下异常:

  1. 必须调用对非静态成员函数的引用。

根据上述异常,我尝试发送一个引用,但似乎也不起作用。如果有聪明的人能解释为什么以及如何解决这个问题,我将不胜感激!

我的天真的引用示例也不起作用:

  1. attr.onsuccess = &DetectorBridge::DownloadSucceeded;

会得到:

  1. 从不兼容的类型‘void (mynamespace::MyClass::*)(emscripten_fetch_t*)’分配给‘void (*)(struct emscripten_fetch_t*)’。
英文:

I am working on a wasm project where I need to define a empscripten fetch callback in a C++ header file, because I need to update a member variable.
Can someone help me with how I define a callback function i C++, where I am able to update a local member variable?

In MyClass.CPP do I have the following method

  1. void MyClass::Register()
  2. {
  3. emscripten_fetch_attr_t attr;
  4. emscripten_fetch_attr_init(&attr);
  5. attr.onsuccess = DownloadSucceeded;
  6. attr.onerror = DownloadFailed;
  7. }

I have defined DownloadSucceeded and DownloadFailed in my header file.

  1. void DownloadSucceeded(emscripten_fetch_t* fetch)
  2. {
  3. printf("Finished downloading %llu bytes from URL %s.\n", fetch->numBytes, fetch->url);
  4. emscripten_fetch_close(fetch); // Free data associated with the fetch.
  5. m_unlocked = true;
  6. }
  7. void DownloadFailed(emscripten_fetch_t* fetch)
  8. {
  9. printf("Downloading %s failed, HTTP failure status code: %d.\n", fetch->url, fetch->status);
  10. emscripten_fetch_close(fetch); // Also free data on failure.
  11. m_unlocked = false;
  12. }

I get the following exception:

  1. reference to non-static member function must be called

From the above exception I tried to send a reference instead, but that didn't seem to work either. If some clever guy can explain why and how to solve this I would be grateful!

My naive reference example which does not work either:

  1. attr.onsuccess = &DetectorBridge::DownloadSucceeded;

Gives:

  1. assigning to 'void (*)(struct emscripten_fetch_t *)' from incompatible type 'void (mynamespace::MyClass::*)(emscripten_fetch_t *)'

答案1

得分: 1

Looking at the emscripten source, it appears that you need to perform something like this. You should save your MyClass pointer to a field designated by emscripten for this purpose.

  1. void MyClass::Register()
  2. {
  3. emscripten_fetch_attr_t attr;
  4. emscripten_fetch_attr_init(&attr);
  5. attr.onsuccess = DownloadSucceeded;
  6. attr.onerror = DownloadFailed;
  7. attr.userData = this; // save this object
  8. }

Then, when you receive the callback, use the saved pointer to modify your variables.

  1. void DownloadSucceeded(emscripten_fetch_t* fetch)
  2. {
  3. printf("Finished downloading %llu bytes from URL %s.\n",
  4. fetch->numBytes, fetch->url);
  5. static_cast<MyClass*>(fetch->userData)->m_unlocked = true; // get saved object
  6. emscripten_fetch_close(fetch); // Free data associated with the fetch.
  7. }

I'm ignoring the issue of access to the m_unlocked member variable, but if that is a concern, there are typical solutions available.

英文:

Looking at the emscriptem source it seems you need to do something like this, where you save your MyClass pointer to a field that emscriptem has designed for this purpose.

  1. void MyClass::Register()
  2. {
  3. emscripten_fetch_attr_t attr;
  4. emscripten_fetch_attr_init(&amp;attr);
  5. attr.onsuccess = DownloadSucceeded;
  6. attr.onerror = DownloadFailed;
  7. attr.userData = this; // save this object
  8. }

Then when you get the callback use that saved pointer to modify your variables

  1. void DownloadSucceeded(emscripten_fetch_t* fetch)
  2. {
  3. printf(&quot;Finished downloading %llu bytes from URL %s.\n&quot;,
  4. fetch-&gt;numBytes, fetch-&gt;url);
  5. static_cast&lt;MyClass*&gt;(fetch-&gt;userData)-&gt;m_unlocked = true; // get saved object
  6. emscripten_fetch_close(fetch); // Free data associated with the fetch.
  7. }

I'm ignoring the issue of access to the m_unlocked member variable, but if that is an issue there are the usual solutions.

huangapple
  • 本文由 发表于 2023年7月6日 15:34:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/76626488.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定