95 lines
4.5 KiB
Markdown
95 lines
4.5 KiB
Markdown
# FFI Function Signatures
|
|||
|
|
|
||
|
|
Under this section we discuss the signature requirements of the exported FFI
|
||
|
|
functions.
|
||
|
|
|
||
|
|
## C-style Name Export
|
||
|
|
|
||
|
|
FFI functions must be exported under C names, that is, they must not go through the
|
||
|
|
C++ name mangling mechanism.
|
||
|
|
|
||
|
|
In Rust, you need to decorate the function with the `#[unsafe(no_mangle)]` attribute
|
||
|
|
together with `extern "C"`, for example:
|
||
|
|
|
||
|
|
```rust
|
||
|
|
#[unsafe(no_mangle)]
|
||
|
|
pub extern "C" fn WFStartup() -> CError {
|
||
|
|
// Function body omitted...
|
||
|
|
}
|
||
|
|
|
||
|
|
// More FFI functions omitted...
|
||
|
|
```
|
||
|
|
|
||
|
|
## Export Name Style
|
||
|
|
|
||
|
|
In this subsection, we discuss the naming style of exported functions.
|
||
|
|
|
||
|
|
In this design, there are exactly two styles to choose from. We call them the
|
||
|
|
Windows style and the POSIX style. Either style can be chosen freely, but within a
|
||
|
|
single library the two styles must not be mixed.
|
||
|
|
|
||
|
|
We recommend the following selection rule: if your library is Windows-only, choose
|
||
|
|
the Windows style; otherwise, choose the POSIX style.
|
||
|
|
|
||
|
|
### Windows Style
|
||
|
|
|
||
|
|
The Windows style format is `<PREFIX><FUNC>` for ordinary functions, and
|
||
|
|
`<PREFIX><STRUCT><FUNC>` for opaque struct functions.
|
||
|
|
|
||
|
|
In the format, `<STRUCT>` is the name of the opaque struct and `<FUNC>` is the name
|
||
|
|
of the function. Both of them must use PascalCase naming.
|
||
|
|
|
||
|
|
For `<PREFIX>`, it is a prefix identifier that is specific to this library. As we
|
||
|
|
all know, C has no namespace concept, and all functions are exported into the same
|
||
|
|
space. Therefore, avoiding name collisions between functions is an important task.
|
||
|
|
By prepending `<PREFIX>` to the function name, name duplication can be avoided as
|
||
|
|
much as possible. For this reason, you need to choose `<PREFIX>` carefully and try
|
||
|
|
to pick a prefix that is unlikely to collide.
|
||
|
|
|
||
|
|
In the Windows style, there are two spellings for `<PREFIX>`. One is the
|
||
|
|
all-uppercase style and the other is the style in which only the first letter is
|
||
|
|
uppercase and all remaining letters are lowercase. Choose according to your own
|
||
|
|
needs. In addition, the length of `<PREFIX>` must not exceed 5 characters, and
|
||
|
|
it must not contain anything other than letters and digits (that is, underscores are
|
||
|
|
not allowed).
|
||
|
|
|
||
|
|
The following examples show some legal and illegal Windows style function names:
|
||
|
|
|
||
|
|
| Name | Verdict | Reason |
|
||
|
|
|------|---------|--------|
|
||
|
|
| `WFStartup` | Legal | An ordinary (non opaque struct) function. |
|
||
|
|
| `WFIconGetHandle` | Legal | An opaque struct function whose `<STRUCT>` is `Icon`. |
|
||
|
|
| `WFWordHandleGetHandle` | Legal | An opaque struct function whose `<STRUCT>` is `WordHandle`. |
|
||
|
|
| `FlGetMessage` | Legal | Uses a `<PREFIX>`, which is `Fl`, that capitalizes only its first letter. |
|
||
|
|
| `MyRustGetMessage` | Illegal | `<PREFIX>`, which is `MyRust`, does not keep all remaining letters lowercase. |
|
||
|
|
| `My_RustGetMessage` | Illegal | `<PREFIX>` contains an underscore. |
|
||
|
|
| `IconGetHandle` | Illegal | Missing `<PREFIX>`. |
|
||
|
|
| `QwertyuiopGetData` | Illegal | `<PREFIX>`, which is `Qwertyuiop`, is too long. |
|
||
|
|
| `WFget_message` | Illegal | `<FUNC>`, which is `get_message`, is not PascalCase. |
|
||
|
|
| `WFicon_handleGetMessage` | Illegal | `<STRUCT>`, which is `icon_handle`, is not PascalCase. |
|
||
|
|
|
||
|
|
### POSIX Style
|
||
|
|
|
||
|
|
The POSIX style format is `<PREFIX>_<FUNC>` for ordinary functions, and
|
||
|
|
`<PREFIX>_<STRUCT>_<FUNC>` for opaque struct functions.
|
||
|
|
|
||
|
|
The `<PREFIX>`, `<STRUCT>` and `<FUNC>` components in the format have the same
|
||
|
|
meaning as in the Windows style, but the format is different. `<STRUCT>` and `<FUNC>`
|
||
|
|
must use snake_case naming. `<PREFIX>` must be all lowercase, and it must not contain
|
||
|
|
anything other than letters and digits (that is, underscores are not allowed). Its
|
||
|
|
length and selection requirements are the same as in the Windows style.
|
||
|
|
|
||
|
|
The following examples show some legal and illegal POSIX style function names:
|
||
|
|
|
||
|
|
| Name | Verdict | Reason |
|
||
|
|
|------|---------|--------|
|
||
|
|
| `wf_startup` | Legal | An ordinary (non opaque struct) function. |
|
||
|
|
| `wf_icon_get_handle` | Legal | An opaque struct function whose `<STRUCT>` is `icon`. |
|
||
|
|
| `wf_word_handle_get_handle` | Legal | An opaque struct function whose `<STRUCT>` is `word_handle`. |
|
||
|
|
| `Fl_get_message` | Illegal | `<PREFIX>`, which is `Fl`, is not all lowercase. |
|
||
|
|
| `my_rust_get_message` | Illegal | `<PREFIX>`, which is `my_rust`, contains an underscore. |
|
||
|
|
| `icon_get_handle` | Illegal | Missing `<PREFIX>`. |
|
||
|
|
| `qwertyuiop_get_data` | Illegal | `<PREFIX>`, which is `qwertyuiop`, is too long. |
|
||
|
|
| `wf_GetMessage` | Illegal | `<FUNC>`, which is `GetMessage`, is not snake_case. |
|
||
|
|
| `wf_Icon_get_message` | Illegal | `<STRUCT>`, which is `Icon`, is not snake_case. |
|