Rcpp: Include header from package into cppFunction - r

I have a package that uses Rcpp. It has different C++ function defined int src/testr.h. Now at some point I need to generate Rcpp functions (using cppFunction or cxxfunction) that use things defined in src/testr.h. How can I do that?
I tried,
> cxxfunction(signature(x="list") includes = c('#include "testr.h"'), body=sprintf(template, name, name))
> Rcpp::cppFunction(depends = "testr", includes = c('#include "src/testr.h"'), sprintf(template, name, name))
But
file7086270f0da.cpp:7:10: fatal error: 'testr.h' file not found
#include "testr.h"
^

Quick suggestion:
Move the header to inst/include/testr.h;
This requires a src/Makevars entry such as PKG_CPPFLAGS = -I../inst/include to have the compilation look there.
Now with the package installed as, say, mypkg, you can add a depends="mypkg" and R will know to set a -I... for you.
We use the same trick all the time in e.g. BH and various Rcpp* packages.

Related

Exporting C++ code from an R package with Rcpp::interfaces(r, cpp) throws error `PACKAGE_RcppExport_registerCCallable" not available for .Call()`

I'm trying to export C++ functions from my R package 'TreeTools' so they can be called from a different package. I've added the line
// [[Rcpp::interfaces(r, cpp)]]
to src/renumber_tree.cpp, per [https://dirk.eddelbuettel.com/code/rcpp/Rcpp-attributes.pdf / http://r-pkgs.had.co.nz/src.html] and when I compileAttributes() and document() the package, there are indicators that the export has been acknowledged:
Relevant header files are added to inst/includes;
#include "../inst/include/TreeTools.h" is added to the start of RcppExports.cpp
A function RcppExport SEXP _TreeTools_RcppExport_registerCCallable() is added to the end of RcppExports.cpp
Compliation nevertheless fails with
Error in .Call("_TreeTools_RcppExport_registerCCallable", PACKAGE = "TreeTools") :
"_TreeTools_RcppExport_registerCCallable" not available for .Call() for package "TreeTools"
Can anyone help me to debug this error?
Could it be related to the fact that I have a manually-generated PACKAGE-init.c file?
Thanks, Dirk, for pointing me in the right direction.
To TreeTools-init.C, I needed to add
extern SEXP _TreeTools_RcppExport_registerCCallable();
and
static const R_CallMethodDef callMethods[] = {
&_TreeTools_RcppExport_registerCCallable, 0},
{NULL, NULL, 0}
};
In RcppExports.R, I saw
# Register entry points for exported C++ functions
methods::setLoadAction(function(ns) {
.Call('_TreeTools_RcppExport_registerCCallable', PACKAGE = 'TreeTools')
})
Replacing the straight quotes around '_TreeTools_RcppExport_registerCCallable' with backticks, i.e.
`_TreeTools_RcppExport_registerCCallable`
allowed the package to load.
Of course, these are replaced with straight quotes whenever compileAttributes() is run, so this doesn't feel like a complete solution...

Rcpp functions undefined when used alongside Stan

