The hardware and bandwidth for this mirror is donated by METANET, the Webhosting and Full Service-Cloud Provider.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]metanet.ch.

rdyncall rdyncall logo

CRAN status R-CMD-check

rdyncall provides an R interface to the DynCall libraries. It is a low-level Foreign Function Interface (FFI) for loading shared C libraries, resolving symbols, calling C functions from R by signature, working with C struct and union data, and exposing R functions as C callback pointers.

The package is intended for developers who already know the C API they want to call and need an exploratory or dynamic binding layer from R without writing a compiled wrapper for every function.

Showcase

rdyncall can call into native libraries directly from R: generate an SDL3 binding package from DynPort metadata, open a real SDL3 window, or bind raylib drawing calls and drive a rotating 3D scene.

SDL3 generated binding package raylib 3D rendering from R
Terminal recording of an SDL3 DynPort package opening a window from rdyncall Terminal recording of a raylib 3D cube example driven through rdyncall
Animated SDL3 window with moving text rendered through rdyncall Animated raylib 3D cube rendered through rdyncall

Installation

install.packages("rdyncall")

You can install the development version from GitHub:

remotes::install_github("hongyuanjia/rdyncall")

Quick Start

Generated DynPort packages can be called through ordinary package namespaces:

dynport(SDL3, package = "SDL3")
SDL3::SDL_GetPlatform()
## [1] "macOS"

You can also call a C function directly by loading a library, resolving a symbol, and providing a call signature:

library(rdyncall)

mathlib <- dynfind(c("msvcrt", "m", "m.so.6"))
sqrt_addr <- dynsym(mathlib, "sqrt")

dyncall(sqrt_addr, "d)d", 144)

The signature "d)d" means one C double argument and a C double return value. Signatures must match the target C function type.

R functions can also be wrapped as C callback pointers:

add <- ccallback("ii)i", function(x, y) x + y)
dyncall(add, "ii)i", 20L, 3L)

Foreign aggregate layouts are described once and then used through raw-backed objects:

cstruct("Rect{ssSS}x y w h;")

rect <- cdata(Rect)
rect$x <- 40
rect$y <- 60
rect$w <- 10
rect$h <- 15

rect$w * rect$h
## [1] 150

Learn rdyncall

The pkgdown articles are the main documentation path:

API Map

Structs, Unions and Memory

rdyncall can model ordinary C struct and union layouts and supports several layout features needed by real C APIs:

For callbacks, ccallback() supports aggregate by-value arguments and returns on the implemented x86_64 and ARM64 dyncallback backends.

DynPort Bindings

dynport() is the package-level mechanism for binding a C API from a data file. The current implementation supports DCF .dynport files and generates ordinary on-disk R packages whose namespace is populated from the DynPort metadata.

The package ships one maintained DynPort example, inst/dynports/SDL3.dynport, generated from SDL3 headers with porter. See the generated-binding articles for how to create DynPort metadata for a C library, load it with dynport(), and run a non-GUI SDL3 smoke test.

Demos

Run demo(package = "rdyncall") to list installed demos. The package includes small examples for direct FFI calls, callbacks, qsort, stdio, GLPK, libxml2, SDL3 and raylib.

Some demos require system shared libraries or open GUI windows. For non-interactive environments, see the Non-GUI demos article.

See the Non-GUI demos article for XML parsing, C sorting, GLPK optimization, and stdio examples. The GUI demos article shows SDL3 and raylib examples with release-hosted media clips.

Safety

This is a low-level FFI. A wrong function address, call signature, calling convention, pointer lifetime or struct layout can crash the R process. Keep the C declaration beside the R signature when writing bindings, and hold an R reference to callback objects for as long as foreign code may call them. Read the FFI safety boundaries article before binding APIs that allocate memory, store pointers, register callbacks, or run event loops.

Project Status

This repository is the active maintenance branch for modern R. Recent work has restored compilation on current toolchains, refreshed the bundled DynCall source, modernized CI, added variadic calls, improved dynamic library discovery, and expanded aggregate layout support.

Acknowledgements

rdyncall builds on the DynCall project. The DynCall libraries make portable dynamic calls, callback bridges, and low-level library loading possible across platforms.

This package was originally created by Daniel Adler. The current repository continues that work for modern R toolchains and expands the package with updated documentation, demos, and binding workflows.

The optional Rtinycc package by Sounkou Mahamane Toure is also a strong companion for rdyncall. It makes it possible to compile small C kernels at runtime from R, while rdyncall can bind the surrounding native libraries and call through function pointers.

References

These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.