gomfy
gomfy

Reputation: 689

How do I create an R package that depends on a shared library with Rcpp?

I have a shared library libbcd.so generated from C source code. I also have some interface code Rinterface.h, Rinterface.cpp, which looks as follows:

Rinterface.h:

#pragma once

#include <R.h>
#include <Rcpp.h>
extern "C" {
#include "bcd.h"
}

void call_bcd();

Rinterface.cpp

#include "Rinterface.h"

// [[Rcpp::export]]
void call_bcd() {
    mm_problem* pr = mm_problem_alloc();
    bcd_vars* vars = bcd_vars_alloc();
    bcd(pr, vars);
}

Where mm_problem_alloc(), bcd_vars_alloc(), bcd(mm_problem*, bcd_vars*) are all functions from libbcd.so and mm_problem and bcd_vars are user defined types from libbcd.so.

I have created a package with Rcpp.package.skeleton("bcd") put the Rinterface files under src folder with the following Makevars

PKG_CPPFLAGS=-I/usr/local/lib/R/site-library/Rcpp/include/ -I/path/to/bcd/headers/
PKG_LIBS=-L/path/to/bcd/library/file -lbcd

If I try to install the package from source with install.packages("/path/to/bcd_1.0.tar.gz", type = "source") after the compilation step I get an error when it tries to load libbcd.so:

** R
** byte-compile and prepare package for lazy loading
** help
*** installing help indices
** building package indices
** testing if installed package can be loaded from temporary location
Error: package or namespace load failed for ‘bcd’ in dyn.load(file, DLLpath = DLLpath, ...):
 unable to load shared object '/home/gomfy/R/x86_64-pc-linux-gnu-library/3.6/00LOCK-bcd/00new/bcd/libs/bcd.so':
  libbcd.so: cannot open shared object file: No such file or directory

Based on this post it seems to me that a workaround would be to rename the .c source files of libbcd.so to .cpp and then put them in the src folder. Is this correct?

In general, what is a recommended way of leveraging Rcpp to be able to call a third party shared library from R? I've found a related question here but it doesn't go into details of building the package. I've looked at Writing R extensions vignette("Rcpp-introduction"), vignette("Rcpp-package") but I wasn't able to come to a clear conclusion. So, I'd appreciate an expert's help here. Thank you!

Upvotes: 2

Views: 667

Answers (1)

Dirk is no longer here
Dirk is no longer here

Reputation: 368181

In short, you can't.

A system-level shared library will be loaded on demand for you by ld.so (on Linux, similar on other OSs and same idea). So if your package depends on a non-standard or uncommon shared library, tough luck. This can only work if ld.so knows about it, and an R package cannot make it so.

What you can do is bundle the sources of your libbcd with your package and them built as a static library linked to from your package. That will work. As will the simpler approach of maybe just putting the source files of libbcd into the package src/ directory -- and R will take care of the rest.

Upvotes: 6

Related Questions