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 builtiniNoruNtype if, and only if, the corresponding C++ type is the same type as the standard library(u)intN_ton this platform.For example,
c_intisi32ifint32_tis a type alias toint. Otherwise,c_intwill be a different type. (Either a newtype, or a non-i32primitive 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: anyffi_11type can be converted to or from a builtin orffi_11type if the conversion is lossless. For example,c_intcan always be converted toc_long, but not toc_ulong. Andi32can always be converted toc_int, buti64can only on some platforms. -
Separately from the above,
c_charcan be converted to and from bothi8andu8usingFromandInto. 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 longon Linux. This depends on a decision about what the type should be. For example, it could beisize, or a newtype. -
TryFromimpls for lossy conversions. -
Any/all other operations (e.g. arithmetic) one might want to support on newtypes.