我试图通过一些简单的FFI工具来解决如何让Rust与C或C++代码一起工作。我现在的问题是:
当我将Rust代码编译到一个对象文件时,似乎缺少了clang链接器的一些绑定来完成一个可执行文件。这里有两个非常简单的文件,我正在使用。
clink.c
#include <stdio.h>
#include <stdbool.h>
int rust_int(int);
bool rust_bool(int, int);
/********************************/
/* void rust_char_star(char *); */
/********************************/
int main(void) {
printf("%d\n", rust_int(5));
if (rust_bool(5, 6)) {
printf("True\n");
}
else { printf("False\n"); }
/******************************/
/* rust_char_star("Testing"); */
/******************************/
return 0;
}
rustlink.rs
use std::os::raw::{c_int, c_char};
// use std::ffi::{CStr, CString};
#[no_mangle]
pub extern "C" fn rust_int(i: c_int) -> c_int {
i
}
#[no_mangle]
pub extern "C" fn rust_bool(x: c_int, y: c_int) -> bool {
if x > y {
true
}
else {
false
}
}
////////////////////////////////////////////////////////////////////////////
// #[no_mangle] //
// pub extern "C" fn rust_char_star(c: *const c_char) { //
// let str_printable = unsafe {CString::from_raw(c as *mut c_char) }; //
// //
// println!("{:?}", str_printable); //
// } //
////////////////////////////////////////////////////////////////////////////
当我在没有CString
的情况下编译其中的每一个时,一切都如预期的那样工作。无视警告。
~/dev/rust/learn/clink$ rustc --emit obj --crate-type staticlib rustlink.rs
warning: unused import: `c_char`
use std::os::raw::{c_int, c_char};
^^^^^^
= note: #[warn(unused_imports)] on by default
~/dev/rust/learn/clink$ clang clink.c rustlink.o -o test
~/dev/rust/learn/clink$ ./test
5
False
但是,当我取消注释所有使用CString
类型的代码时,我就遗漏了一些东西。我不打算在删除注释后重新发布上面的代码。不过,这是产出的结果。
~/dev/rust/learn/clink$ rustc --emit obj --crate-type staticlib rustlink.rs
warning: unused import: `CStr`
--> rustlink.rs:2:16
|
2 | use std::ffi::{CStr, CString};
| ^^^^
|
= note: #[warn(unused_imports)] on by default
~/dev/rust/learn/clink$ clang clink.c rustlink.o -o test
rustlink.o: In function `alloc::alloc::dealloc':
rustlink.3a1fbbbh-cgu.0:(.text._ZN5alloc5alloc7dealloc17hca8aab9ecdf50cafE+0x43): undefined reference to `__rust_dealloc'
rustlink.o: In function `rust_char_star':
rustlink.3a1fbbbh-cgu.0:(.text.rust_char_star+0xa): undefined reference to `std::ffi::c_str::CString::from_raw'
rustlink.3a1fbbbh-cgu.0:(.text.rust_char_star+0x3a): undefined reference to `<std::ffi::c_str::CString as core::fmt::Debug>::fmt'
rustlink.3a1fbbbh-cgu.0:(.text.rust_char_star+0xa9): undefined reference to `std::io::stdio::_print'
rustlink.o:(.data.DW.ref.rust_eh_personality[DW.ref.rust_eh_personality]+0x0): undefined reference to `rust_eh_personality'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
~/dev/rust/learn/clink$
再往前走一点。我试图将锈蚀代码编译到一个静态库中,以便输入到clang中。我不知道为什么,但这是结果。
~/dev/rust/learn/clink$ rustc --crate-type staticlib rustlink.rs
warning: unused import: `CStr`
--> rustlink.rs:2:16
|
2 | use std::ffi::{CStr, CString};
| ^^^^
|
= note: #[warn(unused_imports)] on by default
~/dev/rust/learn/clink$ ls
clink.c librustlink.a rustlink.o rustlink.rs
~/dev/rust/learn/clink$ clang clink.c -o test -lrustlink
/usr/bin/ld: cannot find -lrustlink
clang: error: linker command failed with exit code 1 (use -v to see invocation)
~/dev/rust/learn/clink$ clang clink.c -o test -L -lrustlink
/tmp/clink-357672.o: In function `main':
clink.c:(.text+0x15): undefined reference to `rust_int'
clink.c:(.text+0x3a): undefined reference to `rust_bool'
clink.c:(.text+0x83): undefined reference to `rust_char_star'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
~/dev/rust/learn/clink$
这就是我有点困惑的地方。我想,当您告诉rustc机箱类型是静态的,它包含了所有的依赖项,但我想情况并非如此。
显然我错过了一步。我更希望rustc包含所有绑定,这样我就可以使用一个简单的命令clang来生成一个可执行文件。
发布于 2019-01-06 17:25:03
我错过了标准的库绑定。在Googling上搜索了一下之后,我发现了一些有用的链接:
结果,我只需要知道Rust标准对象文件在哪里。运行以下是一个解决方案:
~/dev/生锈/学习/clink$ rustc -纸箱型静态库rustlink.rs ~/dev/dev/clink$clangclink.c -o test -L。-lrustlink nick@Void:~/dev/锈病/学习/clink$ ./test 5错误的“测试”我到这里了吗?
我添加了一行“我到这里了吗”,因为当我最初成功编译时,程序在完成之前就出现了错误。我想弄清楚是否是CString
打印造成的。原来我有双倍的自由条件。为了完整起见,我将在最下面添加修订后的锈蚀代码。
作为第二种解决方案,更让我满意的是,您可以使用一个对象文件:
~/dev/生锈/学习/clink$ rustc
它们都产生了相同的输出,我不能真正地说一种方法是否比另一种更好。这取决于您的需求正在开发中。
最后的。我上面为rustlink.rs编写的原始代码是错误的。我了解到,使用绑定到原始指针的CString
几乎是个坏主意。我认为,在大多数情况下,它需要分配自己的记忆。这要归功于drop
。我将rust_char_star
函数从最初的post更改为以下内容。
#no_mangle酒吧推出"C“fn rust_char_star(c:*const c_char) { let ch =不安全的{ CStr::from_ptr(c) };str_printable =CString:from(Ch);println!("{:?}",str_printable);println!(”我到这里了吗?“);
这有效地防止了双重自由。
https://stackoverflow.com/questions/54057837
复制相似问题