Webassembly从wasm调用JavaScript方法,即使用c ++代码

Tit*_*ito 4 javascript c++11 emscripten webassembly

我正在使用webassembly,到目前为止,我能够管理emscripten编译我的测试c ++项目到wasm文件em ++提供了我2个文件,即

mainTest.js mainTest.wasm

当我在我的html页面加载mainTest.js然后我得到一个名为" 模块 " 的Java脚本对象.

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

var myTestInteger = Module._callMyTestMethod();
Run Code Online (Sandbox Code Playgroud)

并从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
Run Code Online (Sandbox Code Playgroud)

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

function testExternMethod() {
  console.log("Hello from testExternMethod!" + )
}
Run Code Online (Sandbox Code Playgroud)

在这里我想从c ++调用JavaScript testExternJSMethod.

当我在Firefox中运行页面时,在调试器控制台中获得"-1".

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

我在例子中缺少什么?即在c ++中,我用extern关键字ie定义了方法

extern void testExternJSMethod();
Run Code Online (Sandbox Code Playgroud)

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

我相信我应该以某种方式将该java脚本方法以某种方式链接到模块,但我不知道如何. Module.asm给了我出口.哪种方法调用应该给我进口?因为我认为这个_testExternJSMethod()应​​该在某些导入方法中,ii无法弄清楚如何到达它.

Cli*_*int 9

我不完全确定您的用例,但您缺少能够使用您的功能的重要步骤testExternalJSMethod.你有两个选择:

选项1 - 图书馆

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

extern void testExternalJSMethod();
Run Code Online (Sandbox Code Playgroud)

2 - 创建一个名为的文件 myLibrary.js

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

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

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

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

<script async type="text/javascript" src="myLibrary.js"></script>
Run Code Online (Sandbox Code Playgroud)

5 - --js-library向emcc命令添加选项,并在相对路径之后立即添加myLibrary.js

emcc ... --js-library myLibrary.js
Run Code Online (Sandbox Code Playgroud)

选项2 - 传递指针

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

typedef void testExternalJSMethod()
Run Code Online (Sandbox Code Playgroud)

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

void passFnPointer(int ptr) {
    ((testExternalJSMethod*)ptr)();
}
Run Code Online (Sandbox Code Playgroud)

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

var fnPtr = Module.addFunction(function () {
    alert("You called testExternalJSMethod");
});
Run Code Online (Sandbox Code Playgroud)

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

var passFnPointer = Module.cwrap('passFnPointer', 'undefined', ['number']);
passFnPointer(fnPtr);
Run Code Online (Sandbox Code Playgroud)

5 - -s RESERVED_FUNCTION_POINTERS为emcc命令添加选项

emcc ... -s RESERVED_FUNCTION_POINTERS=10
Run Code Online (Sandbox Code Playgroud)

结论

完成其中一个选项中的所有步骤后,您将可以testExternalJSMethod通过c/c ++ 调用而无需使用myLibrary.jsLibraryManager


Col*_*inE 7

您是否尝试查看 Emscripten 文档?它有一整个关于与代码交互的部分,详细介绍了如何将 C/C++ 函数暴露给 JavaScript 并从 C/C++ 调用 JavaScript 函数。

Emscripten 提供了两种从 C/C++ 调用 JavaScript 的主要方法:使用 emscripten_run_script() 运行脚本或编写“内联 JavaScript”。

值得注意的是,Mozilla 文档详细介绍了普通的 WebAssembly,而 Emscripten 围绕 WebAssembly 添加了更多框架和工具,以便更轻松地移植大型 C/C++ 代码库。