Skip to content

[Coding Guideline]: Use matching types at the language boundary #137

Open
@darkwisebear

Description

@darkwisebear

Chapter

FFI

Guideline Title

Use matching type declarations at the language boundary

Category

Required

Status

Draft

Release Begin

1.0.0

Release End

latest

FLS Paragraph ID

fls_v24ino4hix3m

Decidability

Decidable

Scope

Crate

Tags

undefined-behavior,reduce-human-error

Amplification

If it is required or advisable (e.g. to provide a "rusty" interface) to use different types on the Rust side than on the foreign function side, the respective type changes shall not be done on the FFI boundary but on an additional layer above the FFI level.

Exception(s)

No response

Rationale

If the languages on the FFI boundary to not agree on the type or its layout, size and alignment properties, undefined behavior might be invoked. It is therefore critical to reduce the possibility of such misalignment to an absolute minimum. Developers and/or tools shall therefore follow a set of strict rules that govern how a foreign type definition shall be translated to Rust.

Since the only ubiquitously supported foreign calling ABI is the calling ABI of the C programming language, this rule will state how C types are to be translated. For any other language or ABI, it is required to document the respective translation rules.

It is recommended that tooling is used to automate the generation of matching declarations where possible. If this is not possible (e.g. due to the pre-existence of code), it is recommended to set up tooling that is able to check the consistency of the type declarations.

Non-Compliant Example - Prose

The example shows the import of a single function from C which populates a given out parameter with data about a file. Looking at both type definitions of the second parameter, we can see that types are used which might or might not match, depending on the used platform triple and the definition of size_t. While the resulting program might run perfectly well on your favorite 64 bit host platform, other platforms like a 16 bit embedded platform will most likely fail.

Non-Compliant Example - Code

/* C side */
typedef struct __file_info {
size_t size;
int epoch_time;
} file_info;

int get_name_size(const char* path, file_info* info_out) { ... }

// Rust side
use std::ffi;

#[repr(C)]
struct FileInfo {
size: i64,
epoch_time: i32,
}

unsafe {
#[no_mangle]
extern "C" fn get_name_size(path: *const ffi::c_char, file_info: *mut FileInfo) -> std::ffi::c_int;
}

Compliant Example - Prose

By picking matching types for the Rust extern declaration, we ensure the usage of a type that is understood in the same way on both the Rust and the C side. The type to choose is unambiguous - for each type on C side, it is exactly specified which basic type or compound type to use on Rust side.

Compliant Example - Code

/* C side */
typedef struct __file_info {
size_t size;
int epoch_time;
} file_info;

int get_name_size(const char* path, file_info* info_out) { ... }

// Rust side
use std::ffi;

#[repr(C)]
struct FileInfo {
size: libc::size_t,
epoch_time: std::ffi::c_int,
}

unsafe {
#[no_mangle]
extern "C" fn get_name_size(path: *const ffi::c_char, file_info: *mut FileInfo) -> std::ffi::c_int;
}

Metadata

Metadata

Assignees

Labels

category: requiredA coding guideline with category requiredchapter: fficoding guidelineAn issue related to a suggestion for a coding guidelinedecidability: decidableA coding guideline which can be checked automaticallyscope: crateA coding guideline that can be determined applied at the crate levelstatus: draft

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions

    pFad - Phonifier reborn

    Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

    Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


    Alternative Proxies:

    Alternative Proxy

    pFad Proxy

    pFad v3 Proxy

    pFad v4 Proxy