编辑:有人指出我的示例不够完整,无法使用。我的问题已经解决了,但是如果你有兴趣看完整的代码可以看看here .
给定以下代码:
#[no_mangle]
pub extern "C" fn create_acceptor() -> Acceptor {
Acceptor {}
}
pub struct Acceptor {}
如果我从 C 中调用它,它实际上得到了什么?它是一个指针吗?某种 ID?
我目前在 C 端使用如下代码:
extern int create_acceptor();
int main(int argc, char **argv) {
int acceptor = create_acceptor();
return 0;
}
它似乎工作正常。我像使用不透明类型一样使用它,像 acceptor_doSomething(acceptor)
一样传回 Rust。
但我很困惑,因为我在 C 端为 acceptor
使用什么类型似乎并不重要。 void*
和 int
的行为相同。此外,文档似乎表明我应该使用 #[repr(C)]
,但没有它似乎也能正常工作。这是为什么?
当打印 C 端收到的值时,它显示非常小的整数,所以我猜它是 Rust 端的一个 id?
最佳答案
TL;DR:该示例不是一个有用的示例,也没有显示任何内容。
what does it actually get? Is it a pointer? An id of some sort?
它是结构体,与 Rust 端的定义完全相同。如果您返回一个指针(此示例不是),则它是一个指针;如果您返回某个 id(此示例不是),则它是一个 id。
Rust 的 FFI 没有任何开销或抽象——你返回的就是返回的。
the documentation seems to indicate that I should be using
#[repr(C)]
是的,你应该。没有它,您的代码很可能是未定义的行为。 Rust 结构的布局尚未得到保证。如果不将表示指定为 C,C 代码就无法知道哪些字段在哪里。
but it seems to work without it
那是因为您的示例结构没有字段,因此没有大小(AFAIK 在没有非标准扩展的情况下在 C 中甚至无效)。 Rust 基本上从不需要查看数据(什么数据?)所以你传回什么并不重要。
When printing the value received on the C side, it's showing very small integers
这可能只是堆栈中的垃圾。字面上未初始化的数据。
使用不带 #[repr(C)]
字段的结构
这很不好。不要这样做。 String
是一个具有重要字段的结构,它没有标记为 #[repr(C)]
。
Cargo.toml
[package]
name = "shear"
version = "0.1.0"
authors = ["An Devloper"]
[lib]
crate-type = ["cdylib"]
[dependencies]
src/lib.rs
// Don't do this, `String` isn't #[repr(C)]!
#[no_mangle]
pub extern "C" fn create_example() -> String {
String::from("hello")
}
// Don't do this, `String` isn't #[repr(C)]!
#[no_mangle]
pub extern "C" fn use_example(e: String) {
println!("{}", e);
}
main.c
extern int create_example();
extern void use_example(int example);
int main(int argc, char **argv) {
int example = create_example();
use_example(example);
}
执行
$ cargo build
Compiling shear v0.1.0 (file:///home/ubuntu/shear)
Finished dev [unoptimized + debuginfo] target(s) in 1.02s
$ gcc -o example main.c -L target/debug/ -lshear
$ LD_LIBRARY_PATH=target/debug/ ./example
Segmentation fault
请阅读The Rust FFI Omnibus有关如何跨 FFI 边界正确传输值的详细信息。免责声明:我是第一作者。
关于rust - 当 Rust FFI 函数返回一个没有#[repr(C)] 的结构给 C 时返回什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54300524/