Renaming and Hiding an Exported Rcpp Function in an R Package

Rcpp: calling c++ function in R without exporting c++ function

I think you're probably mixing up the concept of exporting C++ code to be used in R (via // [[Rcpp::export]]), which is entirely different to exporting R functions from your package, i.e. making those functions available to end-users of your package.

To make your Rcpp functions callable from within R at all, you need to // [[Rcpp::export]] them. If you don't do this, none of your C++ code will be available from within your R package.

It sounds like what you would like to do is to use the Rcpp-exported functions within your package but to hide them from end-users. This is a common use case for Rcpp, as it allows you to have an R function that acts as an end-user interface to your C++ code, while leaving you free to alter the C++ implementation in future developments without the risk of breaking existing users' code.

Any function you have created within your package, be it an R function or an Rcpp-exported function, has to actively be exported from your package to make it available to end-users. This is a different concept from // [[Rcpp::export]], which is needed to access C++ functions from within your package's R code.

Any R functions will only be exported from your R package if you specify them in the NAMESPACE file in your project's root directory. Thus to export myfunction() you need to have a line that says export(myfunction) in the NAMESPACE file. You are using roxygen2, which will generate this line automatically as long as you write @export in the roxygen skeleton. An alternative to using roxygen's exporting system is to specify an exportPattern in the NAMESPACE file that uses regex to export only functions whose names match a certain pattern.

My usual workflow is to prefix any Rcpp-exported functions with a period by writing my C++ functions like this:

// [[Rcpp::export(.MyCppFunction)]]
int BoringFunction() { return 0; }

I can now call the C++ function from R like this:

MyRFunction <- function()
{
result <- .MyCppFunction()
return(result)
}

The first line in my NAMESPACE file looks like this:

exportPattern("^[[:alpha:]]+")

Which means that any R function in my package starting with a letter will be exported. Since all the functions I Rcpp::export start with a period, I can use them internally within the R package but they won't be exported to end-users.

In other words, end-users of the package can call MyRFunction() but would get an error if they tried to call .MyCppFunction

How to call R function (which should not be exported) from Rcpp?

You have to get a bit meta here. It is possible to get an environment containing all the unexported functions in a package using the base R function asNamespace. This function itself can be used inside Rcpp. You then create a new Environment from the output of that function, from which you can harvest the unexported function.

As an example, let's get the unexported function ggplot2:::as_lower_ascii to do some work on a string we pass to an Rcpp function:

#include <Rcpp.h>
using namespace Rcpp;

// [[Rcpp::export]]
CharacterVector fun(CharacterVector input){
Function asNamespace("asNamespace");
Environment ggplot_env = asNamespace("ggplot2");
Function to_lower_ascii = ggplot_env["to_lower_ascii"];
return to_lower_ascii(input);
}

So if we source this, then back in R we can do:

fun("HELLO WORLD")
#> [1] "hello world"

How to make invisible functions in R library

If you are only going to use the C++ function within your C++ code, you don't need to use the first instance of the // [[Rcpp::export]] line at all. That way you can still call a() from within b() in your C++ code, but only b will be made available as a function in R.

If you want to be able to use a() as an R function internally within your package, but want to hide it from end-users, you need to export it with a name that starts with a period, so instead of // [[Rcpp::export]], you would type // [[Rcpp::export(.a)]]. Now you will be able to use .a() as a function in your package's R code, but it will be hidden to end-users of your package.

#include <Rcpp.h>

// [[Rcpp::export(.a)]]
int a (int x){
return x+2;
}

// [[Rcpp::export]]
int b(int y){
z = a(y);
return(z);
}

Now, in R you can do this:

> library(MatteosPackage)
> b(1)
[1] 3
>.a(1)
Error in .a(1) : could not find function ".a"
> MatteosPackage::.a(1)
Error: '.a' is not an exported object from 'namespace:MatteosPackage'

rcpp functions not exporting in r package

The importFrom and useDynLib calls in NAMESPACE are important. Either switch to a manually created NAMESPACE file or add

#' @useDynLib thmc, .registration = TRUE
#' @importFrom Rcpp evalCpp

to your roxygen2 code. Here with R-comments, since I would typically use thmc-package.R for this. You can also put this into do_comps.cpp when using C++-comments.

Nesting Rcpp functions

The answers to your question get a little technical quickly, but are all provided in the Rcpp Attributes vignette, and have been for a long time.

First off, you are more-or-less misusing cppFunction(). It is made for quick and simple one-off function tests. Not for writing "infrastructure" or more complex code. For which you should use sourceCpp(), or better still, use a package.

If you switch you code to sourceCpp() and the [[Rcpp::export]] tag you will notice (in verbose=TRUE mode, or in package building) that the exported functions get 'transliterated' into other functions that R calls.

So yes you can nest functions, as you can in C / C++. Nothing is taken from you. But you cannot call the inner, nested function from R but that is possible with the API offered to us by R and which we use (and free you from interfacing directly). It only has SEXP .Call(functionanme, SEXP a, SEXP b,...) as an interface. I.e. a different signature.

But on the C / C++ you can nest, provided you compile your code differently.

Calling a Rcpp function from another Rcpp function while building an R package

Two possible solutions:

The 'quick-and-dirty', solution -- include the function declaration in the file where you use it:

#include <Rcpp.h>
using namespace Rcpp;

// declare fun1
int fun1(int a1);

// [[Rcpp::export]]
Rcpp::NumericVector fun(Rcpp::NumericVector data1)
{
NumericVector fun_data = data1;
int n = data1.size();
for(i=0;i<n;i++){
fun_data[i] = fun1(fun_data[i]);
}
return(fun_data);
}

The more robust solution: write header files that declare the functions, which can then be #include-ed in each file. So you might have a header file fun1.h in the same src directory:

#ifndef PKG_FOO1_H
#define PKG_FOO1_H

int foo(int);

#endif

which you could then use with something like:

#include <Rcpp.h>
#include "fun1.h"
using namespace Rcpp;

// [[Rcpp::export]]
Rcpp::NumericVector fun(Rcpp::NumericVector data1)
{
NumericVector fun_data = data1;
int n = data1.size();
for(i=0;i<n;i++){
fun_data[i] = fun1(fun_data[i]);
}
return(fun_data);
}

As you progress, you're going to need to learn more C++ programming skills, so I recommend checking out one of the books here; in particular, Accelerated C++ is a great introduction.

Missing import(Rcpp) in NAMESPACE leads to C++ library error during R CMD check of tests

The deprecated file was the only file that had the annotation #' @import Rcpp that made sure devtools::document() would include import(Rcpp) in the NAMESPACE file.

I solved the problem by annotating the main R function of the package that uses Rcpp functions with #' @import Rcpp.

After that, devtools::document() cleaned up the autogenerated files and left the package intact.

I would greatly appreciate if someone who understands R package development better, could explain what went wrong and maybe link to the best resources that explain annotations and the NAMESPACE file! Thank you



Related Topics



Leave a reply



Submit