TL;DR: The example isn't a useful one and doesn't show anything.
what does it actually get? Is it a pointer? An id of some sort?
It's the struct, exactly as defined on the Rust side. It's a pointer if you return a pointer (this example does not) or an id if you return some id (this example does not).
Rust's FFI imposes no overhead or abstraction — what you return is what is returned.
the documentation seems to indicate that I should be using #[repr(C)]
Yes, you should. Without it, your code is most likely undefined behavior. The layout of a Rust struct is not yet guaranteed. Without specifying the representation as C, there's no way for the C code to know which fields are where.
but it seems to work without it
That's because your example struct has no fields and thus no size (which AFAIK isn't even valid in C without non-standard extensions). Rust basically never even needs to look at the data (what data?) so it doesn't matter what you pass back.
When printing the value received on the C side, it's showing very small integers
This is probably just junk on the stack laying around. Literally uninitialized data.
Using a struct with fields without #[repr(C)]
This is bad. Don't do it. String is a struct with non-trivial fields and it is not marked #[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);
}
Execution
$ 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
Please read the The Rust FFI Omnibus for details about how to properly transfer values across the FFI boundary. Disclaimer: I am the primary author.
voidshould "work" in most case. Butintdon't make any sense, rust empty type are empty. - Stargateur