R package with C code, 'no such symbol' in package dll - r

I am writing an R package, and started to include C code in it. Following instructions from here, under "getting started with .C()", I created a c function in src/, and an r wrapper to it, linking via the roxygen tag #useDynLib(<package-name>, <name_of_c_function>).
However, after running devtools::document(), I get the following error:
Error in FUN(X[[i]], ...) :
no such symbol <name_of_c_function> in package C:/path/to/package/src/<package-name>.dll
I read that updating R and Rtools have fixed the issue for some. I have updated both of them yesterday, but to no avail.
Any help will be much appreciated.
(This is similar to the problem in this question, which is currently unanswered.)
(It may also be related with this question, except that I use devtools::document() instead of R CMD in that question.)
Relevant code:
# R file
#' #useDynLib <package-name> <name_of_c_function>
#' #export
name_of_func <- function(y) {
stopifnot(is.numeric(y))
.C(name_of_c_function, y,y,length(y),1) [[2]]
}
// C file
<#include stdlib.h>
static void name_of_c_function(double* y, double* x,
const unsigned int length, const double a) {...}

It turns out that the problem is in this line
static void name_of_c_function(...){...}
As mentioned in this post,
The static keyword is somewhat over used. When it applies to function, it means that the function has internal linkage, ie its scope is limited to within a translation unit (simply as a source file).
In other words, the 'static' keyword makes the function no longer callable from outside its own unit, thus resulting in the "no such symbol" error.
Removing the 'static' keyword solves the problem.

Related

A note on graphics::curve() in R CMD check

I use the following code in my own package.
graphics::curve( foo (x) )
When I run R CMD check, it said the following note.How do I delete the NOTE?
> checking R code for possible problems ... NOTE
foo: no visible binding for global variable 'x'
Undefined global functions or variables:
x
Edit for the answers:
I try the answer as follows.
function(...){
utils::globalVariables("x")
graphics::curve( sin(x) )
}
But it did not work. So,..., now, I use the following code, instead
function(...){
x <-1 # This is not used but to avoid the NOTE, I use an object "x".
graphics::curve( sin(x) )
}
The last code can remove the NOTE.
Huuum, I guess, the answer is correct, but, I am not sure but it dose not work for me.
Two things:
Add
utils::globalVariables("x")
This can be added in a file of its own (e.g., globals.R), or (my technique) within the file that contains that code.
It is not an error to include the same named variables in multiple files, so the same-file technique will preclude you from accidentally removing it when you remove one (but not another) reference. From the help docs: "Repeated calls in the same package accumulate the names of the global variables".
This must go outside of any function declarations, on its own (top-level). While it is included in the package source (it needs to be, in order to have an effect on the CHECK process), but otherwise has no impact on the package.
Add
importFrom(utils,globalVariables)
to your package NAMESPACE file, since you are now using that function (unless you want another CHECK warning about objects not found in the global environment :-).

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

Function imported from dependency not found, requires library(dependency)

I am trying to create an R package that uses functions from another package (gamlss.tr).
The function I need from the dependency is gamlss.dist::TF (gamlss.dist is loaded alongside gamlss.tr), but it is referenced in my code as simply TF within a call to gamlss.tr::gen.trun.
When I load gamlss.tr manually with library(), this works. However, when I rely on the functions of the dependency automatically being imported by my package through #import, I get an "object not found" error as soon as TF is accessed.
My attempt to be more explicit and reference the function I need as gamlss.dist::TF resulted in a different error ("unexpected '::'").
Any tips on how to use this function in my package would be much appreciated!
The code below reproduces the problem if incorporated into a clean R package (as done in this .zip), built and loaded with document("/path/to/package"):
#' #import gamlss gamlss.tr gamlss.dist
NULL
#' Use GAMLSS
#'
#' Generate a truncated distribution and use it.
#' #export
use_gamlss <- function() {
print("gen.trun():")
gamlss.tr::gen.trun(par=0,family=TF)
#Error in inherits(object, "gamlss.family") : object 'TF' not found
#gamlss.tr::gen.trun(par=0,family=gamlss.dist::TF)
#Error in parse(text = fname) : <text>:1:1: unexpected '::'
y = rTFtr(1000,mu=10,sigma=5, nu=5)
print("trun():")
truncated_dist = gamlss.tr::trun(par=0,family=TF, local=TRUE)
model = gamlss(y~1, family=truncated_dist)
print(model)
}
use_gamlss() will only start working once a user calls library(gamlss.tr).
This is due to bad design of gamlss.tr in particular the trun.x functions (they take character vectors instead of family objects / they evaluate everything in the function environment instead of the calling environment).
To work around this, you have to make sure that gamlss.distr is in the search path of the execution environment of gamlss.tr functions (This is why ## import-ing it in your package does not help: it would need to be #' #import-ed in gamlss.tr).
This can be achieved by adding it to Depends: of your package.
If you want to avoid that attaching your package also attaches gamlss.distr, you could also add the following at the top of use_gamlss:
nsname <-"gamlss.dist"
attname <- paste0("package:", nsname)
if (!(attname %in% search())) {
attachNamespace(nsname)
on.exit(detach(attname, character.only = TRUE))
}
This would temporarily attach gamlss.dist if it is not attached already.
You can read more on namespaces in R in Hadley Wickham's "Advanced R"

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.

Resources