[Rd] Linking to native routines in other packages

Romain François romain at r-enthusiasts.com
Wed Jan 22 20:23:10 CET 2014


Hello, 

The problem is that you have logic in both your mother and child packages. IMO, you should only have logic in the mother package. 

I’ve done this in a number of packages, it requires a bit of work initially, but not that much. 

What I’d do is have something like this in mother/inst/include/mother.h : 

#if defined(COMPILING_MOTHER)
// just declare, will be defined in test.c
SEXP fun(SEXP test) ; 
#else
inline SEXP fun(SEXP test){
    typedef SEXP(*Fun)(SEXP); 
    static Fun fun = (Fun)R_GetCCallable("mother", "fun") ;
    return fun(test) ;
}
#endif

In your test.c file, make sure you define COMPILING_MOTHER before you include mother.h, something like this

#include <R.h>
#include <Rinternals.h>
#include <R_ext/Rdynload.h>
#define COMPILING_MOTHER
#include <mother.h>

SEXP fun(SEXP);

void R_init_mother(DllInfo *dll) {
    R_RegisterCCallable("mother", "fun", (DL_FUNC) &fun);
}

SEXP fun(SEXP test) {
    Rprintf("fun so much fun\n");
    return R_NilValue;
}

So that in your child package you only have to use it, something like: 

#include <Rinternals.h>
#include <R_ext/Rdynload.h>
#include <mother.h>

SEXP afun(SEXP test) {
   fun(test);
   return R_NilValue;
}

Note that if you only want the interface between the two packages to be at low level (not visible from R), then you don’t need to conform to the SEXP(SEXP...) interface. You can use anything you like. 

Romain

Le 22 janv. 2014 à 19:56, Gregor Kastner <gregor.kastner at wu.ac.at> a écrit :

> Hi again,
> 
> On Wed, 22 Jan 2014 06:39:17 -0600
> Dirk Eddelbuettel <edd at debian.org> wrote:
> 
> | Working examples I know of:   
> | 
> |    'xts' importing two functions from 'zoo'
> | 
> |    'RcppXts' importing approx. ten functions from 'xts'
> | 
> | Maybe by comparing to these you can sort out the missing step at your end.
> 
> Thanks Dirk for the hints; I finally got the code running. Important point
> is that R_init_PKGNAME() is declared as extern "C" (or RcppExport, of course)
> if using g++ in both the mother and the child package. (Interestingly,
> dyn.load() only complains when either the mother or the child package don't
> do so, but not if both don't do so => SEGFAULT.) Since it took me almost the
> entire afternoon to figure that out, I'll document a working example here. 
> 
> Scenario: We have a 'mother' package, which wants to make some C/C++ routines
> available to the 'child' package to be called directly from C/C++ level.
> Thus, mother's 'src' cointains:
> 
> 
> ********* BEGIN test.c *********
> 
> #include <R.h>
> #include <Rinternals.h>
> #include <R_ext/Rdynload.h>
> 
> SEXP fun(SEXP);
> 
> void R_init_mother(DllInfo *dll) {
> R_RegisterCCallable("mother", "fun", (DL_FUNC) &fun);
> }
> 
> SEXP fun(SEXP test) {
> Rprintf("fun so much fun\n");
> return R_NilValue;
> }
> 
> ********** END test.c **********
> 
> 
> (Note that no extern "C" is needed here because it will be compiled with gcc
> anyway).
> 
> The child uses Rcpp and mother, thus has
> 
> 
> ********* BEGIN DESCRIPTION *********
> 
> LinkingTo: mother, Rcpp
> Depends: mother, Rcpp
> Imports: mother, Rcpp
> 
> ********** END DESCRIPTION **********
> 
> 
> in its DESCRIPTION file, and 
> 
> 
> ********* BEGIN test.cpp *********
> 
> #include <Rinternals.h>
> #include <R_ext/Rdynload.h>
> 
> extern "C" {
> SEXP afun(SEXP);
> SEXP(*fun)(SEXP);
> 
> void R_init_child(DllInfo *info) {
>  fun = (SEXP(*)(SEXP)) R_GetCCallable("mother", "fun");
> }
> 
> SEXP afun(SEXP test) {
>  fun(test);
>  return R_NilValue;
> }
> }
> 
> ********** END test.cpp **********
> 
> (Note that extern "C" is crucial here.) After installing mother and child, we
> have:
> 
>> library(child)
> Loading required package: mother
> Loading required package: Rcpp
>> .Call("afun", 123, PACKAGE="child")
> fun so much fun
> NULL
>> 
> 
> Maybe it is of help to someone; please excuse me if I bored anyone with
> trivialities.
> 
> Best,
> Gregor
> 
> ______________________________________________
> R-devel at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel



More information about the R-devel mailing list