I understand that using
libc::c_int, which doesn’t have a cross-platform standard size, makes sense when calling into legacy C code that declares
int. However, when exposing Rust code to C, is there any good reason to bother using e.g.
libc::uint32_t instead of just writing
u32 on the Rust side or
libc::size_t instead of just writing
usize on the Rust side?
I understand that using
These types make it abundantly clear that the values are meant for interfacing to C code. That alone is useful.
Rust may be ported to a platform where those types are different (perhaps in some very subtle ways), so better use them.
Personally, I always use u32 and friends where the corresponding C interface uses uint32_t and friends. However, I always use libc::size_t and ssize_t.
If a platform’s
int32_t differs from
i32, things are seriously broken. (C even requires
intN_t to be two’s complement even though
int is allowed to be one’s complement.)
So the issues really are:
Is Rust realistically going to be ported to platforms where
sizeof(size_t) != sizeof(void*)?
If yes, how could
size_trealistically differ? I.e. what kind of failure modes could
libc::size_t as usizeor
usize as libc::size_tcause?
You can use
usize instead of
libc::size_t everywhere, as
libc::size_t is defined as a synonym of
usize in libc for every currently-supported platform. Same with
ssize_t. I recommend you never use
In theory there could be a platform where
size_t is 16 bits and pointers are 32 bits, or where
size_t is 32 bits and pointers are 64 bits. However, you will probably never encounter any such platform when programming in Rust. (I don’t know of any such platform.)
Similarly, I recommend you never use the
libc::intN_t types. Instead, use the native Rust types.
In particular, I recommend that you avoid adding a dependency to the
libc crate unless you actually use a libc function. And, you basically should never use a libc function.
I developed my own module for this in ring in
https://github.com/briansmith/ring/blob/master/src/c.rs. Note that I also have tests to verify that the C compiler’s alignment and sizeof agree with Rust’s. My version of
That kind of thing happens with segmentation, e.g. 16-bit Windows (32 bit “far” pointers, but malloc() objects are limited to 64K, so size_t can still be 16-bits). Hopefully Rust may never see such a system, popular though they once were.
Thanks. This is what I wanted to hear.
std::os::raw which is a subset of
libc (the primitive types). If only what’s there is needed, I prefer to skip the
libc crate entirely.
Thanks. I never knew that module existed.
I noticed the documentation is “Raw OS-specific types for the current platform/architecture.” I guess in a build script “current” is “host” and otherwise it is “target”.
NIT: It’s too bad that all of these have the unnecessary
Also, I guess this should get replicated into the
core module so that
no_std crates can use them.