callme

{callme} compiles inline C code and generates wrappers so that the C code can be easily called from R.

Features:

What’s in the box

Installation

This package can be installed from CRAN

install.packages('callme')

You can install the latest development version from GitHub with:

# install.package('remotes')
remotes::install_github('coolbutuseless/callme')

Pre-built source/binary versions can also be installed from R-universe

install.packages('callme', repos = c('https://coolbutuseless.r-universe.dev', 'https://cloud.r-project.org'))

Example

The following example compiles a code snippet into a C library and creates a wrapper function in R (of the same name) which can be used to call the compiled code.

library(callme)

code <- "
#include <R.h>
#include <Rinternals.h>

// Add 2 numbers
SEXP add(SEXP val1, SEXP val2) {
  return ScalarReal(asReal(val1) + asReal(val2));
}

// Multiply 2 numbers
SEXP mul(SEXP val1, SEXP val2) {
  return ScalarReal(asReal(val1) * asReal(val2));
}

// sqrt elements in a vector
SEXP new_sqrt(SEXP vec) {
  SEXP res = PROTECT(allocVector(REALSXP, length(vec)));
  double *res_ptr = REAL(res);
  double *vec_ptr = REAL(vec);
  for (int i = 0; i < length(vec); i++) {
    res_ptr[i] = sqrt(vec_ptr[i]);
  }
  
  UNPROTECT(1);
  return res;
}
"

# compile the code
compile(code)

# Call the functions
add(99.5, 0.5)
#> [1] 100
mul(99.5, 0.5)
#> [1] 49.75
new_sqrt(c(1, 4, 25, 999))
#> [1]  1.00000  2.00000  5.00000 31.60696

Linking against an installed library

In this example we want to get the version of the zstd library (which has already been installed on the computer), and return it as a character string.

We need to tell R when compiling the code:

Note: This code works for zstd installed via homebrew on macOS. Paths will be different for other operating systems.

code <- r"(
#include <R.h>
#include <Rinternals.h>
#include "zstd.h"
  
SEXP zstd_version() {
  return mkString(ZSTD_versionString());
}
)"

# Compile the code 
compile(code, 
       PKG_CPPFLAGS = "-I/opt/homebrew/include", 
       PKG_LIBS     = "-L/opt/homebrew/lib -lzstd")

# Call the function
zstd_version()
#> [1] "1.5.6"

References

R project official documentation