C program reads gibberish when given a Rust-created struct

Hello, I am working on a Rust program that loads in C library files as plugins, I am currently facing this very weird behaviour about Rust structs.

I have defined 2 structs in Rust with repr C

#[repr(C)]
struct TwoStruct {
    pub one: u64,
    pub two: u64,
}

#[repr(C)]
struct ThreeStruct {
    pub one: u64,
    pub two: u64,
    pub three: u64,
}

And the same struct is defined in C

struct TwoStruct {
  uint64_t one;
  uint64_t two;
};

struct ThreeStruct {
  uint64_t one;
  uint64_t two;
  uint64_t three;
};

When i pass TwoStruct { one: 1, two: 2 } to a C function that prints out the struct contents, it prints out 1, 2 as expected. But when I pass ThreeStruct { one: 1, two: 2, three: 3 } it prints out gibberish instead of the expected 1, 2, 3.

Why?

I have included a repo so you can run the code, more info in README

Your function pointers need to be extern "C" to match the calling conventions.

diff --git a/src/main.rs b/src/main.rs
index 7e33934..91378a2 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -22,8 +22,8 @@ fn lib_path(name: &str) -> PathBuf {
 fn main() {
     unsafe {
         let printstruct = Library::new(lib_path("printstruct")).unwrap();
-        let printtwo: Symbol<fn(TwoStruct)> = printstruct.get("printtwo").unwrap();
-        let printthree: Symbol<fn(ThreeStruct)> = printstruct.get("printthree").unwrap();
+        let printtwo: Symbol<extern "C" fn(TwoStruct)> = printstruct.get("printtwo").unwrap();
+        let printthree: Symbol<extern "C" fn(ThreeStruct)> = printstruct.get("printthree").unwrap();

         let two = TwoStruct { one: 1, two: 2 };
         let three = ThreeStruct {
9 Likes

thank you it worked, i've done some further searching apparently C expects the entire ThreeStruct in stack, but rust normally optimises this by putting the first 16 byte of the struct in a register

1 Like

The differences may vary on other targets -- even the one that appeared to work in your example might fail elsewhere. Using extern "C" makes sure to match whatever the target uses.

1 Like