【发布时间】:2016-06-20 18:15:00
【问题描述】:
我正在尝试用 C 语言构建一个调用 Rust 函数的最小程序,最好使用#![no_std] 编译,在 Windows 中使用 GCC 6.1.0 和 rustc 1.11.0-nightly (bb4a79b08 2016-06-15) x86_64-pc-windows-gnu。这是我首先尝试的:
main.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
好的,所以其中一些错误与恐慌解除有关。我发现了一个 Rust 编译器设置来删除展开支持,-C panic=abort。使用它,关于eh_personality 和eh_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,我需要定义自己的恐慌函数来使用libcore。但是我找不到有关如何执行此操作的说明:我应该为其提供定义的函数在文档中称为panic_impl,但是链接器抱怨panic::h907815f47e914305,无论它应该是什么。
使用objdump,我能够找到丢失的函数的名称,并将其破解到 C:
main.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 中使用数组,则会生成另一种恐慌函数(用于边界检查),因此我也需要为其提供定义。每当我在 Rust 中尝试更复杂的东西时,都会出现新的错误。而且,顺便说一句,panic_fmt 似乎永远不会被调用,即使确实发生了恐慌。
无论如何,这一切似乎都非常不可靠,并且与我可以通过 Google 找到的关于此事的所有信息相矛盾。有this,但我尝试按照说明操作无济于事。
这似乎是一个简单而基本的事情,但我无法让它以正确的方式工作。也许这是一个 Rust 夜间错误?但我需要libc 和lang_items。如何在没有展开或恐慌支持的情况下生成 Rust 对象文件/静态库?当它想要恐慌时,它可能应该只执行一条非法的处理器指令,或者调用一个我可以在 C 中安全定义的恐慌函数。
【问题讨论】:
-
请不要编辑您的问题以包含答案。 Stack Overflow 明确鼓励您在下面添加自己的答案。