概述
从官方文档Dynamic-Linking可以了解到,动态链接主要是将wasm文件包拆分为一个主模块(Main module)和若干个子模块(Side module)。这个看起来和c的动态库机制差不多,但还是有一个差异值得注意
-
Main modules, which have system libraries linked in.
-
Side modules, which do not have system libraries linked in.
wasm的子模块是不包含系统库调用的,依赖于主模块所依赖的系统库,c平台的动态库是可以自动调用所需系统库的,所以在使用wasm的动态链接方案时,需要注意主模块系统依赖是否完善。
和c平台一样,wasm的动态库链接支持编译时自动链接(加载主模块时自动加载子模块)和运行时加载(在主模块中进行动态控制加载)
编译时链接
先准备子模块
|
|
主模块
|
|
- 将side模块代码用 -sSIDE_MODULE链接参数进行链接, 这里假设输出了side.wasm
|
|
- 将main模块代码用-sMAIN_MODULE编译参数进行链接,同时指定side模块的文件 , 如下代码
|
|
编译完成后,运行
|
|
运行时链接
而运行时链接,需要在主模块里面增加加载动态库的逻辑
|
|
编译字库的命令还是没有区别
|
|
编译主模块命令有所变化,需要将side.wasm文件通过preload file参数预先存放在wasm的虚拟文件系统
|
|
编译完成后,文件目录下有以下文件
|
|
编译完成后,运行
|
|
结果是一致的。
注意事项
- wasm的子模块是不包含系统库调用的,依赖于主模块所依赖的系统库,c平台的动态库是可以自动调用所需系统库的,所以在使用wasm的动态链接方案时,需要注意主模块系统依赖是否完善。
- 使用纯c接口导出,避免cpp奇怪的符号问题
|
|
- 多个子模块时,注意使用编译器参数fvisibility控制符号的导出,避免同名函数符号的冲突
visibility用于设置动态链接库中函数的可见性,将变量或函数设置为hidden,则该符号仅在本so中可见,在其他库中则不可见。g++在编译时,可用参数-fvisibility指定所有符号的可见性(不加此参数时默认外部可见,参考man g++中-fvisibility部分);若需要对特定函数的可见性进行设置,需在代码中使用__attribute__设置visibility属性。编写大型程序时,可用-fvisibility=hidden设置符号默认隐藏,针对特定变量和函数,在代码中使用__attribute__ ((visibility(“default”)))另该符号外部可见,这种方法可用有效避免so之间的符号冲突。
参考:
- https://github.com/WebAssembly/design/blob/main/DynamicLinking.md
- https://stackoverflow.com/questions/63150966/how-to-dlopen-a-side-module-larger-than-4kb