The RcppXPtrUtils package provides the means to compile user-supplied C++ functions with ‘Rcpp’ and retrieve an XPtr that can be passed to other C++ components.
Install the release version from CRAN:
install.packages("RcppXPtrUtils")
The installation from GitHub can be done with the remotes package:
remotes::install_github("Enchufa2/RcppXPtrUtils")
Let’s suppose we have a package with a core written in C++, connected to
an R API with Rcpp. It accepts a user-supplied R function to perform
some processing:
#include <Rcpp.h>
using namespace Rcpp;
template <typename T>
NumericVector core_processing(T func, double l) {
  double accum = 0;
  for (int i=0; i<1e3; i++)
    accum += sum(as<NumericVector>(func(3, l)));
  return NumericVector(1, accum);
}
// [[Rcpp::export]]
NumericVector execute_r(Function func, double l) {
  return core_processing<Function>(func, l);
}
But calling R from C++ is slow, so we can think about improving the
performance by accepting a compiled function. In order to do this, the
core can be easily extended to accept an XPtr to a compiled function:
typedef SEXP (*funcPtr)(int, double);
// [[Rcpp::export]]
NumericVector execute_cpp(SEXP func_, double l) {
  funcPtr func = *XPtr<funcPtr>(func_);
  return core_processing<funcPtr>(func, l);
}
To easily leverage this feature, the RcppXPtrUtils package provides
cppXPtr(), which compiles a user-supplied C++ function using
Rcpp::cppFunction() and returns an XPtr:
# compile the code above
# Rcpp::sourceCpp(code='...')
library(RcppXPtrUtils)
func_r <- function(n, l) rexp(n, l)
func_cpp <- cppXPtr("SEXP foo(int n, double l) { return rexp(n, l); }")
microbenchmark::microbenchmark(
  execute_r(func_r, 1.5),
  execute_cpp(func_cpp, 1.5)
)
#> Unit: microseconds
#>                        expr       min        lq       mean     median        uq
#>      execute_r(func_r, 1.5) 14910.161 16261.928 17628.8078 17468.1140 18635.388
#>  execute_cpp(func_cpp, 1.5)   213.123   223.125   310.2708   237.0265   279.808
#>        max neval cld
#>  22657.568   100   b
#>   2417.878   100  a
The object returned by cppXPtr() is just an externalptr wrapped into
an object of class XPtr, which stores the signature of the function.
If you are a package author, you probably want to re-export cppXPtr()
and ensure that user-supplied C++ functions comply with the internal
signatures in order to avoid runtime errors. This can be done with the
checkXPtr() function:
func_cpp
#> 'SEXP foo(int n, double l)' <pointer: 0x55909eb28830>
checkXPtr(func_cpp, "SEXP", c("int", "double")) # returns silently
checkXPtr(func_cpp, "int", c("int", "double"))
#> Error in checkXPtr(func_cpp, "int", c("int", "double")): Bad XPtr signature:
#>   Wrong return type 'int', should be 'SEXP'.
checkXPtr(func_cpp, "SEXP", c("int"))
#> Error in checkXPtr(func_cpp, "SEXP", c("int")): Bad XPtr signature:
#>   Wrong number of arguments, should be 2'.
checkXPtr(func_cpp, "SEXP", c("double", "int"))
#> Error in checkXPtr(func_cpp, "SEXP", c("double", "int")): Bad XPtr signature:
#>   Wrong argument type 'double', should be 'int'.
#>   Wrong argument type 'int', should be 'double'.
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.