Crate sawp_ffi_derive[][src]

A proc_macro for generating accessors for members of structs and enums

Accessors are compatible with cbindgen for creating FFI

Attributes: #[sawp_ffi(...)]

  • copy: Return Type instead of *const Type. Useful for enums with repr(Integer)
  • skip: Don't generate accessor for member. Note: only public members will have accessors.
  • u8_flag: Return u8 instead of *const Type. Requires member type to be using bitflags macro.
  • type_only: Only generate enum Type and <enum>_get_type. Won't generate accessors for variant fields
  • prefix: Prefix for all functions. eg: <prefix>_<struct_name>_get_<field>

Note: accessors are functions so they will be in snake_case. Struct and Enum names will be converted to snake_case in function names.

Structs

Accessors for structs are of the form:

#[no_mangle]
pub unsafe extern "C" fn struct_name_get_member_name(*const Struct) -> *const Member;

of if either the Member type is a field convertible to a C_FIELD by cbindgen or has the sawp_ffi copy attribute:

#[no_mangle]
pub unsafe extern "C" fn struct_name_get_member_name(*const Struct) -> Member;

Example

extern crate bitflags;
use bitflags::bitflags;
use sawp_ffi_derive::GenerateFFI;

#[repr(u16)]
#[derive(Copy, Clone)]
pub enum Version {
    Version1 = 0x0100,
    Version1_1 = 0x0101,
    Version2 = 0x0200,
}

bitflags! {
    pub struct FileType: u8 {
        const READ = 0b0000_0000;
        const WRITE = 0b0000_0001;
    }
}

#[derive(GenerateFFI)]
#[sawp_ffi(prefix = "sawp")]
pub struct MyStruct {
    pub num: usize,
    #[sawp_ffi(copy)]
    pub version: Version,
    #[sawp_ffi(u8_flag)]
    pub file_type: FileType,
    private: usize,
    #[sawp_ffi(skip)]
    pub skipped: usize,
    pub complex: Vec<u8>,
}

Will result in:

#[no_mangle]
pub unsafe extern "C" fn sawp_my_struct_get_num(my_struct: *const MyStruct) -> usize;

#[no_mangle]
pub unsafe extern "C" fn sawp_my_struct_get_version(my_struct: *const MyStruct) -> Version;

#[no_mangle]
pub unsafe extern "C" fn sawp_my_struct_get_file_type(my_struct: *const MyStruct) -> u8;

#[no_mangle]
pub unsafe extern "C" fn sawp_my_struct_get_complex(my_struct: *const MyStruct) -> *const Vec<u8>;

Enums

Enums will have a flat, C compatible, enum created to define their type. Users of the accessors should first call <enum>_get_type() to determine the enum type and then use the appropriate accessors to get that type's fields. These enums will have the same name as the base enum with Type appended to it.

Note: All enum accessors can return null if the accessor isn't of the correct variant type

Accessors for enums are of the form:

To get the type:

#[no_mangle]
pub unsafe extern "C" fn enum_name_get_type(* const Enum) -> EnumType;

For variants with named fields:

#[no_mangle]
pub unsafe extern "C" fn enum_name_get_variant_name_member_name(e: *const Enum) -> *const Field;

For variants with a single unnamed field:

#[no_mangle]
pub unsafe extern "C" fn enum_name_get_variant_name(e: *const Enum) -> *const Field;

For variants with multiple unnamed fields, N is the field index:

#[no_mangle]
pub unsafe extern "C" fn enum_name_get_variant_name_N(e: *const Enum) -> *const Field;

Unit variants (variants with no fields) will not have any accessors.

Example

extern crate bitflags;
use bitflags::bitflags;
use sawp_ffi_derive::GenerateFFI;

#[repr(u16)]
#[derive(Copy, Clone)]
pub enum Version {
    Version1 = 0x0100,
    Version1_1 = 0x0101,
    Version2 = 0x0200,
}

bitflags! {
    pub struct FileType: u8 {
        const READ = 0b0000_0000;
        const WRITE = 0b0000_0001;
    }
}

#[derive(GenerateFFI)]
pub enum MyEnum {
     UnnamedSingle(u8),
     UnnamedMultiple(u8, u16),
     Named {
        a: u8,
        b: Vec<u8>,
        #[sawp_ffi(u8_flag)]
        file_type: FileType,
     },
     Empty,
}

Will result in:

#[repr(C)]
pub enum MyEnumType {
    UnnamedSingle,
    UnnamedMultiple,
    Named,
    Empty,
}

#[no_mangle]
pub unsafe extern "C" fn my_enum_get_unnamed_single(my_enum: *const MyEnum) -> *const u8;

#[no_mangle]
pub unsafe extern "C" fn my_enum_get_unnamed_multiple_0(my_enum: *const MyEnum) -> *const u8;

#[no_mangle]
pub unsafe extern "C" fn my_enum_get_unnamed_multiple_1(my_enum: *const MyEnum) -> *const u16;

#[no_mangle]
pub unsafe extern "C" fn my_enum_get_named_a(my_enum: *const MyEnum) -> *const u8;

#[no_mangle]
pub unsafe extern "C" fn my_enum_get_named_b(my_enum: *const MyEnum) -> *const Vec<u8>;

#[no_mangle]
pub unsafe extern "C" fn my_enum_get_named_file_type(my_enum: *const MyEnum) -> *const u8;

Derive Macros

GenerateFFI

Derive macro for autogenerated accessors compatible with cbindgen See library documentation for usage examples