我知道在Rust中调用C函数的一种方法是使用类似这样的东西:
extern "C" {
fn abs(input: i32) -> i32;
}
fn main() {
unsafe {
println!("abs(-3) = {}", abs(-3));
}
}
但是如何在Rust代码中调用一些汇编函数(位于.s
文件内的其他Rust文件所在的目录中)?
答案 0 :(得分:7)
这是在macOS上使用C x86_64调用约定的汇编函数。它不是段错误,所以它必须是正确的: - )
<强> Cargo.toml 强>
[build-dependencies]
cc = "1.0.3"
<强> build.rs 强>
extern crate cc;
fn main() {
cc::Build::new()
.file("add.S")
.compile("my-asm-lib");
}
<强> add.S 强>
.text
.globl _my_adder
_my_adder:
addq %rdi, %rsi
movq %rsi, %rax
ret
<强>的src / main.rs 强>
extern "C" {
fn my_adder(a: u64, b: u64) -> u64;
}
fn main() {
let sum = unsafe { my_adder(1, 2) };
println!("{}", sum);
}
要使用汇编功能,有两个主要部分:
Rust本身并不提供编译程序集文件的方法。相反,您必须使用计算机上已存在的C编译器来编译它们。最常见的做法是在cc crate中使用build script。
构建脚本会将您的程序集文件编译为静态库,并指示Cargo链接到库。
您必须确保汇编语法对您正在使用的C编译器有效。例如,MSVC和GCC使用不同的装配样式。您可能需要具有相同组装功能的多个副本才能处理不同的平台。
调用该函数高度依赖于调用约定。主要调用约定是 C调用约定,用extern "C"
或仅extern
表示。您可能还想使用#[link_name = "..."]
或#[no_mangle]
属性。
您还可以使用#[naked]
功能创建自己的自定义调用约定(请参阅RFC 1201)。然后根据调用约定,在调用之前/之后使用调用方的汇编代码。 这不适用于稳定的Rust 。
Rust 1.21.1支持许多其他调用约定:
cdecl,stdcall,fastcall,vectorcall,thiscall,aapcs,win64,sysv64,ptx-kernel,msp430-interrupt,x86-interrupt,Rust,C,system,rust-intrinsic,rust-call,platform-intrinsic,unadjusted
答案 1 :(得分:0)
如果您使用夜间生锈,则可以避免使用global_asm! macro使用自定义构建脚本。
一个简单的用法如下:
#[feature(global_asm)] ... global_asm!(include_str!("something_neato.s"));