内联汇编调用Rust函数及调用约定相关技术问询
问题解答
结论
必须给函数h显式标记extern "C",仅通过汇编里的call sym h调用无法保证Rust编译器始终对h采用C调用约定,未来优化极可能引发未定义行为。
原因分析
- Rust的默认调用约定(未显式指定时)是未定义且不稳定的:编译器会根据版本、优化级别、目标平台自由调整参数传递方式、寄存器使用规则和栈帧布局,没有任何官方保证。当前代码能运行只是巧合,后续版本的激进优化(比如
-O3下的寄存器分配策略变更)完全可能破坏调用兼容性。 - 函数调用约定是独立属性:
g标记为extern "C"仅约束自身的调用规则,不会自动传递给它调用的h。汇编里的sym h只是获取h的地址,编译器不会因为g的约定就改变h的代码生成规则。 - 显式标记
extern "C"是唯一可靠的方式:给h加上unsafe extern "C"后,编译器会严格遵循目标平台的C调用约定生成代码(包括参数入栈/寄存器传递、返回值处理、调用者/被调用者栈帧责任等),无论g通过汇编怎么调用,都能保证符合约定,彻底避免未定义行为。
额外建议
即使当前两种写法都能运行,也必须保留extern "C"标记——这是唯一符合Rust语言规范的做法,能确保代码在未来编译器版本、不同优化级别下的稳定性。
内容的提问来源于stack exchange,提问作者Derek C.
相关产品推荐
相关产品推荐

