--- title: "Downstream C API" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Downstream C API} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>" ) ``` Rminibwa alignment batches are native external pointers with borrowed column buffers. R users can inspect them through ALTREP vectors, but downstream packages should consume them through the installed C header: ```c #include ``` The header resolves functions with `R_GetCCallable()`. A downstream package therefore needs `LinkingTo: Rminibwa` for the header and an ordinary R package runtime dependency to ensure Rminibwa is loaded before the first call. This vignette uses `Rtinycc` to compile the downstream consumer in-process. The C source is displayed with Rtinycc's C rendering helper and compiled from the same `rminibwa_capi_code` object. ## Build a tiny alignment batch ```{r tiny-batch} library(Rminibwa) td <- tempfile("rminibwa-capi-") dir.create(td) ref <- paste(rep("ACGT", 1000), collapse = "") fa <- file.path(td, "ref.fa") writeLines(c(">chr1", ref), fa, useBytes = TRUE) prefix <- file.path(td, "idx") mb_index_build(fa, prefix, threads = 1L) idx <- mb_index_load(prefix) aln <- charToRaw(substr(ref, 1L, 100L)) |> mb_map(idx, opt = mb_opts("sr", out_n = 0L), name = charToRaw("read1")) mb_align_n(aln) mb_align_col(aln, "tid")[[1]] ``` ## The downstream C consumer ```{r c-consumer-source, echo = FALSE, results = "asis"} capi_candidates <- c( file.path("inst", "capi", "rminibwa_tinycc_consumer.c"), file.path("..", "inst", "capi", "rminibwa_tinycc_consumer.c"), system.file("capi", "rminibwa_tinycc_consumer.c", package = "Rminibwa") ) capi_path <- capi_candidates[file.exists(capi_candidates)][[1L]] rminibwa_capi_code <- paste(readLines(capi_path, warn = FALSE), collapse = "\n") Rtinycc:::rtinycc_c_block(rminibwa_capi_code) ``` ## Compile and call it with Rtinycc ```{r compile-c-consumer} ffi <- Rtinycc::tcc_ffi() |> Rtinycc::tcc_include(system.file("include", package = "Rminibwa")) |> Rtinycc::tcc_source(rminibwa_capi_code) |> Rtinycc::tcc_bind( rminibwa_capi_summary = list(args = list("sexp"), returns = "sexp") ) |> Rtinycc::tcc_compile() ffi$rminibwa_capi_summary(aln) ``` The C function never asks R to materialize a data frame. It receives the batch SEXP, obtains the opaque `RmbAlignBatch *`, and reads borrowed `int32_t`, `int64_t`, and packed CIGAR buffers directly. ```{r cleanup, include = FALSE} unlink(td, recursive = TRUE) ```