Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I transition from using C++ with inline to making my own R package?

There are two things going on here: (1) I am just learning how to use Rcpp and friends to make my R code faster and (2) I have never built an R package before.

I've got the use of inline down. Great package. Love it. However, I can't seem to use any code developed with inline with package.skeleton to make an R package.

Here is a minimal example:

Step 1: Make the R script

#############################
# File : build-R-pacakge.R  #
#############################
require(inline)
require(Rcpp)
require(RcppArmadillo)

# Define a simple cxxfunction
plus.two.cpp.src <- '
    arma::mat U = Rcpp::as<arma::mat>(UmatrixR);
    return(Rcpp::wrap(U+2));
'
plus.two.cpp <- cxxfunction(
             signature(UmatrixR="numeric"),
             body=plus.two.cpp.src,
             plugin="RcppArmadillo")

# Define the analogous R function
plus.two.r <- function( x ) {
  return( x + 2 )
}

Step 2: Build it as an R Package

In new R session run:

source('build-R-package.R')
RcppArmadillo.package.skeleton(name='inlineExample',
                 list=c('plus.two.cpp', 'plus.two.r'),
                 code_files='build-R-package.R')

Then delete the man/*.Rd files since R doesn't put in defaults that 'just work'.

$ rm inlineExample/man/*.Rd

And run:

$ R CMD build inlineExample/
<< snip >> 
$ R CMD check inlineExample_1.0.tar.gz 
<< snip >>
$ R CMD INSTALL inlineExample_1.0.tar.gz 
<< snip >>

Which all complete successfully, except for some complaining about the missing documentation.

Step 3: Try it out

And then try it out in a new R session:

> require(inlineExample)
Loading required package: inlineExample
Loading required package: Rcpp
Loading required package: RcppArmadillo
Loading required package: inline
>
> plus.two.cpp( matrix(1:12, ncol=3))
Error in .Primitive(".Call")(<pointer: (nil)>, UmatrixR) : 
  NULL value passed as symbol address
>
> plus.two.cpp
An object of class "CFunc"
function (UmatrixR) 
.Primitive(".Call")(<pointer: (nil)>, UmatrixR)
<environment: 0x2f28370>
Slot "code":
[1] "\n// includes from the plugin\n#include <RcppArmadillo.h>\n#include <Rcpp.h>\n\n\n#ifndef BEGIN_RCPP\n#define BEGIN_RCPP\n#endif\n\n#ifndef END_RCPP\n#define END_RCPP\n#endif\n\nusing namespace Rcpp;\n\n\n// user includes\n\n\n// declarations\nextern \"C\" {\nSEXP file2f8c4cc10657( SEXP UmatrixR) ;\n}\n\n// definition\n\nSEXP file2f8c4cc10657( SEXP UmatrixR ){\nBEGIN_RCPP\n\n  arma::mat U = Rcpp::as<arma::mat>(UmatrixR);\n  return(Rcpp::wrap(U+2));\n\nEND_RCPP\n}\n\n\n"

It fails. To my untrained eyes it seems that:

  1. the code that inline compiled never got copied by *.package.skeleton to the "right" part of the directory skeleton for later compilation by the R build process, and
  2. failing that the 'code_files' argument does not cause R to source those *.R files when the package is loaded.

Thinking about this further, it seems like (2) would be a really bad idea because it would force the user to compile the code every time they loaded their package. That would both exclude all users who require binary only packages and just simply be really inefficient.

And (1) seems technically possible, but as discussed on the Rcpp mailing list, it is not worth implementing a set of auto-magic converter functions.

So, the question:

Can someone please give a walk-through of the correct way to take the provided example code and turn it into an R package?

There is just a bit too much newness for me to make sense of the existing documentation. FWIW, I'm sure it would be helpful for people in the future!

like image 994
Nathan VanHoudnos Avatar asked Jul 12 '12 16:07

Nathan VanHoudnos


1 Answers

Step 1: Write a dummy package without Rcpp, just to get a feel for how things work.

Step 2: Read Dirk's explanation of how to make a package that uses Rcpp.

From what I've read inline seems to make Rcpp in packages harder not easier.

like image 69
Ari B. Friedman Avatar answered Oct 24 '22 08:10

Ari B. Friedman