Reputation: 77096
I'm trying to make an R interface to the C++ library Faddeeva (various types of complex error functions); unfortunately I have very little experience in calling external code in R and it's proving quite a challenge.
My naive attempt,
R CMD SHLIB Faddeeva.cc
produced a shared library Faddeeva.so
, which I load in R,
dyn.load("Faddeeva.so")
dlls <- getLoadedDLLs()
getDLLRegisteredRoutines(dlls[['Faddeeva']])
It's empty, I haven't registered any of the functions. I believe I'll have to write some interface code to work with SEXPs so that I can use the .Call interface (could Rcpp make this step easier?), but I'm still confused as to why this shared library shows no registered routines.
Any advice or directions for undertaking such a project will be most welcome!
Edit: Thanks to Dirk's answer and help with Rcpp, the interface is now implemented in the Faddeeva package.
Upvotes: 3
Views: 177
Reputation: 368201
I would step back and look at other packages which use external libraries. The oldie but goldie is RcppGSL, but for example RcppRedis using the (C-library) hiredis.
There is really no deep magic:
ldconfig -p | grep libraryname
) by adding it in src/Makevars
to PKG_LIBS
.src/
and skip step 3.Note that I have said nothing about Rcpp. It "only" helps with point 2. The rest is the same as linking a C library to an R extensions. Which probably a thousand different packages on CRAN do.
If you are completely lost, consider the new list r-package-devel but do read a little in Writing R Extensions first.
Jelmer's package nloptr wraps another of Johnson's libraries: nlopt. Maybe that can help as inspiration. I helped a little making the installation more efficient (by using a system libnlopt
where present).
Edit: I had a closer look at the page by Johnson. There is no library. Just a .cc
and .hh
. Drop those into src/
of your package, possibly renameding to .cpp
and .h
-- and you are done!
Edit 2: Ok, I created a little sample package per the recipe I just outlined. By using Rcpp the caller becomes as simple as
#include <Rcpp.h>
using namespace Rcpp;
#include "Faddeeva.h"
// [[Rcpp::export]]
double Dawson(double x) { // special case for real x
return Faddeeva::Dawson(x);
}
and we can use the package as usual:
edd@max:/tmp$ Rscript -e 'library(RcppFaddeeva); Dawson(4.2)'
[1] 0.122761
edd@max:/tmp$
I'll put this on GitHub in a moment.
Edit 3: It is now in this GitHub repo.
Upvotes: 4