如何从Rust可执行文件导出符号?

时间:2017-05-01 01:05:30

标签: rust

我正在尝试从Rust可执行文件中导出符号:

#[allow(non_upper_case_globals)]
#[no_mangle]
pub static exported_symbol: [u8; 1] = *b"\0";

fn main() {
    println!("Hello, world!");
}

exported_symbol似乎未被生成的二进制文件导出:

$ cargo build
$ nm ./target/debug/test_export| grep exported_symbol

另一方面,如果我使用相同的源构建库,则会导出符号:

$ rustc --crate-type cdylib src/main.rs
$ nm libmain.so| grep exported_symbol
0000000000016c10 R exported_symbol

我在Linux x86-64上使用Rust 1.18.0。

2 个答案:

答案 0 :(得分:3)

您可以将链接器选项传递给rustc,例如:

$ rustc src/main.rs --crate-type bin -C link-args=-Wl,-export-dynamic
$ nm main|grep export
00000000000d79c4 R exported_symbol

你可能想把它放在.cargo/config的挡风板中:

[target.x86_64-unknown-linux-gnu]
rustflags = [ "-C", "link-args=-Wl,-export-dynamic" ]

答案 1 :(得分:1)

我建议在.cargo/config文件而不是上面的文件中

[build]
rustflags = ["-C", "link-args=-rdynamic"]

-rdynamic具有更高的可移植性。特别是,它可以在Linux和MacOS上使用。

此外,在当前的Rust / LLVM版本中,除非实际使用符号,否则链接程序很有可能将其删除。

为避免这种情况,应调用引用导出函数的伪函数(在任何时间点,例如main函数中)。

此类功能的示例可能是:

pub fn init() {
    let funcs: &[*const extern "C" fn()] = &[
        exported_function_1 as _,
        exported_function_2 as _,
        exported_function_3 as _      
    ];
    std::mem::forget(funcs);
}

当然,导出的函数应具有#[no_mangle]属性:

#[no_mangle]
pub extern "C" fn exported_function_1() {
  // ...
}