You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Suggestion for c_int in Listing 20-8 and 20-9 Using extern Functions to Call External Code to set a good example #4443
unsafeextern"C"{
safe fnabs(input:i32) -> i32;}fnmain(){println!("Absolute value of -3 according to C: {}", abs(-3));}
But it may set a better precedent to use std::ffi::c_int for the parameter and return value of abs. While c_int and i32 should be equivalent on all modern platforms, that doesn't extend to c_long.
See the documentation for c_int and c_long, in particular this note for c_long:
This type will always be i32 or i64. Most notably, many Linux-based systems assume an i64, but Windows assumes i32.
If I erroneously declare labs to take a i64, then the Rust compiler will happily allow this runtime truncation to happen with no warning on Windows. Unsurprising, as Rust has no way to know that it should be 32-bit on Windows unless we tell it.
safe fnlabs(input:i64) -> i64;
However, if we use c_long instead, then the Rust compiler can catch the mismatch at compile time:
use std::ffi::c_long;unsafeextern"C"{
safe fnlabs(input:c_long) -> c_long;}
Something like this:
| println!("Absolute value of {num2} according to C: {}", labs(num2));
| ---- ^^^^ expected `i32`, found `i64`
| |
| arguments to this function are incorrect
Though note that this compiler error only happens on Windows, and I saw no such errors or clippy warnings on macOS. Writing cross-platform code is difficult!
So while safe fn abs(input: i32) -> i32 should be perfectly fine, it may be good if readers are aware of c_int and therefore adopt similar types at FFI boundaries.
Suggested fix:
use std::ffi::c_int;unsafeextern"C"{
safe fnabs(input:c_int) -> c_int;}fnmain(){println!("Absolute value of -3 according to C: {}", abs(-3));}
With minor updates to the surrounding prose.
Since this example is using 32-bit ints and since the truncation is well-defined implementation-specific C behaviour (and not strictly unsafe), I'm not sure if it this potential logic bug with c_long needs to be noted on the chapter on safety. What do you think?
Thanks for reporting. I agree that caring for compatible data types is important -- I think I took some care in my own book, but I have to agree that I don't know much about Rust's FFI. But extending that section might be an option -- you might have a look and tell me if there is something wrong: https://rust-for-c-programmers.com/ch25/25_4_interfacing_with_c_code_ffi.html
I might read your blog post, and perhaps I will add it to the list in the appendix.
OK, I have added your blog post to the appendix (currently second link from the bottom). But I am still unsure how much room FFI should occupy in a beginner book -- I think most beginners would not use FFI, and they actually should better not use it. For tiny languages we often need C FFI, but Rust has such a rich collection of libraries, that FFI is very rarely needed. But I agree, a short mention of the risk of incompatible data types in beginner books is useful. I just read your blog, I think it is mostly OK.
changed the title [-]Suggestion for c_int in Listing 20-9 Using extern Functions to Call External Code[/-][+]Suggestion for c_int in Listing 20-9 Using extern Functions to Call External Code to set a good example[/+]on Aug 5, 2025
changed the title [-]Suggestion for c_int in Listing 20-9 Using extern Functions to Call External Code to set a good example[/-][+]Suggestion for c_int in Listing 20-8 and 20-9 Using extern Functions to Call External Code to set a good example[/+]on Aug 5, 2025
Activity
nathany commentedon Jul 13, 2025
I explored this topic a little more and wrote up a blog post going over it.
https://nathany.com/labs/
Hope it's helpful. Thanks.
StefanSalewski commentedon Jul 13, 2025
Thanks for reporting. I agree that caring for compatible data types is important -- I think I took some care in my own book, but I have to agree that I don't know much about Rust's FFI. But extending that section might be an option -- you might have a look and tell me if there is something wrong: https://rust-for-c-programmers.com/ch25/25_4_interfacing_with_c_code_ffi.html
I might read your blog post, and perhaps I will add it to the list in the appendix.
StefanSalewski commentedon Jul 14, 2025
OK, I have added your blog post to the appendix (currently second link from the bottom). But I am still unsure how much room FFI should occupy in a beginner book -- I think most beginners would not use FFI, and they actually should better not use it. For tiny languages we often need C FFI, but Rust has such a rich collection of libraries, that FFI is very rarely needed. But I agree, a short mention of the risk of incompatible data types in beginner books is useful. I just read your blog, I think it is mostly OK.
nathany commentedon Jul 14, 2025
Thanks. I want to point out that I made a mistake in my article that I need to correct. It was called out by the fine folks on Reddit: https://www.reddit.com/r/rust/comments/1lyjok1/hello_ffi_foot_guns_at_the_labs/
nathany commentedon Aug 5, 2025
I wondered if the tech review would mention the same concern, but it looks like #4460 doesn't make any changes to these listings.
[-]Suggestion for c_int in Listing 20-9 Using extern Functions to Call External Code[/-][+]Suggestion for c_int in Listing 20-9 Using extern Functions to Call External Code to set a good example[/+][-]Suggestion for c_int in Listing 20-9 Using extern Functions to Call External Code to set a good example[/-][+]Suggestion for c_int in Listing 20-8 and 20-9 Using extern Functions to Call External Code to set a good example[/+]