gpt4 book ai didi

c - Rust 和 C 与最小程序和 no_std 的链接问题

转载 作者:太空狗 更新时间:2023-10-29 15:17:33 25 4
gpt4 key购买 nike

我正在尝试使用 GCC 6.1.0 和 rustc 1.11 在 Windows 中使用 C 语言构建一个调用 Rust 函数的最小程序,最好使用 #![no_std] 编译。 0-nightly (bb4a79b08 2016-06-15) x86_64-pc-windows-gnu。这是我首先尝试的:

ma​​in.c

#include <stdio.h>

int sum(int, int);

int main()
{
printf("Sum is %d.\n", sum(2, 3));
return 0;
}

sum.rs

#![no_std]
#![feature(libc)]
extern crate libc;

#[no_mangle]
pub extern "C" fn sum(x: libc::c_int, y: libc::c_int) -> libc::c_int
{
x + y
}

然后我尝试运行:

rustc --crate-type=staticlib --emit=obj sum.rs

但是得到了:

error: language item required, but not found: `panic_fmt`
error: language item required, but not found: `eh_personality`
error: language item required, but not found: `eh_unwind_resume`
error: aborting due to 3 previous errors

好的,所以其中一些错误与 panic unwinding 有关。我发现了一个用于移除展开支持的 Rust 编译器设置,-C panic=abort。使用它,关于 eh_personalityeh_unwind_resume 的错误消失了,但 Rust 仍然需要 panic_fmt 函数。所以我在 the Rust docs 找到了它的签名,然后我将其添加到文件中:

sum.rs

#![no_std]
#![feature(lang_items, libc)]
extern crate libc;

#[lang = "panic_fmt"]
pub fn panic_fmt(_fmt: core::fmt::Arguments, _file_line: &(&'static str, u32)) -> !
{ loop { } }

#[no_mangle]
pub extern "C" fn sum(x: libc::c_int, y: libc::c_int) -> libc::c_int
{
x + y
}

然后,我再次尝试构建整个程序:

rustc --crate-type=staticlib --emit=obj -C panic=abort sum.rs
gcc -c main.c
gcc sum.o main.o -o program.exe

但是得到了:

sum.o:(.text+0x3e): undefined reference to `core::panicking::panic::h907815f47e914305'
collect2.exe: error: ld returned 1 exit status

panic 函数引用可能来自 sum() 加法中的溢出检查。这一切都很好而且令人向往。根据this page ,我需要定义自己的 panic 函数来使用 libcore。但是我找不到关于如何这样做的说明:我应该为其提供定义的函数在文档中称为 panic_impl,但是链接器提示 panic::h907815f47e914305,不管它应该是什么。

使用 objdump,我找到了缺失函数的名称,并将其破解到 C:

ma​​in.c

#include <stdio.h>
#include <stdlib.h>

int sum(int, int);

void _ZN4core9panicking5panic17h907815f47e914305E()
{
printf("Panic!\n");
abort();
}

int main()
{
printf("Sum is %d.\n", sum(2, 3));
return 0;
}

现在,整个程序编译链接成功,甚至可以正常运行。

如果我随后尝试在 Rust 中使用数组,则会生成另一种 panic 函数(用于边界检查),因此我也需要为其提供定义。每当我在 Rust 中尝试更复杂的东西时,就会出现新的错误。顺便说一下,panic_fmt 似乎永远不会被调用,即使确实发生了 panic 。

无论如何,这一切看起来都非常不可靠,并且与我通过 Google 可以找到的关于此事的所有信息相矛盾。有 this ,但我尝试按照说明进行操作,但无济于事。

这似乎是一件简单而基本的事情,但我无法让它以正确的方式工作。也许这是 Rust 的夜间错误?但我需要 libclang_items。如何在没有展开或 panic 支持的情况下生成 Rust 目标文件/静态库?当它想要 panic 时,它可能应该只执行非法的处理器指令,或者调用我可以在 C 中安全定义的 panic 函数。

最佳答案

你不应该使用 --emit=obj;只是 rustc --crate-type=staticlib -C panic=abort sum.rs 应该做正确的事情。 (这修复了 _ZN4core9panicking5panic17h907815f47e914305E 链接错误。)

要修复另一个链接错误,您需要正确编写 panic_fmt(注意 extern 的使用):

#[lang="panic_fmt"]
extern fn panic_fmt(_: ::core::fmt::Arguments, _: &'static str, _: u32) -> ! {
loop {}
}

有了这些更改,一切似乎都按照预期的方式工作。


您需要 panic_fmt 以便您可以决定在发生 panic 时要做什么:如果您使用 #![no_std],rustc 会假设没有标准库/libc/kernel,所以它可以'不要只是调用 abort() 或期望非法指令来做任何有用的事情。它应该以某种方式在稳定的 Rust 中公开,但我不知道是否有人正在努力稳定它。

你不需要使用#![feature(libc)]来获取libc;你应该改用 crates.io 上发布的版本(或者你可以手动声明你需要的函数)。

关于c - Rust 和 C 与最小程序和 no_std 的链接问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37929165/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com