参考文档:
4.3 使用C接口导出C++对象-C/C++面向WebAssembly编程
WebAssembly技术_JS调用C函数示例_传递参数、方法导出_DS小龙哥的博客-CSDN博客
- 单个lib的调用方法
1.1 单个lib的编译和链接方法
# 把vs的工程转换成cmake工程:(cmake-converter python里面的类似于pip的工具)
cmake-converter -s D:\work\WASM\WASM\Code\path\to\Calc.sln
# 执行cmake,生产.a的静态库:
cd /d D:\work\WASM\WASM\Code\path\to\
## 需要修改
emcmake cmake
## emcmake make_出错,mingw32_ok
emcmake make
mingw32-make
# 生产js和wasm文件:
cd /d D:\work\WASM\WASM\Code\path\to\Calc
emcc -s "EXPORTED_FUNCTIONS=['_fnCalcPlus']" libCalc.a -o libCalc.js
# serve要安装:
npm install -g serve
#运行结果展示:
1.2 几种常见
函数的调用方法
1.2.1 基本数据类型和调用方法
(1)C/C++链接库代码:
DLL_PUBLIC int fnCalcPlus2(int a, int b);
(2)前端调用代码:
console.log('1+100=:',Module._fnCalcPlus2(1,100));
1.2.2 js传数组到c/c++
(1)C/C++链接库代码:
DLL_PUBLIC int* fnIntArray(int *buff);
(2)前端调用代码:
var buff=_malloc(50) //申请空间
var out_p=_fnIntArray(buff) //调用函数
if (out_p == 0) { //打印结果
console.log('int_array return null')
return;
}
var str = '';
for (var i = 0; i < 10; i++) {
str += Module.HEAP32[(out_p >> 2) + i];
str += ' ';
}
console.log(str);
_free(buff) //释放空间
1.2.3 js传入c/c++的字符串(中文乱码问题)
(1)C/C++链接库代码:
DLL_PUBLIC char* fnStrCpy(char *str); // 中文乱码- 不区分平台的字符转换方案;
DLL_PUBLIC void fnStrPrint(char *str);
- 前端调用代码:
function runStrcpy(){
var buff=_malloc(500) //申请空间
var buff1=Module._fnStrCpy(buff)
//c不转成utf,中文会乱码;
console.log('Strcpy UTF8ToString:',UTF8ToString(buff1));
// c/c++里面是ASCII的中文也是乱码;
console.log('Strcpy AsciiToString:', AsciiToString(buff1));
_free(buff) //释放空间
}
function runStrPrt()
{
//申请空间,存放字符串
var varStr = "from js test js传递给C代码"
var ptr1 = allocate(intArrayFromString(varStr), ALLOC_NORMAL);
//传递给C代码
_fnStrPrint(ptr1)
}
- 注意事项:
从js传入c/c++的字符串,需要链接运行时函数;这些函数可以在unexportedRuntimeSymbols 里面找到;增加的链接命令如下:
-s EXPORTED_RUNTIME_METHODS="['allocate','UTF8ToString','intArrayFromString']"
1.2.4 js传入64位的整数,返回值有bug
(1)C/C++链接库代码:
DLL_PUBLIC int64_t i64_add(int64_t a, int64_t b); // 64位支持有问题;
(2)前端调用代码:
console.log('64位返回值问题:', Module._i64_add(0xFFFFFFFE,0x7FFFFFFF, 1, 0));
(3)原因分析
bug 导出到js会变成: int32_t func(int32_t a_lo, int32_t a_hi, int32_t b_lo, int32_t b_hi)
1.2.5 js获取c++对象和调用对象的方法;
(1)C/C++链接库代码:
DLL_PUBLIC SomeClass *getSomeClass(int a); // 获取c++对象;
DLL_PUBLIC void delSomeClass(SomeClass *obj);
DLL_PUBLIC int fnSomeClassMethodAdd(SomeClass *obj, int a);
(2)前端调用代码:
var s = Module._getSomeClass(200);
console.log('class add: 200+100=',Module._fnSomeClassMethodAdd(s, 100));
Module._delSomeClass(s);
- 多个lib的调用,c++库依赖其它库
- 多个lib的调用编译和链接方法
(1)libtoClassTest.js 调用libtoClassTest.a里面的导出函数fnCalcPlus2;
(2)libtoClassTest.a里面的导出函数fnCalcPlus2调用libLib1Demo.a的fnCalcPlusFromLibDemo函数;
(3) emcc - s "EXPORTED_FUNCTIONS=['_fnCalcPlus2']" - s EXPORTED_RUNTIME_METHODS = "['allocate']" libtoClassTest.a libLib1Demo.a - o libtoClassTest.js
DLL_PUBLIC int fnCalcPlus2(int a, int b);
2.2 多个lib调用遇到的问题
2.2.1 emcc提示错误找不到fnCalcPlusFromLibDemo函数;
原因:(1) sln工程里面生成的是Lib1Demo.lib,而cmake里面是libLib1Demo.a;
(2)emcc没有链接libLib1Demo.a库;