3

I would like to write a C++ function with Rcpp that uses a C function found in the package hypred, which is on CRAN here.

I read using C function from other package in Rcpp, but don't understand if this applies for me and if it would apply, what to do.

The desired function is in the the source file /src/hypredRoutines.c and is called meiosisFUNAllChr.

What I so far did based on this SO question here is:

  1. I separated the function meiosisFUNAllChr from the rest of the code and placed it in a new file called meiosisFUNAllChr.c.
  2. I created a header file called meiosisFUNAllChr.h containing:

    #ifndef MEIOSISFUNALLCHR_H
    #define MEIOSISFUNALLCHR_H
    void meiosisFUNallChr (...);
    #endif 
    
  3. Compiled it with

    gcc -c -o meiosisFUNAllChr.o meiosisFUNAllChr.c
    
  4. Created a dummy c++ function

    #include <Rcpp.h>
    using namespace Rcpp;
    
    extern "C" {
     #include "meiosisFUNallChr.h"
    }
    
    // [[Rcpp::export]]
    int timesTwo(int x) {
     return x * 2;
    }
    

At this point, compiling with sourceCpp does not work. Can you show me how to get it working?

Many Thanks!

EDIT

Compiling with sourceCpp gives me:

meiosisFUNallChr.h: file or directory not found
Community
  • 1
  • 1
NoBackingDown
  • 2,144
  • 1
  • 19
  • 25

2 Answers2

3

hypred registers its two functions, at the R level you can get hold of the one you want like this:

xp <- getDLLRegisteredRoutines( getLoadedDLLs()[["hypred"]] )[[".C"]][["meiosisFUNallChr"]]$address

I believe you can then access the function pointer in C++ like this:

DL_FUNC meiosisFUNallChr = reinterpret_cast<DL_FUNC>( R_ExternalPtrAddr(xp) ) ;

But you'd be better off negotiating with the package authors that they implement this scheme if you can make a case that you really need to be calling the C function directly.

Romain Francois
  • 17,432
  • 3
  • 51
  • 77
  • +1 regarding the registration scheme -- there are a few package in the Rcpp universe that do this. My simplest is probably RApiSerialize. @romain: is the `getDLLRegisteredRoutine(...)` approach "blessed" (or at least tolerated) by CRAN, ie is that what you used for mlxR? – Dirk Eddelbuettel Mar 13 '15 at 16:11
  • no idea. I don't see why not though, I'm only calling allowed R functions `getDLLRegisteredRoutines` and `getLoadedDLLs` ... `mlxR` is an entirely different kind of bird – Romain Francois Mar 14 '15 at 11:35
  • Yes, quite a different bird -- not a library under R's control. Is there something genralizable from what you did? We may have a similar issue with Rblpapi. – Dirk Eddelbuettel Mar 14 '15 at 12:14
  • What we used is perhaps not ideal for distribution. essentially none of the code or the examples directly refer to the underlying c++ library. The user is supposed to have installed some software first, and mlxR compiles an R package from that software at runtime, so CRAN does not need to know about that software ... – Romain Francois Mar 16 '15 at 07:52
-1

Briefly:

  • You want to use another source file (presumably available under a suitable license).

  • You want to call it from a new file of yours.

  • So you already have two files.

By now the alarm bells should go off that you really, really, want to create a package.

Which the Rcpp documentation details in many places. And there are 340+ packages on CRAN using Rcpp, many doing this very issue of calling a C file too. Pick one or two, study their structure; also pick one or two created by the fully documented Rcpp tools such as Rcpp.package.skeleton() and things should become a lot clearer.

Edit: Obviously, this approach only needs to be taken if the other package does not export its function. If you can get its author to export, use that as mention in Romain's answer. Pairs of packages that export/use are zoo/xts, xts/RcppXts, expm/RcppKalman (not on CRAN), RApiSerialize/RcppRedis, ...

Dirk Eddelbuettel
  • 360,940
  • 56
  • 644
  • 725