I just followed “The Rust Reference: 17. Application Binary Interface (ABI)” and “The Embedded Rust Book: 10.2 A little Rust with your C”
After then, I tried to expose Rust program to C as ABI.
foo.rs
:
// This is kept because of `#[used]`:
#[used]
static FOO: u32 = 123;
// This is removable because it is unused:
#[allow(dead_code)]
static BAR: u32 = 0;
// This is kept because it is publicly reachable:
pub static BAZ: u32 = 0;
// This is kept because it is referenced by a public, reachable function:
static QUUX: u32 = 0;
pub fn quux() -> &'static u32 {
&QUUX
}
// This is removable because it is referenced by a private, unused (dead) function:
static CORGE: u32 = 0;
#[allow(dead_code)]
fn corge() -> &'static u32 {
&CORGE
}
used
attributeThe attribute can only be applied to static
item.
This attribute tells compiler to keep this variable, even the variable isn’t used and is room for optimization in case of shared object output.
no_mangle
attributeName mangling is also calledd name decoration (by Wikipedia).
Name mangling append the variable/function name in the output.
The Rust compiler mangles symbol names differently than native code linkers expect, and this is why we need no_mangle
.
link_section
attributeThe attribute specifies the section of the object file that a function or static’s content will be placed into.
#[no_mangle]
#[link_section = ".example_section"]
pub static VAR1: u32 = 1;
export_name
attributeThis attribute specifies the name of the symbol that will be exported on a function or static.
#[export_name = "exported_symbol_name"]
pub fn name_in_rust() { }
$ rustc -O --emit=obj --crate-type=rlib foo.rs
$ nm -C foo.o
0000000000000000 R foo::BAZ
0000000000000000 r foo::FOO
0000000000000000 R foo::QUUX
0000000000000000 T foo::quux
-O
: Optimize the code. A synonym for -C opt-level=2.--emit-obj
: Generates a native object file. The default output filename is CRATE_NAME.o
..--crate-type=rlib
: A “Rust library” file will be produced. This is used as an intermediate artifact and can be thought of as a “static Rust library”..Tried with another --crate-type
:
rustc -O --emit=obj --crate-type=staticlib foo.rs
The result:
➜ nm -C foo.o
0000000000000000 r foo::FOO
➜ objdump -D -C --demangle foo.o
foo.o: file format elf64-x86-64
Disassembly of section .rodata._ZN3foo3FOO17hbcfcd8524a307ff1E:
0000000000000000 <foo::FOO>:
0: 7b 00 jnp 2 <foo::FOO+0x2>
...
Hex 7b
is 123
.
Now, I tried the second reference.
https://docs.rust-embedded.org/book/interoperability/rust-with-c.html
AS of Jan. 2022, C++ has no stable ABI for the Rust compiler to target, so we try C.
lib.rs
:
static FOO: usize = 123;
#[no_mangle]
#[export_name = "mylib"]
pub extern "C" fn rust_adder(a: &usize, b: &usize) -> usize {
*a + *b + FOO
}
test.c
:
#include <stdio.h>
int mylib(int *a, int *b);
int main() {
int i = 1000;
int j = 10000;
int result = mylib(&i, &j);
printf("Result: %d", result);
}
Compile, link, and execute!!:
rustc -O --emit=obj --crate-type=staticlib lib.rs
gcc -o rust_with_c test.c lib.o
./rust_with_c
Result: 11123