Call User-Defined R Function from C++ Using Rcpp Package (Example)

 

With the R package Rcpp we cannot only define and call C++ functions from R, but also integrate R functions in these C++ codes. Here, we show you how. If you are new to the Rcpp package, make sure to first take a look at our blog post about Rcpp.

This post is structured as follows.

Let’s get started!

 

Why Would We Want to Call User-Defined R Functions in C++ Code Via Rcpp?

As a user of R, for elaborate operations, loops that cannot be vectorized, and for functions that need to be executed frequently, it can be useful to compile some code in the C++ programming language via the Rcpp package. The so compiled C++ functions can then be used in R such as regular functions. The result of having some functions written in C++ instead of R is usually a more efficient code.

The only disadvantage of Rcpp and C++ for R users is that it takes some time to get used to the C++ programming language. Especially for functions where we don’t expect a big efficiency gain by rewriting R code to C++ code, it can be more convenient to leave these functions as R functions. The Rcpp package allows us not only to compile C++ code for use in R, but also to use R functions in this C++ code. This allows us to have R and C++ code work together. Furthermore, we might want to call some already defined R functions, for example from certain packages, in C++.

One note: Just because an R function is called within C++, it is still an R function. We do not achieve any efficiency gain just by calling R functions in C++!

 

Example 1: Call Self-Defined R Function

We want to define a function in R and then use it in the C++ code via R package Rcpp.

For that, we first load the Rcpp package.

if (!require('Rcpp', quietly = TRUE)) { install.packages('Rcpp') } 
library('Rcpp') # Load package 'Rcpp'

We define a simple example function called “fun_r” in R which calculates the element-wise sinus of the sum of two vectors.

fun_r <- function (x, y) {
  return (sin(x + y))
}

We define C++ function fun_cpp() which uses R function fun_r().

