Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Types

Every place the converter prints a type goes through Convert(QualType). It first asks the type rules for a mapping, so library types and typedef names such as size_t are resolved by rules, and only falls back to the Visit*Type methods for the built-in and user-defined types described here.

Given

struct Item {
  int id;
  char name[8];
  std::vector<int> refs;
};

int count(Item item) { return item.id; }

the unsafe model produces (attributes and trait impls omitted)

#![allow(unused)]
fn main() {
pub struct Item {
    pub id: i32,
    pub name: [libc::c_char; 8],
    pub refs: Vec<i32>,
}
pub unsafe fn count_0(mut item: Item) -> i32 {
    return item.id;
}
}

and the refcount model produces

#![allow(unused)]
fn main() {
pub struct Item {
    #[offset(0)]
    pub id: i32,
    #[offset(4)]
    pub name: Value<Box<[u8]>>,
    #[offset(16)]
    pub refs: Value<Vec<i32>>,
}
pub fn count_0(item: Item) -> i32 {
    let item: Value<Item> = Rc::new(RefCell::new(item));
    return (*item.borrow()).id;
}
}

Fields are stored inline in their struct, so a whole struct lives in a single Value, like the elements of an array; only arrays and vectors are Values of their own (see Boxing). A pointer to a field records the allocation of the struct plus the byte offset of the field in it, which the #[offset(N)] attributes give (see Pointers to fields).