Crate sawp_ffi_derive[][src]

Expand description

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.
  • flag = flag_repr: Return flag_repr instead of *const Type flag_repr should be the repr type of Flag. Requires member type to be sawp_flags::Flags
  • type_only: Only generate enum Type and <enum>_get_type. Won’t generate accessors for variant fields
  • prefix = 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

use sawp_flags::{BitFlags, Flags, Flag};
use sawp_ffi_derive::GenerateFFI;

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

#[repr(u8)]
#[derive(Copy, Clone, Debug, BitFlags)]
pub enum FileType {
    READ = 0b0000_0001,
    WRITE = 0b0000_0010,
}

#[derive(GenerateFFI)]
#[sawp_ffi(prefix = "sawp")]
pub struct MyStruct {
    pub num: usize,
    #[sawp_ffi(copy)]
    pub version: Version,
    #[sawp_ffi(flag=u8)]
    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 sawp_flags;
use sawp_flags::{BitFlags, Flags, Flag};
use sawp_ffi_derive::GenerateFFI;

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

#[repr(u8)]
#[derive(Copy, Clone, Debug, BitFlags)]
pub enum FileType {
    READ = 0b0000_0001,
    WRITE = 0b0000_0010,
}

#[derive(GenerateFFI)]
pub enum MyEnum {
     UnnamedSingle(u8),
     UnnamedMultiple(u8, u16),
     Named {
        a: u8,
        b: Vec<u8>,
        #[sawp_ffi(flag=u8)]
        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;

Special type handling

Strings

If the field type is a String, accessors to get the pointer and length will be generated as well. They will be the field accessor appended with _ptr/_len respectively.

Note: Strings will not be null terminated

Vector

If the field type is a Vector, accessors to get the pointer and length will be generated as well. They will be the field accessor appended with _ptr/_len respectively.

Options

If the field type is an Option, the accessor will return a pointer. If the Option has a value, the pointer will contain that value, otherwise the pointer will be null

sawp_flags::Flags

If the field type is a sawp_flags::Flags, the accessor will return the primative value, ie. the returned value by .bits().

Derive Macros

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