asm.js模块.调用/模块.cwrap回调
asm.js Module.ccall / Module.cwrap callback
我在c++中有一些回调函数,我想在用emscripten编译后在javascript中重新创建。
有人知道如何调用那些使用call或cwrap?
谢谢!
我使用的技术是将指针转换为unsigned int(技术上,uint32_t),然后将其传递给JS。当我准备进行回调时,我将值传递回c++,将其转换回函数指针,然后调用相关的函数。
这些都可以自动完成;例如,您可以设置回调类,使其具有一个基类,在调用重定向到正确派生类的虚函数之前,所有指针都转换为基类(在我的情况下,我使用它来处理参数和返回类型)。
我很乐意帮你写一些代码。我正在做一个名为Empirical的项目,这将是一个主要面向将科学软件移植到网络的头文件库。它仍处于积极的早期开发阶段,但你可能会发现一些有用的部分。
https://github.com/mercere99/Empirical emp::JSWrap()
是一个接受std::function对象并返回uint32_t
的函数。你可以在这里找到它的定义:https://github.com/mercere99/Empirical/blob/master/emtools/JSWrap.h它应该正确处理基本参数和返回类型和std::string
,但我正在努力扩展。如果您只从项目中获取一些文件,请注意JSWrap确实包含了一些其他文件,但不是太多。
您需要担心的另一个相关文件是library_emp.js (https://github.com/mercere99/Empirical/blob/master/emtools/library_emp.js),它定义了emp.Callback()
,可以在JS端使用。
要将这两个文件集成到程序中,您需要:
- 添加到你的c++代码
#include "JSWrap.h"
和#include "init.h"
(可能有额外的路径信息) 添加到您的编译: - 在使用任何回调之前,请在c++端运行
emp::Initialize();
。 - 通过调用
uint32_t fun_id = emp::JSWrap(FunctionToBeWrapped);
包装你正在使用的函数,它将返回一个函数ID值,你可以传递给JS。或者,你可以调用uint32_t fun_id = emp::JSWrap(FunctionToBeWrapped, "JS_Function_Name");
,它会用指定的名字为你创建一个JS函数。 - 在JS中,你可以通过使用
emp.Callback(id, parameters)
触发回调来提供指定的函数ID -或者-如果你使用emp.JS_Function_Name(parameters...)
,你可以使用提供的名称,它将回调原始函数。任何返回值都将被返回。
--js-library ../../emtools/library_emp.js
让我知道这是否有帮助!在JSWrap.h的顶部还有一些文档,测试文件位于https://github.com/mercere99/Empirical/tree/master/UTests/emtools(包括一个Makefile,一个名为JSWrap的代码文件)。
编辑:下面是一个示例代码,将函数对象的指针发送给JS,然后从JS调用它。
#include <emscripten.h>
#include <functional>
// A couple of possible callbacks, all with the same signature.
double Times2(double val) { return val * 2; }
double Plus7(double val) { return val + 7; }
// A function callback from JS that takes a callback id and an arg and does the callback.
extern "C" {
double Callback_dd(uint32_t cb_id, double val) {
auto * fun_ptr = reinterpret_cast<std::function<double(double)>*>(cb_id);
return (*fun_ptr)(val);
}
}
int main() {
// Pick the function you want to run
auto fun = std::function<double(double)>(Times2);
// auto fun = std::function<double(double)>(Plus7);
// Convert a function pointer to a uint32_t.
// Note double casting to first convert it to a number and then reduce it to 32-bits.
// Using reintepret_cast would be better, but looked confusing with the double cast.
uint32_t cb_id = (uint32_t) (long long) &fun;
// The following code passed the callback ID to JavaScript. The JS code then uses the
// ID to call back the original function.
EM_ASM_ARGS({
Callback_dd = Module.cwrap('Callback_dd', 'number', ['number']);
var x = 12.5;
alert('Result: fun(' + x + ') = ' + Callback_dd($0, x));
}, cb_id);
}
注意,如果你打算在main()结束后进行回调,你需要确保你所调用的函数将持续存在。
要编译这段代码,将其放入一个文件中(我们将其命名为callback_test.cc),然后从命令行运行:em++ -s EXPORTED_FUNCTIONS="['_Callback_dd', '_main']" -std=c++11 callback_test.cc -o callback_test.html
你现在应该能够在浏览器中打开callback_test.html,它将从JS中调用你传递给它的c++函数指针。
在这种情况下,您需要提前知道函数签名,但是正如我上面提到的,您可以使用一个更复杂的回调来记住签名。
- 尝试导入pybind-opencv模块时出现libgtk错误
- 为什么当我解模块化时,这个C++代代码"效率较低"?
- 如果C++对象的类在另一个boost模块中声明,如何使用boost将指向该对象的指针返回到python
- 内联如何影响模块接口中的成员函数
- C++返回 Numpy 数组的 Python 扩展模块
- 当我尝试加载内核模块时,如何修复C++中的这个 malloc() 错误?
- 如何从线程中的不同模块调用函数?
- 如何使用 soong 命名空间来有条件地编译模块
- asn1c 不会从 asn.1 模块中提取八位字节字符串的默认值
- CMake - 模块 + 库混淆
- 特征 LLT 模块给出不正确的结果?
- 枚举进程模块在有效句柄上返回无效句柄
- 在 python 模块中导入子模块时PyImport_Import失败
- 将 PCL 链接到 Cython C++ 模块
- 即使直接从官方示例中复制,也找不到未知类型名称QML_ELEMENT和 QML 模块
- 电源功能模块化操作
- 如何告诉本机节点模块所需的dll存储在哪里?
- 如何为模块化应用程序实现C++插件系统
- C++ Python 模块在 Blender 中崩溃,但在 Python 控制台中不会崩溃
- asm.js模块.调用/模块.cwrap回调