Emscripten(incoming分支)是否可取消导出函数自动添加前置下划线?
我刚好也遇到过类似的困扰,在折腾Emscripten导出WASM函数的时候,默认的前置下划线确实挺烦人的。结合我自己的实践和对incoming分支的了解,给你分享几个可行的方案,让导出的函数保持原名称:
1. 直接在代码里指定导出名称(最稳定)
这是我最常用的方法,完全不受编译选项的影响——给需要导出的函数加上__attribute__((export_name("你的原函数名")))属性,强制指定WASM里的导出名称。举个例子:
// C代码直接加属性就行 __attribute__((export_name("calc_sum"))) int calc_sum(int a, int b) { return a + b; } // 如果是C++代码,记得用extern "C"避免C++的名字修饰 extern "C" { __attribute__((export_name("cpp_print"))) void cpp_print(const char* msg) { // 函数逻辑 } }
这样编译出来的WASM里,导出的函数名就是你指定的calc_sum和cpp_print,不会有任何额外的下划线。
2. 用编译选项禁止名称修饰
在Emscripten的incoming分支里,你可以试试-s NO_NAME_MANGLE=1这个选项,它会禁止Emscripten对导出函数名做额外修改(包括加下划线)。配合EXPORTED_FUNCTIONS使用的时候要注意:EXPORTED_FUNCTIONS里得写编译器处理后的带下划线的名字,而NO_NAME_MANGLE会让最终WASM导出的是原名。比如:
emcc your_code.c -o output.js -s EXPORTED_FUNCTIONS=['_calc_sum'] -s NO_NAME_MANGLE=1
这样编译后,WASM里导出的就是calc_sum,而不是_calc_sum。
3. 给链接器传参数阻止demangle
Emscripten用的是LLVM的链接器,我们可以通过-s LINKER_FLAGS传递--no-demangle参数,让链接器保留函数的原始名称,避免自动添加下划线。比如你用EXPORT_ALL=1的场景:
emcc your_code.c -o output.js -s EXPORT_ALL=1 -s LINKABLE=1 -s LINKER_FLAGS="--no-demangle"
这个参数会让所有导出的函数都保持原来的名字,不会被加上前置下划线。
关于incoming分支的小提示
incoming是Emscripten的开发分支,偶尔会有选项变动,但上面这几个方法我最近测试过都是有效的。如果发现NO_NAME_MANGLE没生效,可以试试配合-s ABORT_ON_WASM_EXCEPTIONS=0(某些异常处理逻辑可能会影响名称导出),不过最稳妥的还是直接在代码里指定导出名称的方法。
最后可以用wasm2wat工具验证一下:把生成的.wasm转成文本格式,看看导出段的函数名是不是你想要的:
wasm2wat output.wasm -o output.wat
然后在output.wat里找(export "你的函数名" (func ...))的条目,确认名称正确就行。
内容的提问来源于stack exchange,提问作者sandthorn

