从Rust程序调用C库函数(由rustc
编译的可执行文件)运行良好,并且是Rust团队的目标。
从C程序调用Rust crate函数(由clang
编译的可执行文件)正在处理简单的事情,但如果我生成任务,它就会崩溃。
如何让Rust任务起作用?
这是我的来源和错误消息。您也可以从https://github.com/Eonil/TeachingMyselfRust
下载a.rs
#[no_mangle]
pub fn test1()
{
let a1 = proc()
{
};
spawn(a1);
}
b.c
#include <stdio.h>
extern void test1();
int main(int argc, char** argv)
{
test1();
return 0;
}
构建脚本
rm -rf ./Build
mkdir ./Build
rustc a.rs --crate-type=staticlib -o ./Build/rust-stuffs.a
clang b.c ./Build/rust-stuffs.a -o Build/out
cd Build
./out
执行结果
warning: unlinked native library: System
There are not many persons who know what wonders are opened to them in the
stories and visions of their youth; for when as children we listen and dream,
we think but half-formed thoughts, and when as men we try to remember, we are
dulled and prosaic with the poison of life. But some of us awake in the night
with strange phantasms of enchanted hills and gardens, of fountains that sing
in the sun, of golden cliffs overhanging murmuring seas, of plains that stretch
down to sleeping cities of bronze and stone, and of shadowy companies of heroes
that ride caparisoned white horses along the edges of thick forests; and then
we know that we have looked back through the ivory gates into that world of
wonder which was ours before we were wise and unhappy.
fatal runtime error: assertion failed: !ptr.is_null()
stack backtrace:
1: 0x108bc7944 - rt::backtrace::imp::write::hdaa6a604147ca757g8b::v0.10
2: 0x108b5f4aa - rt::util::abort::h3d7b16d436532c64Bmc::v0.10
3: 0x108bc605a - rt::local_ptr::compiled::take::hb1c4b940f0aa52aea9a::v0.10
4: 0x108b5e6ad - task::TaskBuilder::spawn::h2dcf43b5eaa6805aQhC::v0.10
5: 0x108b5eb6d - task::spawn::hff1c6bd6cfded263NjC::v0.10
6: 0x108b29670 - test1
7: 0x108b295fd - main
./run.bash: line 8: 38948 Illegal instruction: 4 ./out
答案 0 :(得分:7)
不是那么简单,我很害怕。 Rust任务不是普通线程,如pthreads
或C中的其他线程。它们确实需要Rust运行时的一些支持,因此为了创建任务,您需要启动运行时。其中一种方法是从C程序调用Rust函数,然后调用另一个C函数:
#include <stdio.h>
extern int run(int argc, char** argv, void (*kont)(void));
extern void do_work();
void actual_main(void);
int main(int argc, char** argv) {
return run(argc, argv, actual_main);
}
void actual_main(void) {
printf("Hello from C program\n");
do_work();
}
锈:
extern crate native;
#[no_mangle]
pub extern fn run(argc: int, argv: *const *const u8, kont: extern fn()) {
native::start(argc, argv, proc() kont());
}
#[no_mangle]
pub extern fn do_work() {
spawn(proc() {
println!("Hello from task");
});
}
编译(在我的Linux机器上;如果你正在使用另一个操作系统,你可能需要调整它):
% rustc --crate-type staticlib --crate-name ex lib.rs
% gcc -c example.c
% gcc -L. -o example example.o -lex -lm -lpthread -lgcc_s -ldl
运行:
% ./example
Hello from C program
Hello from task
这确实需要您更改主要功能。在任何情况下,从Rust(任务,Rust I / O,盒子等)访问特定于运行时的函数的所有代码都必须在&#34;&#34; native::start()
调用调用堆栈。这是我所知道的最简单的方法。或者,如果这是可以接受的,您可以在Rust中编写main()
函数,这样您的可执行二进制文件将rustc
输出,即使它的工作实际上将在C代码中发生。