Files
sarasacw-omrf/assets/c-friendly-ffi-design/c-cpp-headers.md
T

86 lines
2.6 KiB
Markdown
Raw Normal View History

# 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
```
2026-08-09 22:12:10 +08:00
## Parameter Declarations
A declaration of an exported FFI function in the C header file generally looks like
the following:
```c++
CError FBAdd(
OMRF_IN_PARAM_TY(uint32_t, in_a),
OMRF_IN_PARAM_TY(uint32_t, in_b),
OMRF_OUT_PARAM_TY(uint32_t, out_rv),
OMRF_OUT_PARAM_TY(bool, out_overflow));
```
## 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).