[Rd] Linking to native routines in other packages
Gregor Kastner
gregor.kastner at wu.ac.at
Mon Jan 27 09:24:12 CET 2014
Thanks Romain for that elegant solution.
Best,
Gregor
On Wed, 22 Jan 2014 20:23:10 +0100
Romain François <romain at r-enthusiasts.com> wrote:
> 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