Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Struct passed by-value from C to Rust get's corrupted (using FFI and .dll from Visual Studio) #11343

Closed
Matthias247 opened this issue Jan 6, 2014 · 4 comments · Fixed by #12762

Comments

@Matthias247
Copy link
Contributor

I'm interfacing an external DLL which I'm creating with Visual Studio 2012.

I've tried to pass a struct by-value from C to Rust in a callback.
The struct and the callback are defined as follows:

pub struct Value {
    a: u32,
    b: i32,
    c: i32,
    d: u8,
    e: u8,
    f: u8,
    g: u8
}

#[deriving(Clone,Eq)]
pub struct Notification {
    notification_type: i32,
    value_id: Value,
    data: u8
}

extern "C" fn on_notification(notification_target: *mut LibWrap, notification: Notification) {
  ...
}

However the struct received in on_notification is corrupted and contains not the data which is sent in C++.

I wrote a test program to isolate and reproduce the issue.
The gist therefore is here: https://gist.github.com/Matthias247/8283183
It can be cloned from https://gist.github.com/8283183.git
It includes the source code for the library with a visual studio project to built it and the rust test program.
I also included make.sh to build it on Linux. However in Linux I can't reproduct the issue. The struct get's copied correctly there.

This is the output from my test program:

Starting
rust notification size: 24
rust value size: 16
Initializing library
C++ notification size: 24
C++ value size: 16
 1  0  0  0  2  0  0  0  3  0  0  0  4  0  0  0  5  6  7  8  9 CC CC CC
 1  0  0  0  2  0  0  0  3  0  0  0  4  0  0  0  5  9 48 64 80 CC CC CC
Notification: Notification{notification_type: 1i32, value_id: Value{a: 2u32, b:
3i32, c: 4i32, d: 5u8, e: 9u8, f: 72u8, g: 100u8}, data: 128u8}

The first line is the content of the notification in bytes in C++, the second the content in Rust.
You can see that the last bytes of the notification structure are different in C++ in Rust. Interesting hereby is also that the last field (notification.data == 9) gets copied into notification.value_id.d (verified this with using other values for notification.data) and the remaining notification fields are garbage.

@Matthias247
Copy link
Contributor Author

@sanxiyn on IRC mentioned that this could be related to #9205
However I'm not sure because that issue is about structs as return values. In my case the struct is a function argument and not the return value.

@Matthias247
Copy link
Contributor Author

Issue #11198 is also similar.
However I could successfully pass structs from Rust to C before - but mine didn't contain u8 values but only pointers and i32/u32 values.
Maybe the issue is related to u8/i8 types in structs? Because in my example the problem also exists at the first u8 location.

@Matthias247
Copy link
Contributor Author

Update:

As @eddyb on IRC suggested I have created a more compact example and included LLVM IR: https://gist.github.com/Matthias247/8376787
The error happens on all structs with more than a single u8 or u16 value.
The new test tests are passing a struct with 4 u8 or 4 u16 parameters from Rust to C as well as from C to Rust.

I also switched the C side from a C++ project with extern C declarations to a pure C project, so that this issue can be ruled out.

@ghost
Copy link

ghost commented Jan 12, 2014

You can bypass the problem by using external LLVM to compile bitcode. I wrote small utility to do that:
https://gist.github.com/krzat/8374078 , and it worked with rsfml.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant