Question

I am trying to define a function using Rcpp for speedup. The situation is as follows:

  • I have a package FOO with a lot of C++ code (my own package and currently not using Rcpp) which have defined a set of functions e.g. foo_a and foo_b.
  • In another package BAR (using Rcpp) I am defining a function (using Rcpp Attributes) where I want to call functions foo_a and foo_b.

How do I solve this? Looking a bit in other posts I get that I have in some way to include header files in FOO and use attribute // [[Rcpp::depends(FOO)]] in BAR, but I seem to miss some points. Any hints on how to do it?

Best Lars

EDIT: Thanks for the comments I liked Kevin Usheys approach and tried to implement it. However, after some coding I realized that I actually don't need functions from FOO but a class and its public functions. I guess that I cannot do the tricks you suggested for a class. I ended up putting the source files of the class from FOO in the BAR src dir (not the best approach since I now have 2 versions of the same code). However for the moment this hack work for me.

Was it helpful?

Solution 2

Another option, in case you don't mind introducing Rcpp into package FOO - follow along with Section 3.5 of Rcpp-attributes and do the following:

  1. Place // [[Rcpp::interfaces(cpp)]] at the top of the .cpp source files containing functions you'd like to be made available to other packages,

  2. Place // [[Rcpp::export]] in front of those functions you would like exported,

  3. Call compileAttributes() in the package directory of FOO to generate files in inst/include that can then be used by package BAR, using // [[Rcpp::depends(FOO)]],

  4. Install package FOO.

If you have this set up correctly, you should be able to call a function with a template like this (supposing foo_a is an exported function from FOO):

// [[Rcpp::depends(FOO)]]

#include <Rcpp.h>
#include <FOO.h>
using namespace Rcpp;

// [[Rcpp::export]]
SEXP some_function() {
  return FOO::foo_a();
}

OTHER TIPS

I would recommend one of these options:

If foo_a and foo_b are simple enough, just have them as inline functions in headers of FOO and put these headers in FOO/inst/include/FOO.h. Rcpp::depends(FOO) will then include this file when you invoke compileAttributes (or perhaps load_all) on BAR.

Otherwise, consider registering the functions using R's registration model. this is a bit more work, but that's bearable. Writing R extensions has the details. I would suggest putting all the registration logic in FOO so that the client package BAR only has to use it. For example, I'd have foo_a like this in FOO's headers, e.g. in FOO/inst/include/FOO.h:

#ifdef COMPILING_FOO
inline int foo_a(int x, double y, const std::string& z){
    typedef int (*Fun)(int, double, const std::string&) ;
    static Fun fun = (Fun)R_GetCCallable( "FOO", "foo_a" ) ;
    return fun(x,y,z) ;
}
#else 
// just declare it
int foo_a(int x, double y, const std::string& z) ;
#endif

and the actual definition of foo_a in some .cpp file in FOO/src:

#define COMPILING_FOO
#include <FOO.h>

int foo_a(int x, double y, const std::string& z){
   // do stuff
}

Then, you need to register foo_a using R_RegisterCCallable in the function R_init_FOO:

extern "C" void R_init_FOO( DllInfo* info ){
    R_RegisterCCallable( "FOO", "foo_a", (DL_FUNC)foo_a );
}

The RcppXts package does just that for a bunch of functions from the well-known xts package.

Edit: Here is some code from xts.

First, xts::src/init.c does the registration via a dozen or so declarations like

R_RegisterCCallable("xts","do_is_ordered",(DL_FUNC) &do_is_ordered);

Second, xts::inst/include/xtsApi.h provides a header for client packages with eg

SEXP attribute_hidden xtsIsOrdered(SEXP x, SEXP increasing, SEXP strictly) {
    static SEXP(*fun)(SEXP,SEXP,SEXP) = NULL;
    fun = (SEXP(*)(SEXP,SEXP,SEXP)) R_GetCCallable("xts","do_is_ordered");
    return fun(x, increasing, strictly);
}

Third, in a client package such as RcppXts we define this (using Rcpp Modules) as

function("xtsIsOrdered",
         &xtsIsOrdered,
         List::create(Named("x"),
                      Named("increasing") = true,
                      Named("strictly") = true),
         "Tests whether object is (strictly) (increasing) ordered");

which exposes it to R. We could equally well call the C function xtsIsOrdered from C++ code.

I removed the incorrect earlier comment that functions have to conform to 'SEXP in, SEXP out'.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top