WebAssembly从wasm调用JavaScript方法,即在C ++代码中调用

时间:2017-11-12 11:06:40

标签: javascript c++11 emscripten webassembly

我正在玩WebAssembly,到目前为止我能够管理emscripten将我的测试C ++项目编译为wasm文件 em ++为我提供了2个文件,即

mainTest.js mainTest.wasm

当我在html页面中加载mainTest.js时,我得到一个名为的JavaScript对象 "的模块"

我确实找到了如何从javascript调用C ++ / wasm方法,例如:

var myTestInteger = Module._callMyTestMethod();

并从中读取字符串 的 Module.wasmMemory.buffer ,但我不明白如何从C ++代码调用JavaScript。

即。我希望能够做到这样的事情:

#ifdef __cplusplus
extern "C" {
#endif
extern void testExternJSMethod();

int main() 
{
    cout << " Hello From my Test1 !" << endl;

    testExternJSMethod();
    return 0;
}
int EMSCRIPTEN_KEEPALIVE callMyTestMethod(){
    return 26;
}
#ifdef __cplusplus
}
#endif

和我在另一个名为utils.js的js文件中加载的我的js方法testExternMethod

function testExternMethod() {
  console.log("Hello from testExternMethod!" + )
}

这里我想从C ++调用JavaScript testExternJSMethod。

当我在Firefox中运行页面时,获取&#34; -1&#34;在调试器控制台中。

那么我在这种情况下缺少什么?不幸的是,Mozilla文档仅提供了那些S表达式而不是C ++的示例。

我在示例中缺少什么?在C ++中,我使用extern关键字定义了该方法,即

extern void testExternJSMethod();

但我觉得这不是我必须做的全部。

我相信我应该以某种方式将JavaScript方法以某种方式链接到模块,但我不知道如何。 Module.asm 为我提供 exports 。哪种方法调用应该给我导入?因为我认为这个_testExternJSMethod()应该在某些导入方法中,所以我无法弄清楚如何实现它。

2 个答案:

答案 0 :(得分:8)

我不确定您的用例,但您错过了能够使用您的函数testExternalJSMethod的重要步骤。你有两个选择:

选项1 - 库

1 - 用c / c ++定义你的函数。

extern void testExternalJSMethod();

2 - 创建名为myLibrary.js

的文件

3 - 需要使用以下代码将JS函数添加到库文件中的LibraryManager

function makeAlert(text) {
    alert(text);
}

if (typeof mergeInto !== 'undefined') mergeInto(LibraryManager.library, {
    testExternalJSMethod: function() {
        makeAlert("Hello world");
    }
});

4 - 如果testExternalJSMethod取决于其自身范围之外的任何内容(例如,上面的makeAlert),请务必在html页面中包含该脚本

<script async type="text/javascript" src="myLibrary.js"></script>

5 - 向emcc命令添加选项--js-library,并在myLibrary.js

的相对路径后立即添加
emcc ... --js-library myLibrary.js

选项2 - 传递指针

1 - 在c / c ++中定义你的javascript函数类型

typedef void testExternalJSMethod()

2 - 无论你想在哪里使用这个函数,都接受一个int参数,它将是函数指针,并将指针强制转换为你的函数

void passFnPointer(int ptr) {
    ((testExternalJSMethod*)ptr)();
}

3 - 使用emscripten的addFunction()并存储其返回值(指针用c / c ++)

var fnPtr = Module.addFunction(function () {
    alert("You called testExternalJSMethod");
});

4 - 使用步骤3中存储的指针值传递给我们的函数passFnPointer

var passFnPointer = Module.cwrap('passFnPointer', 'undefined', ['number']);
passFnPointer(fnPtr);

5 - 将选项-s RESERVED_FUNCTION_POINTERS添加到您的emcc命令

emcc ... -s RESERVED_FUNCTION_POINTERS=10

答案 1 :(得分:4)

Have you tried looking at the Emscripten documentation? It has a whole section on interacting with code that details how to expose C / C++ functions to JavaScript and call JavaScript functions from C / C++.

Emscripten provides two main approaches for calling JavaScript from C/C++: running the script using emscripten_run_script() or writing “inline JavaScript”.

It is worth noting that the Mozilla documentation details plain WebAssembly, whereas Emscripten adds a lot more framework and tooling around WebAssembly in order to make it easier to port large C / C++ codebases.