嵌入传递 lambda 函数作为回调参数
Posted
技术标签:
【中文标题】嵌入传递 lambda 函数作为回调参数【英文标题】:Embind pass lambda function as callback parameter 【发布时间】:2016-04-02 08:49:46 【问题描述】:我想创建一个函数来计算一些东西。并在完成后调用回调函数。
void calculate(int param1, ..., std::function<void(void)> callback)
//code...
callback();
函数的绑定是使用Embind
创建的:
EMSCRIPTEN_BINDINGS(my_module)
function("calculate", &calculate);
但如果我尝试调用 Module.calculate(0, ..., function()/*...*/)
我会收到此错误:
UnboundTypeError: Cannot call calculate due to unbound types: NSt3__18functionIFvvEEE
【问题讨论】:
在 emscripten GitHub 上有一个关于这个的线程,看起来可以使用 embind。 github.com/kripken/emscripten/issues/4927 【参考方案1】:我不确定这是否是唯一的方法,但要从 Js -> C++ 传递回调,我必须这样做
不使用std::function
,而是使用原始函数指针
使用 Runtime.addFunction
获取 javascript 函数的 C++ 函数指针,并将其传递到 C++ 世界,而不是尝试直接传递 Javascript 函数。
不使用EMBIND
,而是使用cwrap
/ccall
API。
对于您的示例,稍微简化接口以便仅从 JS -> C++ 传递回调,C++ 可能如下所示:
extern "C"
EMSCRIPTEN_KEEPALIVE
void calculate(void (*callback)())
callback();
创建回调函数指针的 Javascript 可能如下所示
var callbackPointer = Module.Runtime.addFunction(function()
console.log('In the callback');
);
并调用函数,传递指针(作为“数字”):
Module.ccall('calculate', 'number', ['number'], [callbackPointer]);
然后编译确保为函数指针保留空间:
em++ app.cpp -s RESERVED_FUNCTION_POINTERS=1 -o app.js
【讨论】:
感谢您的帮助。但是如果我的calculate
函数是一个类方法,并且我想一次有更多实例呢?
您应该能够创建 C++ 对象并将指向它们的原始指针传递给 Javascript。然后,静态calculate
函数可以与回调的函数指针一起获取指向这些对象之一的指针。然后它将取消引用对象指针,并调用其实例calculate
方法。【参考方案2】:
您现在可以这样做:
void calculate(int param1, ..., emscripten::val callback)
callback();
EMSCRIPTEN_BINDINGS
没有改变。
回调甚至可以接受参数,只要它们是受支持/声明的类型(例如,如果您将 std::vector<blah>
参数传递给回调,请确保您已使用 register_vector<blah>()
。)
【讨论】:
这个是最方便的方式,我写个样例可以参考sdk_web_assembly以上是关于嵌入传递 lambda 函数作为回调参数的主要内容,如果未能解决你的问题,请参考以下文章