ffi_11 0.0.0

One-to-one FFI types for C++/Rust interop.
Documentation
  • Coverage
  • 5.88%
    1 out of 17 items documented0 out of 5 items with examples
  • Size
  • Source code size: 47.67 kB This is the summed size of all the files inside the crates.io package for this release.
  • Documentation size: 1.49 MB This is the summed size of all files generated by rustdoc for all configured targets
  • Ø build duration
  • this release: 6s Average build duration of successful builds.
  • all releases: 9s Average build duration of successful builds in releases after 2024-10-23.
  • Links
  • google/crubit
    1015 65 2
  • crates.io
  • Dependencies
  • Versions
  • Owners
  • ssbr

One to one FFI.

In ffi_11, if a type is distinct in C/C++, it is distinct in Rust. This relationship varies from platform to platform.

For example, char and signed char are distinct types in C++. This means that in ffi_11, there is a distinct ffi_11::c_char type which is not the same as ffi::c_schar, even if char is signed. This is unlike the std::ffi module, which would instead define both c_char and c_schar as aliases to i8.

As another example, on some platforms, int64_t is long, while on other platforms, it is long long. Exactly one of ffi_11::c_long or ffi_11::c_longlong will be i64, depending on the platform.

Guarantees and backwards compatibility

ffi_11 offers the following guarantees:

  • Every unique C/C++ type is given a unique Rust type: the Rust->C/C++ type mapping is one-to-one.

  • A given type c_<X> is the same type as a builtin iN or uN type if, and only if, the corresponding C++ type is the same type as the standard library (u)intN_t on this platform.

    For example, c_int is i32 if int32_t is a type alias to int. Otherwise, c_int will be a different type. (Either a newtype, or a non-i32 primitive 32 bit integer type.)

There are no type identity guarantees other than the above. For example, long long may be a i64,isize, or a newtype, depending on the platform.

There is also no guarantee that every Rust primitive type has a C++ equivalent. The 1:1 relationship only applies to the types in the ffi_11 module. To get the equivalent high-fidelity interop in C++, you would need an equivalent <ffi_11.h> header, defined in a similar fashion and using newtypes to define C++ types that correspond to Rust primitives that otherwise have no C++ equivalent. (For example, the typical Windows ABI only has one 64 bit integer type, while Rust has two.)

Supported Operations

The following operations are supported:

  • From: any ffi_11 type can be converted to or from a builtin or ffi_11 type if the conversion is lossless. For example, c_int can always be converted to c_long, but not to c_ulong. And i32 can always be converted to c_int, but i64 can only on some platforms.

  • Separately from the above, c_char can be converted to and from both i8 and u8 using From and Into. It is considered an ambiguously-signed type for portability.

Supported platforms

For now, the only supported platforms are:

  • LP64: Any LP64 platform which uses the smallest suitable fundamental type for intN_t. For example, Linux on x86_64 or Aarch64. But not OpenBSD.
  • LLP64: 64-bit Windows.

We will add support over time to other commonly used platforms.

TODO(b/333759161): get and test a compatibility matrix, including (currently untested) Windows.

Unfinished Work

This module is still embryonic, and is missing the following:

  • Support for long long on Linux. This depends on a decision about what the type should be. For example, it could be isize, or a newtype.

  • TryFrom impls for lossy conversions.

  • Any/all other operations (e.g. arithmetic) one might want to support on newtypes.

References