#include #include #define Export __attribute__((visibility("default"))) __attribute__((used)) extern "C" struct MAData int iRetCode; int iBegin; double *pOut; MAData(int iInitSize) pOut = (double *)malloc(sizeof(double) * iInitSize); Export MAData* getMAData() { MAData* context = new MAData(3); context->iRetCode = 1; context->iBegin = 2; context->pOut[0] = 1.111; context->pOut[1] = 3.14985; context->pOut[2] = 99.551414; return context;

以上是c++代码,命名main.cpp,放置在项目文件夹web/js/scripts下, 使用emscripten编译,调用编译命令:

emcc main.cpp -o na.js -s WASM=1 -s EXTRA_EXPORTED_RUNTIME_METHODS="["ccall", "cwrap"]"

生成了na.wasm文件和na.js文件。

下载require.js加载模块,https://requirejs.org/docs/release/2.3.6/minified/require.js

命名require.js,放置到web/js目录下,用于加载na.js,并且在该目录下创建main.js:

define(function(require) {
    require('./scripts/na');

修改web/index.html,加载main.js:

<script src="js/require.js"></script>
<script>
    require(["js/main"])
</script>

至此,整个加载过程完毕。

启动web时,c++代码已经载入,通过flutter调用:

//获取js的全局模块和方法
js.JsObject Module = js.context['Module'];
var HEAP8 = Module['HEAP8'];
var HEAP32 = Module['HEAP32'];
var HEAP64 = Module['HEAPF64'];
//获取c++的getMAData方法函数,并且封装成dart函数
js.JsFunction _getMAData = Module.callMethod('cwrap', ['getMAData', '', []]);
int getMAData() {
  return _getMAData.apply([]);
//以下是调用过程,
 var ret = getMAData();//返回结构体指针地址
    var iRetCode= HEAP32[ret >> 2];//获取第一个变量值
    var iBegin= HEAP32[ret + 4 >> 2];//获取第二个变量值,因为int是4个自己,所以+4,‘>> 2’是HEAP32固定偏移量,具体原因可以不管
    var pOut= HEAP32[ret + 8 >> 2];//获取第三个变量值,该值是指针
    for (var i = 0; i < 3; i++) {
      print(HEAP64[(pOut + (i * 8)) >> 3]);
    }//获取pOut里的三个值,因为double类型是8个字节,所以每次遍历+8个字节, ‘>> 3’是固定HEAP64固定偏移量,可以不管

 至此调用过程结束。

参考文献:

https://www.cntofu.com/book/150/zh/ch2-c-js/ch2-07-ccall-cwrap.md

https://dev.to/kyorohiro/dart-and-c-how-to-ffi-and-wasm-5-structure-and-object-bjd