TL; DR: пример не полезен и ничего не показывает.
что это на самом деле получает? Это указатель? Какой-то идентификатор?
Это структура, точно такая, как определено на стороне Rust. Это указатель, если вы возвращаете указатель (в этом примере это не так) или идентификатор, если вы возвращаете какой-то идентификатор (в этом примере это не так).
FFI Rust не накладывает никаких накладных расходов или абстракций - вы возвращаете то, что возвращаете.
документация указывает на то, что я должен использовать #[repr(C)]
Да, вам следует . Без этого ваш код, скорее всего, будет неопределенным поведением. Расположение структуры Rust еще не гарантировано. Без указания представления как C, для кода на C невозможно узнать, где находятся поля.
но, кажется, работает без него
Это потому, что в вашем примере struct нет полей и, следовательно, нет размера (что AFAIK даже не допустимо в C без нестандартных расширений). Русту практически никогда не нужно просматривать данные (какие данные?), Поэтому не имеет значения, что вы передаете обратно.
При печати значения, полученного на стороне C, отображаются очень маленькие целые числа
Вероятно, это просто мусор в стеке. Буквально неинициализированные данные.
Использование структуры с полями без #[repr(C)]
Это плохо . Не делай этого. String
- это структура с нетривиальными полями, и она не помечена #[repr(C)]
.
Cargo.toml
[package]
name = "shear"
version = "0.1.0"
authors = ["An Devloper"]
[lib]
crate-type = ["cdylib"]
[dependencies]
ЦСИ / 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. Отказ от ответственности: я основной автор.