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).