I have an R package that uses Rcpp for some internal functions. These functions are not exported for the user to access directly (see minimally reproducible example in the rcpptest repository).
I am now attempting to add Stan code to the src/ directory to be compiled when the package is installed (reproducible example in the rcppstan repository). However, when I modify the package to work with Stan, I get the following error in R CMD CHECK:
#> ❯ checking R code for possible problems ... NOTE
#> meanC: no visible binding for global variable ‘_rcppstan_meanC’
#> Undefined global functions or variables:
#> _rcppstan_meanC
And indeed, when I try to call the R function that uses the meanC function, I get an error saying Error in meanC(x) : object '_rcppstan_meanC' not found.
From what I can tell, here is what is changing when I modify the package to work with rstan, and thus the likely cause.
When only using Rcpp, the following is in the src/RcppExports.cpp:
static const R_CallMethodDef CallEntries[] = {
{"_rcpptest_timesTwo", (DL_FUNC) &_rcpptest_timesTwo, 1},
{NULL, NULL, 0}
};
RcppExport void R_init_rcpptest(DllInfo *dll) {
R_registerRoutines(dll, NULL, CallEntries, NULL, NULL);
R_useDynamicSymbols(dll, FALSE);
}
When Stan is incorporated, that code is no longer generated in the src/RcppExports.cpp file. Instead, it appears that this is being handles by the src/init.cpp file created by the rstantools package. The relevant chunk from that file is here:
static const R_CallMethodDef CallEntries[] = {
{NULL, NULL, 0}
};
void attribute_visible R_init_rcppstan(DllInfo *dll) {
// next line is necessary to avoid a NOTE from R CMD check
R_registerRoutines(dll, NULL, CallEntries, NULL, NULL);
R_useDynamicSymbols(dll, TRUE); // necessary for .onLoad() to work
}
Why does the code in src/init.cpp make the Rcpp functions undefined? Conversely, is there a way to edit src/init.cpp so that the Stan models are able to compile and be accessed correctly, while still allowing the Rcpp functions to be defined?
The init.cpp takes of registering methods and Makevars inhibits compilation of the cpp files. With the following changes in Makevars (and Makevars.win) I got it to compile:
diff --git a/src/Makevars b/src/Makevars
index 7aedc5b..3ea312e 100644
--- a/src/Makevars
+++ b/src/Makevars
## -1,8 +1,9 ##
STANHEADERS_SRC = `"$(R_HOME)/bin$(R_ARCH_BIN)/Rscript" --vanilla -e "cat(system.file('include', 'src', package = 'StanHeaders'))"`
PKG_CPPFLAGS = -I"../inst/include" -I"$(STANHEADERS_SRC)" -DBOOST_RESULT_OF_USE_TR1 -DBOOST_NO_DECLTYPE -DBOOST_DISABLE_ASSERTS -DEIGEN_NO_DEBUG -DBOOST_MATH_OVERFLOW_ERROR_POLICY=errno_on_error
-SOURCES = $(wildcard stan_files/*.stan)
-OBJECTS = $(SOURCES:.stan=.o) init.o
+CPP_SOURCES = $(wildcard *.cpp)
+STAN_SOURCES = $(wildcard stan_files/*.stan)
+OBJECTS = $(STAN_SOURCES:.stan=.o) $(CPP_SOURCES:.cpp=.o)
all: $(SHLIB)
#if test -e "/usr/bin/install_name_tool" && test -e "/usr/local/clang4/lib/libc++.1.dylib" && test -e "/usr/lib/libc++.1.dylib"; then /usr/bin/install_name_tool -change /usr/local/clang4/lib/libc++.1.dylib /usr/lib/libc++.1.dylib $(SHLIB); fi
After calling Rcpp::compileAttributes() the method registration was again present in RcppExports.cpp. When I tried R CMD INSTALL, I got an error from .onLoad(), c.f. https://github.com/stan-dev/rstanarm/issues/190. Using the workaround from there, i.e. R CMD INSTALL --preclean solved the issue first, but was not reliable. What solved the issue for me was to change
R_useDynamicSymbols(dll, FALSE);
into
R_useDynamicSymbols(dll, TRUE);
in RcppExports.cpp. That is of course problematic, since that file might be overwritten, in particular when RStudio/devtools is used. A rather hacky solution would be to add
RcppExports.o: patch
patch:
sed -i 's/R_useDynamicSymbols(dll, FALSE)/R_useDynamicSymbols(dll, TRUE)/' RcppExports.cpp
.phony: all clean patch
in the Makevars(.win). But in the end the problem seems to be that C++ code for Rcpp modules is generated during package installation in a subdirectory of src. Therefore Rcpp::compileAttributes() cannot include the corresponding methofs in the list of registered methods. I do not see a good solution for that.
Now the package builds, checks and installs with two NOTEs:
N checking installed package size
installed size is 7.8Mb
sub-directories of 1Mb or more:
libs 7.7Mb
N checking for GNU extensions in Makefiles
GNU make is a SystemRequirements.

object 'Cdqrls' not found when building R packages using devtools

I got an error as the title shows
Error: object 'Cdqrls' not found
I use devtools for building R packages, and one function in my current package, I used
.Call(Cdqrls, x[, id1, drop=FALSE] * w, w * z, epsilon)
and also includes a lm.c file in the src folder, which includes:
...
SEXP Cdqrls(SEXP x, SEXP y, SEXP tol)
{
SEXP ans, ansnames;
SEXP qr, coefficients, residuals, effects, pivot, qraux;
int n, ny = 0, p, rank, nprotect = 4, pivoted = 0;
double rtol = asReal(tol), *work;
...
directly copied from R source files. When I used load_all() in devtools, it compiles shared objects in src/ (I checked that works well) with new files: lm.o and MyPkgName.so. However, from the wiki of devtools, I found that
load_all ignores the package NAMESPACE
If working properly, I think by running some functions, I am able to update the NAMESPACE file to contain useDynLib(MyPkgName, Cdqrls). Is that correct? I think in that way the error may disappear... Any suggestions are greatly appreciated!
Update
According to #mnel and this post, it seems that using #useDynLib should work. However, the function I used .Call() is NOT documented, and there are several functions that used .Call so I personally do not wanna document them as they're not used for end-users. Thus, where shall I put #useDynLib?
The answer is to use #useDynLib PkgName Routine1 Routine2 using roxygen2, so that once running document() function in devtools the NAMESPACE file will contain useDynLib(PkgName,Routine1,Routine2), which will work perfectly.

R code to use a function from .cpp file, based on Rcpp package

I am confused by how to use the Rcpp package. What is the R-code to use a R function of newRcppVectorExample, after saving the following .cpp code, says example.cpp? The code is from http://dirk.eddelbuettel.com/code/rcpp.examples.html.
Do I have to create a package? Can I use the example.cpp directly? e.g. R CMD SHLIB example.cpp, then use the dyn.load function.
#include <RcppClassic.h>
#include <cmath>
RcppExport SEXP newRcppVectorExample(SEXP vector) {
BEGIN_RCPP
Rcpp::NumericVector orig(vector);
Rcpp::NumericVector vec(orig.size());
std::transform(orig.begin(), orig.end(), vec.begin(), ::sqrt);
return Rcpp::List::create(Rcpp::Named( "result" ) = vec,
Rcpp::Named( "original" ) = orig) ;
END_RCPP
}
You may want to spend some time with the documentation, both for R itself (ie Writing R Extensions) and Rcpp where you could start with the Rcpp-introduction vignette (which is also our Journal of Statistical Software paper).
In short, one extends R via the .Call() function which can access compiled code loaded via a package, or via dyn.load(). But there is little point in me duplication that material here.
Edit: And given that you found the example you show in the RcppExamples package, here is how it is called in that same package:
RcppVectorExample <- function(vec=seq(1,9)^2, api=c("classic", "new")) {
api <- match.arg(api) # match to classic or new
fun <- paste(api, "RcppVectorExample", sep="")
## Make the call...
val <- .Call(fun, # either new or classic
vec,
PACKAGE="RcppExamples")
val
}
This is slightly more complicated than usually because we can call either the example from the old and deprecated API (which is nevertheless still provided by the RcppClassic package) or the new API (for which you picked the code).
The key is that .Call() is used with a first argument for the C++ function named, followed by a set of arguments and a final argument pointing to the package in which the shared library is found.

Lemon Graph Library on R using Rcpp

I think that this answer is a bit complex because it involves several things.
I want to do high performance computations with R particularly with graphs (networks). As a R package igraph is very nice. But R is slow, so I want to code the computationally expensive routines in C++ (maybe in C). I take a look at the igraph C library and I found it a little messy to work with. I also look at the Boost Graph Library and I read about it that it is difficult to learn. So I eventually found Lemon Graph Library. It is in C++ and seems very nice to work with.
So I installed the Lemon Graph Library as recommended in the official page. Then using the Rcpp and inline packages I manage myself to run Lemon Graph C++ code from R. Here I write in detail what I had made. But basically I put this:
inc <- '
#include <lemon/list_graph.h>
using namespace lemon ;
'
src <- '
int xx = Rcpp::as<int>(x);
int res = xx + 1;
ListDigraph g;
ListDigraph::Node u = g.addNode();
ListDigraph::Node v = g.addNode();
ListDigraph::Arc a = g.addArc(u, v);
int i = countNodes(g);
int j = countArcs(g);
Rprintf("num nodes is %d , and num edges is %d \\n",i,j);
return Rcpp::wrap(res);
'
fun <- cxxfunction( signature(x="numeric"), body=src,include=inc, plugin="Rcpp")
in a myexample_inline.R file and then run a R console and write:
> library("inline")
> library("Rcpp")
> source("myexample_inline.R")
> fun(1)
num nodes is 2 , and num edges is 1
[1] 2
So it works !!! But now I have the following problem. If I make a C++ function (say double func1(g)) that for example calculates some property to some Lemon graph object. How I call that function from the inlined code? I must made func1() as a template function and put it in the include field of cxxfunction()?
Basically: I can't figure out how to call a C++ function inlined in R from another C++ function also inlined in R. Is it possible? Is there another way that do not uses inline code?
Maybe I can do it using Rcpp modules but I couldn't (still) figure out how to do this.
I'm having problems with making modules work. I will keep trying with this, but maybe I can get some kind of hint from here.
I also thought about the possibility to develop (my first) a package. But I had the problem that the Lemon Graph C++ code call the headers in this way (for example):
#include <iostream>
#include <lemon/list_graph.h>
So it means (at least I believe this) that I can not avoid the installation of the Lemon Graph Library. If I want to make a R package of the Lemon Graph Library I have to "rewrite" all the code again !!! So this is not my main option.
Best Regards
I have managed to success to this problem. Here you can find a detailed explanation about what I have done. Maybe, it is trivial to most of the people here, but it may be a good starting point for someone that is in the same position that I was. I will post a resume here of what I done.
First I installed the Lemon Graph (C++) Library (LGL). I just downloaded the LGL from its home page (from here). Then I proceed:
$ tar xvzf lemon-1.2.tar.gz
$ cd lemon-1.2
$ ./configure
$ make
$ make check # This is optional, but recommended. It runs a bunch of tests.
$ sudo make install
Then check if it works. So in a file named mycode.cc I put:
#include <iostream>
#include <lemon/list_graph.h>
using namespace lemon;
using namespace std;
int main()
{
ListDigraph g;
ListDigraph::Node u = g.addNode();
ListDigraph::Node v = g.addNode();
ListDigraph::Arc a = g.addArc(u, v);
cout << "Hello World! This is LEMON library here." << endl;
cout << "We have a directed graph with " << countNodes(g) << " nodes "
<< "and " << countArcs(g) << " arc." << endl;
return 0;
}
Then I compile and run it:
$ g++ -O2 mycode.cc -lemon
... BLA BLA BLA ...
$./a.out
Hello World! This is LEMON library here.
We have a directed graph with 2 nodes and 1 arc.
So it works. Now, the idea is to integrate that code into R via Rcpp. So in some directory I open a R console and I do:
> require("Rcpp")
Loading required package: Rcpp
> Rcpp.package.skeleton("pkgwithlgl")
Creating directories ...
Creating DESCRIPTION ...
Creating NAMESPACE ...
Creating Read-and-delete-me ...
Saving functions and data ...
Making help files ...
Done.
Further steps are described in './pkgwithlgl/Read-and-delete-me'.
Adding Rcpp settings
>> added Depends: Rcpp
>> added LinkingTo: Rcpp
>> added useDynLib directive to NAMESPACE
>> added Makevars file with Rcpp settings
>> added Makevars.win file with Rcpp settings
>> added example header file using Rcpp classes
>> added example src file using Rcpp classes
>> added example R file calling the C++ example
>> added Rd file for rcpp_hello_world
So, in this way I just created a new Rcpp based source package named pkgwithlgl. Now inside the pkgwithlgl directory (which is the source of the package that I want to modify and install) there is a directory named src. Inside it there are the files with the C++ code of the package. In particular there is one named *rcpp_hello_world.cpp* which contains:
#include "rcpp_hello_world.h"
SEXP rcpp_hello_world(){
using namespace Rcpp ;
CharacterVector x = CharacterVector::create( "foo", "bar" ) ;
NumericVector y = NumericVector::create( 0.0, 1.0 ) ;
List z = List::create( x, y ) ;
return z ;
}
Now, I modify it so it becomes:
#include "rcpp_hello_world.h"
#include <lemon/list_graph.h>
using namespace lemon ;
SEXP rcpp_hello_world(){
using namespace Rcpp ;
int res = 1;
ListDigraph g;
ListDigraph::Node u = g.addNode();
ListDigraph::Node v = g.addNode();
ListDigraph::Arc a = g.addArc(u, v);
int i = countNodes(g);
int j = countArcs(g);
Rprintf("num nodes is %d , and num edges is %d \n",i,j);
return wrap(res) ;
}
Then, from the linux console in the container directory of the source package I write:
$ R CMD INSTALL pkgwithlgl
which returns:
* installing to library ‘/home/juan/R/x86_64-pc-linux-gnu-library/2.12’
* installing *source* package ‘pkgwithlgl’ ...
** libs
g++ -I/usr/share/R/include -I"/usr/local/lib/R/site-library/Rcpp/include" -fpic -O3 -pipe -g -c rcpp_hello_world.cpp -o rcpp_hello_world.o
g++ -shared -o pkgwithlgl.so rcpp_hello_world.o -L/usr/local/lib/R/site-library/Rcpp/lib -lRcpp -Wl,-rpath,/usr/local/lib/R/site-library/Rcpp/lib -L/usr/lib64/R/lib -lR
installing to /home/juan/R/x86_64-pc-linux-gnu-library/2.12/pkgwithlgl/libs
** R
** preparing package for lazy loading
** help
Warning: /home/juan/Desktop/facu/investigacion_ensayos/Cosas_crudas/programming_coding/R-work- space/integrating_R_with_cpp_via_Rcpp/using_packages/pkgwithlgl/man/pkgwithlgl- package.Rd:32: All text must be in a section
Warning: /home/juan/Desktop/facu/investigacion_ensayos/Cosas_crudas/programming_coding/R-work- space/integrating_R_with_cpp_via_Rcpp/using_packages/pkgwithlgl/man/pkgwithlgl- package.Rd:33: All text must be in a section
*** installing help indices
converting help for package ‘pkgwithlgl’
finding HTML links ... done
pkgwithlgl-package html
rcpp_hello_world html
** building package indices ...
** testing if installed package can be loaded
* DONE (pkgwithlgl)
So the package is installed (the warnings has to do with the fact that I don't filled in the right way the .Rd file, ie, the files that contains the helps about the package). The I open a R console and write:
> require("pkgwithlgl")
Loading required package: pkgwithlgl
Loading required package: Rcpp
> rcpp_hello_world()
num nodes is 2 , and num edges is 1
[1] 1
so it works !!! That is all.
But hey !!! What happens if I build this package and upload it into (forexample) CRAN (I will not do it). If some one install this package from CRAN, will it work for him? Even if it does not install the LGL package?
Best Regards
Howdy, and thanks for your interest in Rcpp.
To bind calls between different library functions, you may want to look into building a package. There are now twenty packages using Rcpp as listed on the Rcpp page on CRAN so you have examples to copy from. At a first appromixation,. this is no different from writing a normal program and Rcpp simply helps you getting it to R.
If you have more questions, please feel free to bring them to the rcpp-devel list.

Resources