Emscripten如何向C++函数传递带两个参数的JS回调函数
解决方案
方案1:直接使用emscripten::val接收JS回调
你之前认为emscripten::val仅支持无参回调是用法错误,该类型可以直接接收任意JS函数,并且支持传入任意数量参数调用:
- 先引入必要头文件
#include <emscripten/val.h>
- 修改C++函数签名与内部逻辑
void generate_effect(const std::string& file_name, const std::string& out_dir, emscripten::val callback) { // 原有业务逻辑不变 bool is_success = ...; // 业务逻辑返回的执行结果 std::string error_msg = ...; // 业务逻辑返回的提示信息 // 执行回调,参数会自动转换为JS对应的布尔、字符串类型 callback(is_success, error_msg); }
- 绑定代码无需额外调整,保持原有写法即可
EMSCRIPTEN_BINDINGS(main) { function("generateEffect", &generate_effect); }
JS侧调用方式就是你预期的写法,无需额外修改。
方案2:std::function + optional_override 实现(符合无原始指针开发规范)
如果要求C业务代码不能依赖emscripten相关类型、禁止使用原始函数指针,可以用该方案,C侧仅使用标准库的std::function:
- 先修改C++函数签名,用std::function作为回调参数
#include <functional> #include <string> void generate_effect(const std::string& file_name, const std::string& out_dir, std::function<void(bool, const std::string&)> callback) { // 原有业务逻辑不变 bool is_success = ...; std::string error_msg = ...; // 直接调用std::function即可 callback(is_success, error_msg); }
- 修改绑定代码,用optional_override完成JS函数到std::function的自动转换
#include <emscripten/bind.h> #include <emscripten/val.h> EMSCRIPTEN_BINDINGS(main) { function("generateEffect", emscripten::optional_override( [](const std::string& file_name, const std::string& out_dir, emscripten::val js_callback) { // 将JS函数包装为std::function传入业务逻辑 auto wrapper = [js_callback](bool success, const std::string& msg) { js_callback(success, msg); }; generate_effect(file_name, out_dir, wrapper); } )); }
注意事项
- 如果需要在C++侧异步持有回调(比如放到异步队列中延迟执行),需要调用
js_callback.persist()延长JS函数的生命周期,避免被JS垃圾回收机制回收导致调用崩溃 - 回调参数支持基础类型自动转换:C的bool对应JS布尔,C的std::string/const char*对应JS字符串,数值类型也可以自动匹配
内容的提问来源于stack exchange,提问作者Alexander
相关产品推荐
相关产品推荐

