Suppose I have two packages in R, the first with the name foo , the second with the name bar . I want to enable the C function in foo and share this functionality with bar so that it is platform independent and complies with CRAN policies.
What is the preferred method for doing this and how can I use the function registration function and dynamic libraries?
The purpose of my question is that, although I read all the documentation I could find, nothing happened to me as obvious, and I'm not sure what the most sustainable course of action is.
Example:
Suppose in one package foo I define a C addinc function that adds two numbers.
#include <Rh> #include <Rinternals.h> SEXP addinc(SEXP x_, SEXP y_) { double x = asReal(x_); double y = asReal(y_); double sum = x + y; return ScalarReal(sum); }
In the same package, I can try calling addinc in an R function called addinr via the .Call interface.
addinr <- function(x,y){ .Call("addinc", x, y, PACKAGE="foo") }
However, when creating, checking, and installing the package, running addinr returns the error below, presumably because the function is not yet registered in R.
library(foo) addinr(1,2)
Error in .Call ("addinc", x, y, PACKAGE = "foo"):
"addinc" is not available for .Call () for package "foo"
It seems to me that the easiest way to solve this problem is to create a dynamic library for compiled code by adding the file useDynLib(foo) to foo NAMESPACE. This seems to solve the problem, because now I can call addinr() without any problems. Moreover, I can run .Call("addinc", ..., PACKAGE="foo") directly from R.
My real question, however, arises when it is assumed that the second package, say bar , uses foo addinc . For example, suppose bar defines the multiplyinr function as follows.
multiplyinr <- function(x,y){ ans <- 0 for(i in 1:y) ans <- .Call("addinc", ans, x, PACKAGE="foo") ans }
This, in fact, works perfectly fine, and I can call multiplyinr inside R. However, when I create and check the bar I get a note complaining that bar calls foreign language functions from another package.
Calling an external function for another package:
.Call ("addinc", ..., PACKAGE = "foo")
See the chapter "System and foreign language interfaces in the manual" Writing R-Extensions ".
According to this question, the package bar not suitable for sending to CRAN, since the use of .Call() thus not considered "portable", as explained in the Guide to Writing R Extensions .
In conclusion, the simple solution that foo includes useDynLib(foo) in its NAMESPACE file does not seem to cut it. So my question is: what is the preferred method for sharing the C function with other packages?
Wherein:
Does useDynLib() truly dangerous or incompatible CRAN policy? What is the purpose of declaring useDynLib() in a NAMESPACE file as an alternative to registering and creating a shared library manually?
Would you manually register the C function and expand the shared library to change anything (i.e. using R_RegisterCCallable() or R_registerRoutines() )?