#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