cppFunction(' 
NumericVector fun_cpp(NumericVector a, NumericVector b){
 
    // Make the self-defined R function "fun_r" available in the
    // C++ code. It is called "fun_r_in_cpp".
    Function fun_r_in_cpp("fun_r");   
 
    // Use function "fun_r_in_cpp"
    NumericVector result = fun_r_in_cpp(a, b);
 
    return result;
}
')

In the above code you see that it is necessary to first make the R function available in C++. We do this by using Function fun_r_in_cpp(“fun_r”). That is, we assign the function the name “fun_r_in_cpp”. Then, we can use function fun_r_in_cpp() in the C++ code.

Let’s check whether the function is returning the right values.

fun_cpp(a = c(4.5, 6), b = c(2,6))
# [1]  0.2151200 -0.5365729
 
fun_r(  x = c(4.5, 6), y = c(2,6))
# [1]  0.2151200 -0.5365729

Similar to R, there are different ways to set the arguments of the R functions in C++. In the above example we just plugged in “a” and “b” of function fun_cpp() at the spots for function argument “x” and “y” of function fun_r(). To make sure we set the arguments to the right objects, we recommend to explicitly call the argument names instead. The following code shows three ways to do that.

cppFunction(' 
NumericVector fun_cpp(NumericVector a, NumericVector b){
 
  // Make the self-defined function "fun_r" available in the
  // C++ code. It is called "fun_r_in_cpp".
  Function fun_r_in_cpp("fun_r");   
 
  // The following 3 lines give the same results
  NumericVector result  = fun_r_in_cpp(Named("x")=a, Named("y")=b);
  NumericVector result2 = fun_r_in_cpp(Named("x", a), Named("y", b));
  NumericVector result3 = fun_r_in_cpp(a, b);
 
  // You can see that by using "Rcout" to return the resulting values
   Rcout << R"_(fun_r_in_cpp(Named("x")=a, Named("y")=b)   returns   )_"   << result  << "\\n" << std::endl;
   Rcout << R"_(fun_r_in_cpp(Named("x", a), Named("y", b))   returns   )_" << result2 << "\\n" << std::endl;
   Rcout << R"_(fun_r_in_cpp(a, b)   returns   )_"                         << result3 << "\\n" << std::endl;
 
  return result;
}
')

Let’s execute the function. The Rcout commands print the results of the different ways of using the R function in C++.

fun_cpp(a = c(4.5, 6), b = c(2,6))
 
# fun_r_in_cpp(Named("x")=a, Named("y")=b)   returns   0.21512 -0.536573
# 
# fun_r_in_cpp(Named("x", a), Named("y", b))   returns   0.21512 -0.536573
# 
# fun_r_in_cpp(a, b)   returns   0.21512 -0.536573
# 
# [1]  0.2151200 -0.5365729

All three different versions give the same results.

 

Example 2: Call R Function From an R Package

Now we want to call an R package function in the C++ code. We take the cov() function from the stats package. For two input matrices, the function calculates the covariances of the matrix columns. When you are unsure to which package an R function like cov() belongs to, just try the following code.

?cov

You see the package name “stats” in the upper left corner of the help page.

We call R function cov() within a C++ function like in the following code:

cppFunction(' 
NumericMatrix fun_cpp(NumericMatrix A, NumericMatrix B){
 
    // Obtain the namespace of the stats package.
    // The namespace is assigned to "stats_env".
    Environment stats_env = Environment::namespace_env("stats");
 
    // From the above defined "stats_env", we get function "cov" and 
    // assign it to "fun_cov_in_cpp".
    Function fun_cov_in_cpp = stats_env["cov"];
 
    // Now we can use the above defined function "fun_cov_in_cpp" in the C++ code.
    return fun_cov_in_cpp(A, B);
}
')

Check the function.

# Example function input matrices
set.seed(5)
mat_A <- matrix(rnorm(50*2), nrow = 50, ncol = 2) 
mat_B <- matrix(rnorm(50*2), nrow = 50, ncol = 2) 
 
stats::cov(mat_A, mat_B)
 
#            [,1]       [,2]
# [1,] 0.03282022 -0.1439654
# [2,] 0.15209587  0.2109052
 
fun_cpp(mat_A, mat_B)
 
#            [,1]       [,2]
# [1,] 0.03282022 -0.1439654
# [2,] 0.15209587  0.2109052

To include a package function instead of a self-defined function, we only have to include an extra line of code which refers to the namespace of the package in which the function, in this case cov(), is defined.

 

Video & Further Resources

If you are interested to learn more, we recommend you to have a look at the Rcpp Sugar documentation by Dirk Eddelbuettel and Romain François. Rcpp sugar provides you with various functions and operators that can be used to write C++ code similar to R syntax. The advantage here is: The code is usually more efficient than the corresponding code in R. We show you some examples of how to use Rcpp sugar here.

We also recommend you to take a look at following video of the YouTube channel of the rusershamburg. In the video, Marvin Wright shows an introduction to Rcpp.

 

Please accept YouTube cookies to play this video. By accepting you will be accessing content from YouTube, a service provided by an external third party.

YouTube Content Consent Button Thumbnail

YouTube privacy policy

If you accept this notice, your choice will be saved and the page will refresh.

 

We also have the following blog posts on https://statisticsglobe.com/ that you might want to take a look at.

 

In this post, we showed you how to include self-written or package R functions into your Rcpp C++ code integration. If you have any questions or comments, let us know below.

 

Anna-Lena Wölwer Survey Statistician & R Programmer

This page was created in collaboration with Anna-Lena Wölwer. Have a look at Anna-Lena’s author page to get more information about her academic background and the other articles she has written for Statistics Globe.

 

Subscribe to the Statistics Globe Newsletter

Get regular updates on the latest tutorials, offers & news at Statistics Globe.
I hate spam & you may opt out anytime: Privacy Policy.


Leave a Reply

Your email address will not be published.

Fill out this field
Fill out this field
Please enter a valid email address.

Menu
Top