将JS函数传递给Emscripten生成的代码

Lór*_*tér 17 javascript emscripten

我有一段C++代码通过Emscripten转换为JavaScript.我希望转换后的C++代码能够回调调用它的JavaScript代码.就像是:

JavaScript的:

function callback(message) {
    alert(message);
}

ccall("my_c_function", ..., callback);
Run Code Online (Sandbox Code Playgroud)

C++:

void my_c_function(whatever_type_t *callback) {
    callback("Hello World!");
}
Run Code Online (Sandbox Code Playgroud)

这有可能吗?

Dan*_*lig 15

我相信接受的答案有点过时了.

请参阅"与代码交互"emscripten教程中的此项目符号.

例如C:

void invoke_function_pointer(void(*f)(void)) {
  (*f)();
}
Run Code Online (Sandbox Code Playgroud)

JS:

var pointer = Runtime.addFunction(function() { 
  console.log('I was called from C world!'); 
});
Module.ccall('invoke_function_pointer', 'number', ['number'], [pointer]);
Runtime.removeFunction(pointer);
Run Code Online (Sandbox Code Playgroud)

通过这种方式,C代码不需要知道它被转换为JS,并且所需的任何桥接都可以完全由JS控制.

(代码入侵消息编写器;可能包含错误)


abe*_*ier 10

在Emscripten中经常做的事情是将强类型映射到简单类型.

JS:

function callback(message) {
    alert(message);
}

var func_map = {
    0: callback
};

// C/C++ functions get a _ prefix added
function _invoke_callback(callback_id, text_ptr) {
    func_map[callback_id](Pointer_stringify(text_ptr));
}

ccall("my_c_function", ..., 0);
Run Code Online (Sandbox Code Playgroud)

C++:

// In C/C++ you only need to declare the func signature and
// make sure C is used to prevent name mangling
extern "C" void invoke_callback(int callback_id, const char* text);

void my_c_function(int callback_id) {
    invoke_callback( callback_id, "Hello World!" );
}
Run Code Online (Sandbox Code Playgroud)

当然,您可以添加一些胶水代码,这样就可以非常无缝.

  • +1提及避免C++名称修改. (3认同)

Tar*_*aut 7

有一种通过embind实现您的要求的新方法。

考虑下面的C ++代码。

#include <emscripten/bind.h>
using namespace emscripten;

void cbTest(emscripten::val cb)
{
    cb();
}

EMSCRIPTEN_BINDINGS(my_module) {
    function("cbTest", &cbTest);
}
Run Code Online (Sandbox Code Playgroud)

cbTest C ++函数采用emscripten :: val。这可以是任何对象。对我们来说,这是一个函数对象。这就是从JS调用它的方式

var cbFunc = function() {
    console.log("Hi, this is a cb");
}

Module.cbTest(cbFunc);
Run Code Online (Sandbox Code Playgroud)

PS此api仍在构建中。