refactor: refactor c-friendly ffi design doc
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
# C/C++ Headers
|
||||
|
||||
Under this section we discuss how to write the C/C++ header files that accompany the
|
||||
Rust FFI library. The Rust-side counterpart of each topic is covered in
|
||||
[FFI Function Signatures](ffi-function-signatures.md) and
|
||||
[Allowed Data Types](allowed-data-types.md).
|
||||
|
||||
## Function Declaration Style
|
||||
|
||||
FFI functions must be exported under C names, that is, they must not go through the
|
||||
C++ name mangling mechanism. In the generated C header file, you need to use the
|
||||
`extern "C"` specifier, the `__cplusplus` macro and macro conditionals to import the
|
||||
declarations correctly, for example:
|
||||
|
||||
```c++
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
CError WFStartup(void);
|
||||
|
||||
// More FFI functions omitted...
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif // __cplusplus
|
||||
```
|
||||
|
||||
## Required Header Files
|
||||
|
||||
The generated C/C++ header files must include the appropriate header files for the
|
||||
types used in the declarations.
|
||||
|
||||
- In C, the `bool` type is provided by `<stddef.h>`. C++ supports `bool` natively
|
||||
and does not need any header file.
|
||||
- In C, the integer types are provided by `<stdint.h>`. In C++, they are provided
|
||||
by `<cstdint>`.
|
||||
- In C, the `uintptr_t` and `intptr_t` types are provided by `<stdint.h>`. In C++,
|
||||
they are provided by `<cstdint>`.
|
||||
- The floating-point types do not require any header file.
|
||||
|
||||
## Type Correspondences
|
||||
|
||||
The following table shows the correspondence between the Rust types that can cross
|
||||
the FFI boundary directly (listed in [Allowed Data Types](allowed-data-types.md))
|
||||
and their C/C++ counterparts. The left column lists the Rust type and the right
|
||||
column lists the corresponding C/C++ type.
|
||||
|
||||
| Rust | C/C++ |
|
||||
|------|-------|
|
||||
| `bool` | `bool` |
|
||||
| `f32` | `float` |
|
||||
| `f64` | `double` |
|
||||
| `i8` | `int8_t` |
|
||||
| `i16` | `int16_t` |
|
||||
| `i32` | `int32_t` |
|
||||
| `i64` | `int64_t` |
|
||||
| `u8` | `uint8_t` |
|
||||
| `u16` | `uint16_t` |
|
||||
| `u32` | `uint32_t` |
|
||||
| `u64` | `uint64_t` |
|
||||
| `usize` | `uintptr_t` |
|
||||
| `isize` | `intptr_t` |
|
||||
|
||||
## The char Problem
|
||||
|
||||
For the Rust `char` type, the C/C++ header side uses `char32_t` as the parameter
|
||||
type. Note that `char32_t` can hold any 32-bit unsigned integer, which is broader
|
||||
than the set of valid Unicode scalar values carried by the Rust `char` type. The
|
||||
Rust side is responsible for validating the incoming value; see
|
||||
[The char Problem](allowed-data-types.md#the-char-problem) in
|
||||
[Allowed Data Types](allowed-data-types.md).
|
||||
Reference in New Issue
Block a user