---
title: "Getting Started with Rtinycc"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Getting Started with Rtinycc}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>"
)
tcc_bind <- Rtinycc::tcc_bind
tcc_compile <- Rtinycc::tcc_compile
tcc_ffi <- Rtinycc::tcc_ffi
tcc_global <- Rtinycc::tcc_global
tcc_include_paths <- Rtinycc::tcc_include_paths
tcc_lib_paths <- Rtinycc::tcc_lib_paths
tcc_link <- Rtinycc::tcc_link
tcc_path <- Rtinycc::tcc_path
tcc_source <- Rtinycc::tcc_source
```

`Rtinycc` bundles TinyCC and exposes two layers:

- low-level helpers for working with the bundled compiler and `libtcc`
- a higher-level FFI interface for compiling small C fragments into callable R functions

The package is designed around explicit data conversion. You declare the C
signature you want, `Rtinycc` generates the wrapper code, and the compiled
object exposes ordinary R-callable functions.

## Toolchain Paths

The bundled TinyCC installation is discoverable from R:

```{r}
tcc_path()
tcc_include_paths()
tcc_lib_paths()
```

These helpers are useful when you need to inspect the bundled toolchain or
bridge `Rtinycc` with other build logic.

## A Minimal FFI Example

The usual entry point is `tcc_ffi()`. You add C source, declare the function
signatures you want to expose, and compile once:

```{r}
ffi <- tcc_ffi() |>
  tcc_source(
    "
    static double affine(double x, double slope, double intercept) {
      return slope * x + intercept;
    }
    "
  ) |>
  tcc_bind(
    affine = list(
      args = list("f64", "f64", "f64"),
      returns = "f64"
    )
  ) |>
  tcc_compile()

ffi$affine(2, 3, 4)
```

The wrapper takes care of converting R numerics to `double` and converting the
C return value back to an R scalar.

## Managing Globals

You can also expose C globals through generated getter and setter helpers:

```{r}
ffi_globals <- tcc_ffi() |>
  tcc_source(
    "
    int shared_counter = 1;

    void bump_counter(void) {
      shared_counter += 1;
    }
    "
  ) |>
  tcc_bind(
    bump_counter = list(args = list(), returns = "void")
  ) |>
  tcc_global("shared_counter", "i32") |>
  tcc_compile()

ffi_globals$global_shared_counter_get()
ffi_globals$bump_counter()
ffi_globals$global_shared_counter_get()
```

This pattern is useful for wrapping small stateful C helpers without dropping
to the lower-level `libtcc` API.

## When to Use `tcc_link()`

`tcc_compile()` is for source you provide directly. `tcc_link()` is for binding
to functions that already exist in a shared library. The high-level binding
format is the same, so you can move between generated code and linked code
without changing the R-side calling convention. See the
`Linking External Libraries` vignette for the external-linking workflow and the
platform-specific runtime notes.
