API mode for package generation: generate_package_from_headers() now accepts use_api_mode = TRUE to generate packages with compiled struct helpers instead of runtime offset calculation. Generated packages include src/init.c for proper R function registration and src/struct_helpers.c with accessor functions using compiler-computed offsets via offsetof(). This enables correct handling of bitfield structs and eliminates the need for runtime compilation, producing standard R packages that work on systems without compilers.
API mode for bitfield structs: Added compiler-based struct helpers using offsetof() to handle structures with bitfields. Use ffi_create_helpers() to generate constructor and accessor functions with correct compiler-computed offsets. Supports complex structs like htslib's hFILE that mix pointers, bitfields, and regular members.
TinyCC support now comes from Rtinycc; RSimpleFFI no longer builds or vendors its own TinyCC copy during configure.
The test suite now runs under tinytest instead of testthat.
Converted ffi_set_field() and ffi_get_field() to S7 generics with multiple method signatures to support both reflection-based (StructType/UnionType) and compiler-based (API mode) approaches simultaneously.
generate_htslib_package.R tool: Script to generate FFI bindings for
htslib (SAM/BAM/VCF/BCF library) demonstrating package generation capabilities.ffi_struct() and ffi_union() parameter renamed: pack → .pack
packpack = 1 should change to .pack = 1strip_type_qualifiers() - tree-sitter AST parsing handles type
qualifier stripping directly via node type filtering, making the regex-based
approach unnecessary.Fixed anonymous bitfields (e.g., : 30 for padding) causing empty field names
in generated code by checking for node_is_missing() in tree-sitter parsing.
Fixed inline/nested struct definitions generating invalid R code by extracting
just the struct name from struct_specifier nodes instead of the full body text.
Fixed typedef'd anonymous structs/unions/enums being duplicated in typedefs (they are already extracted as structs/unions/enums).
Fixed missing treesitter package import declaration (#2)
treesitter to DESCRIPTION Imports field@importFrom roxygen2 directives for tree-sitter functionstcc_extract_structs(), tcc_extract_unions(), tcc_extract_enums(), tcc_extract_functions(), tcc_extract_typedefs(), tcc_parse_header()ffi_parse_header() now always uses tree-sitter (no use_treesitter parameter)treesitter and treesitter.c are now required dependencies (not optional)use_treesitter = FALSE from any code - tree-sitter handles all valid C syntaxTree-sitter parser is now the only parser:
FILE* open_file(...))__attribute__((packed)) and sets packed attribute on structs/unionspack=1 for packed structs automaticallyStruct allocation helpers are now auto-generated in R bindings:
new_StructName() - allocate and optionally initialize struct instancesStructName_to_list() - convert struct pointer to R listTypedef resolution in function wrappers:
SEXPTYPE → ffi_uint())@param documentation for better IDE supportImproved variadic function handling:
... now generate usage examples using ffi_cif_var() instead of broken wrappersFILE* open_file(...))next, break, etc.) and underscore-prefixed identifiersAdded pack parameter to ffi_struct() for controlling struct alignment:
pack = 1 for byte-packed structs (no padding)pack = 2, 4, 8, or 16 for specific alignment boundariespack = NULL (default) uses natural alignment#pragma pack(n) and MSVC packing behaviorAdded pack parameter to ffi_union() for controlling union alignment:
Added ffi_packed_offset() and ffi_packed_size() for computing packed struct layouts
Added bit-field helper functions for manual bit manipulation:
ffi_pack_bits() / ffi_unpack_bits() - pack/unpack multiple bit-fieldsffi_extract_bit_field() / ffi_set_bit_field() - single field operationsffi_create_bitfield_accessors() - generate accessor functions for bit-field structsffi_longlong() / ffi_ulonglong() storage typesAutomatic bit-field detection and code generation:
: N) in struct definitionsgenerate_r_bindings() auto-generates accessor code when bit-fields are presentpack(), get(), set() operationsAdded typedef extraction from C headers:
tcc_extract_typedefs() parses typedef definitionsgenerate_typedef_definition() generates R code for typedefssort_typedefs_by_dependency()Autogeneration of bindings using tinycc for preprocessing of header files
Centralized C-to-FFI type mappings in get_ffi_type_map():
Added strip_type_qualifiers() for handling const/volatile in type resolution
Added get_resolvable_types() helper function
Added ffi_deref_pointer() to dereference pointer addresses, enabling access to global pointer variables in shared libraries (e.g., R_GlobalEnv, R_NilValue)
Added ffi_read_global() to read typed values from global symbol addresses
Added test global variables (test_global_int, test_global_double, test_global_string, test_global_array) for testing and examples
Added "Dangerous: Calling R API Exported Symbols" section to README demonstrating how to call R's internal C API via FFI
Added examples showing how to access global variables and call Rf_eval, Rf_install, Rf_lang1/2, etc.
Initial release
Core FFI functionality using libffi
Support for basic C types (int, double, float, pointer, string, etc.)
Support for fixed-width integer types (int8, int16, int32, int64, uint8, etc.)
Support for platform-specific types (size_t, ssize_t, long, etc.)
Struct types with ffi_struct(), field access, and nested structs
Array types with ffi_array_type()
Variadic function support with ffi_cif_var()
Closure API for R callbacks (ffi_closure())
Dynamic library loading with dll_load(), dll_compile_and_load()
Memory allocation with ffi_alloc(), ffi_copy_array(), ffi_fill_typed_buffer()