{callme} compiles inline C code and generates wrappers so that the C
code can be easily called from R.
Features:
#include directives.CFLAGS, PKG_CPPFLAGS and PKG_LIBS for
setting compiler flags, C pre-processor flags, and library linking
flags, respectively.compile(code, CFLAGS, PKG_CPPFLAGS, PKG_LIBS, env, verbosity)
compile the C code and assign R functions into the nominated env
in R. C code could be as a string or in a file.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'))
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
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:
/opt/homebrew/include directory for zstd.h.zstd library in /opt/homebrew/lib.zstd library (-lzstd)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"