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.
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:
::install_github("Enchufa2/RcppXPtrUtils") remotes
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>
(T func, double l) {
NumericVector core_processingdouble accum = 0;
for (int i=0; i<1e3; i++)
+= sum(as<NumericVector>(func(3, l)));
accum return NumericVector(1, accum);
}
// [[Rcpp::export]]
(Function func, double l) {
NumericVector execute_rreturn 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]]
(SEXP func_, double l) {
NumericVector execute_cpp= *XPtr<funcPtr>(func_);
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)
<- function(n, l) rexp(n, l)
func_r <- cppXPtr("SEXP foo(int n, double l) { return rexp(n, l); }")
func_cpp
::microbenchmark(
microbenchmarkexecute_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'.
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.