Rcpp functions undefined when used alongside Stan - r

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.

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...

Error using RcppArmadillo.package.skeleton

I want to create a package containing a RcppArmadillo function:
library(Rcpp)
library(RcppArmadillo)
sourceCpp("calculSignSim.cpp")
RcppArmadillo.package.skeleton(name = "calculSignSimCPP",list = "calculSignSim")
The function created by sourceCpp works fine.
However, this latter line gives me the following error:
Calling package.skeleton to create basic package.
Creating directories ...
Creating DESCRIPTION ...
Creating NAMESPACE ...
Creating Read-and-delete-me ...
Saving functions and data ...
Making help files ...
Done.
Further steps are described in './calculSignSimCPP/Read-and-delete-me'.
Adding RcppArmadillo settings
>> added Imports: Rcpp
>> added LinkingTo: Rcpp, RcppArmadillo
>> added useDynLib and importFrom directives to NAMESPACE
>> added Makevars file with Rcpp settings
>> added Makevars.win file with RcppArmadillo settings
>> added example src file using armadillo classes
>> added example Rd file for using armadillo classes
Error in Rcpp::compileAttributes(root) :
Evaluation error: D:/R packages/calculSignSimCPP/R/calculSignSim.R:3:21: unexpected '<'
2: function (lemmesV, ulemmesV, optionLien)
3: .Primitive(".Call")(<
^.
In addition: Warning message:
In dump(item, file = file.path(code_dir, sprintf("%s.R", list0[item])), :
deparse may be incomplete
I really don't understand why it doesn't work.
When I do not explicitely indicate which function I want to include, i.e. when I do
RcppArmadillo.package.skeleton(name = "calculSignSimCPP")
Everything works fine, but the created package does not contain my function...
Any idea ?

Overwriting NAMESPACE and Rd with roxygen2

I create a new package with RStudio. In "Configure Build Tools", I check "Generate documentation with Roxygen".
The first time I click on "Document" in the "Build" pane, everything works fine:
==> roxygen2::roxygenize('.', roclets=c('rd', 'collate', 'namespace'))
First time using roxygen2. Upgrading automatically...
Writing hello.Rd
Writing NAMESPACE
Documentation completed
I get this NAMESPACE:
# Generated by roxygen2: do not edit by hand
export(hello)
and this file hello.Rd:
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/hello.R
\name{hello}
\alias{hello}
\title{Hello}
\usage{
hello(x)
}
\arguments{
\item{x}{string}
}
\value{
a string
}
But now, I modify the file hello.R, and then I get two problems.
Firstly, this window appears:
If I click on "Yes", nothing happens.
Secondly, it seems that roxygen2 cannot overwrite hello.Rd, because I get this text in the "Build" pane:
==> roxygen2::roxygenize('.', roclets=c('rd', 'collate', 'namespace'))
Error: The specified file is not readable: U:\Data\Rtests\testPackage\man/hello.Rd
Execution halted
Exited with status 1.
The only way I found to update the documentation is to run:
roxygen2::roxygenize(clean=TRUE)
This command firstly cleans everything, the NAMESPACE and the Rd files, and then generates the NAMESPACE and the Rd files.
I don't know whether this is an issue with the path of Rtools. I tried to set the path by doing:
Sys.setenv(PATH="%PATH%;C:/Program Files/Rtools/gcc-4.6.3/bin;C:/Program Files/Rtools/gcc-4.6.3/bin64;C:/Program Files/Rtools/gcc-4.6.3/i686-w64-mingw32/bin;C:/Program Files/Rtools/bin")
But that does not solve the issue.
I'm using:
roxygen2 5.0.1
RStudio 0.99.892
Windows 7
R version 3.3.1
Cause of the problem.
The roxygen2 package depends on the digest package. The error (The specified file is not readable) is generated by the digest function of the digest package, at the moment when this function calls the file.access function: https://github.com/eddelbuettel/digest/blob/master/R/digest.R#L102.
I get:
> file.access("U:/Data", 4)
U:/Data
-1
That means that U:/Data has not the read permission. But this is not true: it has the read permission. The problem is that my U: drive is a "network drive", and there are some issues with the file.access function for network drives, as we can see here for example: https://github.com/eddelbuettel/digest/issues/13.
A workaround
The problem would be solved if R.utils::fileAccess would be used instead of file.access in the digest::digest function.
So, firstly take the code of the digest::digest function and modify it as follows.
mydigest <- function (object, algo = c("md5", "sha1", "crc32", "sha256",
"sha512", "xxhash32", "xxhash64", "murmur32"), serialize = TRUE,
file = FALSE, length = Inf, skip = "auto", ascii = FALSE,
raw = FALSE, seed = 0, errormode = c("stop", "warn", "silent"))
{
file.access <- R.utils::fileAccess
.... the code of the digest function here ...
}
Then do:
library(digest)
R.utils::reassignInPackage("digest", "digest", mydigest)
And now the documentation can be updated by doing:
roxygen2::roxygenize()

RUnit: could not find function "checkEquals"

I am creating an R package with the standard directory hierarchy. Inside the R directory, I create a test subdirectory.
In the R directory, I create a uTest.R file containing:
uTest <- function() {
test.suite <- defineTestSuite('test',
dirs = file.path('R/test'))
test.result <- runTestSuite(test.suite)
printTextProtocol(test.result)
}
In the R/test directory, I create a runit.test.R file containing:
test.validDim <- function() {
testFile <- "test/mat.csv"
generateDummyData(testFile,
10,
10)
checkEquals(validDim(testFile), TRUE)
}
I build and install my package using R CMD INSTALL --no-multiarch --with-keep.source RMixtComp in Rstudio. When I try to launch the function uTest(), I get this error message:
1 Test Suite :
test - 1 test function, 1 error, 0 failures
ERROR in test.validDim: Error in func() : could not find function "checkEquals"
However, if I call library(RUnit) prior to calling uTest(), everything works fine. In the import field of the DESCRIPTION file, I added RUnit, and in the NAMESPACE file I added import(RUnit).
How can I call uTest() directly after loading my package, without manually loading RUnit ?
You should not add RUnit to the Depends (or Imports) field in the DESCRIPTION file (despite the comment to the contrary). Doing so implies that the RUnit package is necessary in order to use your package, which is likely not the case. In other words, putting RUnit in Depends or Imports implies RUnit needs to be installed (Imports) and on the users' search path (Depends) in order for them to use your package.
You should add RUnit to the Suggests field in the DESCRIPTION file, then modify your uTest function as below:
uTest <- function() {
stopifnot(requireNamespace("RUnit"))
test.suite <- RUnit::defineTestSuite('test', dirs = file.path('R/test'))
test.result <- RUnit::runTestSuite(test.suite)
RUnit::printTextProtocol(test.result)
}
Doing this allows you to use RUnit for your tests, but does not require users to have RUnit installed (and possibly on their search path) in order to use your package. Obviously, they'll need RUnit if they wish to run your tests.

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