Rust外部模块导入问题:如何完成tests9.rs测试任务?
解决Rust tests9.rs练习问题:导出函数并设置别名
核心要求
让测试代码能调用Foo模块中的my_demo_function,同时让my_demo_function_alias成为该函数的别名,仅添加两行属性,不能修改现有代码逻辑。
解决方案
需要添加的两行属性分别作用于两个位置:
- 给
Foo模块内的my_demo_function添加#[no_mangle],禁用Rust默认的符号混淆,让外部能通过函数名找到它; - 给
extern块内的my_demo_function_alias添加#[link_name = "my_demo_function"],指定它链接到my_demo_function的符号,作为别名。
修改后的完整代码
// tests9.rs // // Rust is highly capable of sharing FFI interfaces with C/C++ and other statically compiled // languages, and it can even link within the code itself! It makes it through the extern block, just like the code below. // // The short string after the `extern`keyword indicates which ABI the externally imported // function would follow. In this exercise, "Rust" is used, while other variants exists like // "C" for standard C ABI, "stdcall" for the Windows ABI. // // The externally imported functions are declared in the extern blocks, with a semicolon to // mark the end of signature instead of curly braces. Some attributes can be applied to those // function declarations to modify the linking behavior, such as #[link_name = ".."] to modify the actual symbol names. // // If you want to export your symbol to the linking environment, the`extern`keyword can // also be marked before a function definition with the same ABI string note. The default ABI // for Rust functions is literally "Rust", so if you want to link against pure Rust functions, // the whole extern term can be omitted. // // Rust mangles symbols by default, just like C++ does. To suppress this behavior and make // those functions addressable by name, the attribute #[no_mangle] can be applied. // // In this exercise, your task is to make the testcase able to call the`my_demo_function`in // module Foo. the`my_demo_function_alias`is an alias for`my_demo_function`, so the two // line of code in the testcase should call the same function. // // You should NOT modify any existing code except for adding two lines of attributes. // I AM NOT DONE extern "Rust" { fn my_demo_function(a: u32) -> u32; // 新增:给别名指定链接的符号名 #[link_name = "my_demo_function"] fn my_demo_function_alias(a: u32) -> u32; } mod Foo { // No `extern` equals `extern "Rust"`. // 新增:禁用符号混淆,让外部能找到这个函数 #[no_mangle] fn my_demo_function(a: u32) -> u32 { a } } #[cfg(test)] mod tests { use super::*; #[test] fn test_success() { // The externally imported functions are UNSAFE by default // because of untrusted source of other languages. You may // wrap them in safe Rust APIs to ease the burden of callers. // // SAFETY: We know those functions are aliases of a safe // Rust function. unsafe { my_demo_function(123); my_demo_function_alias(456); } } }
原理说明
#[no_mangle]:Rust默认会对函数名进行符号混淆(类似C++),添加这个属性后,函数会以原始名称my_demo_function暴露给链接器,让外部的extern声明能找到它;#[link_name = "my_demo_function"]:告诉Rust,这个my_demo_function_alias的声明实际要链接到符号my_demo_function,相当于给原函数起了一个别名,因此两个外部调用最终都会指向Foo模块里的同一个函数。
内容的提问来源于stack exchange,提问作者herimone tommie
相关产品推荐
相关产品推荐

