如何创建依赖于Rcpp共享库的R包?

时间:2019-11-11 20:38:51

标签: c r dll rcpp

我有一个从libbcd.so源代码生成的共享库C。 我还有一些接口代码Rinterface.h, Rinterface.cpp,如下所示:

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);
}

mm_problem_alloc(), bcd_vars_alloc(), bcd(mm_problem*, bcd_vars*)libbcd.so中的所有函数,而mm_problembcd_varslibbcd.so中的用户定义类型。

我创建了一个软件包,其中Rcpp.package.skeleton("bcd") Rinterface 文件放在src文件夹下,并带有以下 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
  • 我可以使用R CMD SHLIB Rinterface.cpp
  • 创建接口库
  • 我还可以使用R CMD build .
  • 构建软件包tarball

如果在编译步骤后尝试使用install.packages("/path/to/bcd_1.0.tar.gz", type = "source")从源代码安装软件包,则在尝试加载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

基于this post,在我看来,一种解决方法是将.c的{​​{1}}源文件重命名为libbcd.so,然后将其放入{{1 }}文件夹。这是正确的吗?

通常,推荐使用Rcpp来从.cpp调用第三方共享库的方法是什么?我发现了一个相关的问题here,但没有涉及构建软件包的细节。我看过 Writing R扩展 srcR,但我无法得出明确的结论。因此,在此感谢专家的帮助。谢谢!

1 个答案:

答案 0 :(得分:5)

简而言之,你不能。

ld.so将根据需要为您加载系统级共享库(在Linux上,与其他OS相似,并且使用相同的概念)。因此,如果您的软件包依赖于非标准或不常见的共享库,那么运气不好。 这只有在ld.so知道并且R软件包不能做到的情况下才能起作用。

您可以 libbcd 的源与软件包捆绑在一起,并将它们构建为链接的静态库从您的包裹。那可行。可能只是将libbcd的源文件放入包src/目录中的更简单的方法-R将负责其余的工作。