[英]What is returned when a Rust FFI function returns a struct without #[repr(C)] to C?
編輯:有人指出,我的示例還不夠完整,無法使用。 我的問題已經解決,但是如果您有興趣查看完整的代碼,可以在這里查看 。
給出以下代碼:
#[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:該示例不是有用的示例,沒有顯示任何內容。
它實際上得到了什么? 是指針嗎? 某種ID?
這是結構,完全與Rust端定義的一樣。 如果您返回一個指針(此示例未返回),則為一個指針;如果您返回某個ID(此示例未返回),則為一個id。
Rust的FFI不會增加開銷或抽象-您返回的就是返回的東西。
該文檔似乎表明我應該使用
#[repr(C)]
是的, 你應該 。 沒有它,您的代碼很可能是未定義的行為。 尚未保證Rust結構的布局。 如果不將表示形式指定為C,則C代碼無法知道哪些字段位於何處。
但是似乎沒有它就可以工作
那是因為您的示例結構沒有字段,因此沒有大小(如果沒有非標准擴展名,則AFAIK在C語言中甚至無效)。 Rust基本上甚至不需要查看數據(什么數據?),所以回傳什么都沒有關系。
打印在C端接收到的值時,它顯示非常小的整數
這可能只是周圍堆積的垃圾。 字面上未初始化的數據。
#[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
請閱讀Rust FFI Omnibus,以獲取有關如何在FFI邊界上正確傳輸值的詳細信息。 免責聲明:我是第一作者。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.