Unexpected behavior of `extern "Rust"`

From the Rust Reference:

  • extern "Rust" -- The default ABI when you write a normal fn foo() in any Rust code.

And I write a little code to test this.

Version

platform: macOS 10.15

rust compiler: 1.41.0

Code

First, I write a library libtest

// test/src/lib.rs
pub fn from_lib(a: isize, b:isize) -> isize {
    a + b
}

In Cargo.toml, I set the crate-type to be dylib:

[lib]
name = "test"
crate-type = ["dylib"]

Then in another project extern_test, I use the extern block to use this function:

// extern_test/src/main.rs
extern "Rust" {
    fn from_lib(a: isize, b: isize) -> isize;
}

fn main() {
    let a = unsafe {
         from_lib(1, 2)
    };
}

And in build.rs (reference: The Cargo Book):

// extern_test/build.rs
fn main() {
    println!("cargo:rustc-link-lib=test");
    println!("cargo:rustc-link-search=crate=/path/to/directory/of/test");
}

Output

When I build this project, the linker generates an error:

Undefined symbols for architecture x86_64:
            "_from_lib"

This is the default C ABI in my platform, so I add #[no_mangle] above the from_lib function in libtest:

// test/src/lib.rs
#[no_mangle]
pub fn from_lib(a: isize, b:isize) -> isize {
    a + b
}

Then the project can be successfully built.

Question

As saying in the rust reference, I don't need to add #[no_mangle] macro, since extern "Rust" is the default ABI when you write a normal fn foo() in any Rust code. But the output is not expected.

Function calling convention and name mangling are different topics. Calling convention is about how to pass arguments and receive return value when calling this function, and name mangling is about what string will be placed on the symbol table to let linker find this function/statics.

4 Likes

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.