Rcpp:无法加载共享对象,未定义的符号

时间:2016-03-26 05:48:00

标签: c++ r rcpp

我正在尝试使用Rcpp将BayesOpt C ++库中的功能扩展到R.我是一个长期的R用户,但对C ++来说相对较新,我遇到了一些问题。我已经按照Rcpp的插图设置了一个包,我理解这是将外部C ++库引入的最好方法。

我已将src / Makevars中的PKG_CPPFLAGS和PKG_LIBS设置为BayesOpt包含文件夹和库,我在src /中有一个.cpp文件(称为test.cpp),它使用#include来处理来自BayesOpt的一些头文件。在这个文件中,我有/\\.高于我想要导出的函数。

当我运行// [[Rcpp::export]]时,库似乎正在成功运行 - 查看日志,一切顺利,直到它尝试加载刚刚“安装”的软件包。然后,我得到

R CMD check mypackage

在错误日志中。 ** testing if installed package can be loaded Error in dyn.load(file, DLLpath = DLLpath, ...) : unable to load shared object '/home/me/p3/mypackage.Rcheck/mypackage/libs/mypackage.so': /home/me/p3/mypackage.Rcheck/mypackage/libs/mypackage.so: undefined symbol: _ZTIN8bayesopt13DiscreteModelE 给出echo _ZTIN8bayesopt13DiscreteModelE | c++filt,这是我的test.cpp文件中第一个使用BayesOpt标头的对象。为了解决这个问题,我看起来又高又低,但我似乎找不到一个。我想相信Makevars正确地指向库,因为它能够在第一次安装检查期间找到头文件 - 只有在加载候选包时我得到这个未定义的符号错误。我看过一个使用外部库的Rcpp示例,但是Dirk在我看到的答案中指出的typeinfo for bayesopt::DiscreteModel,有一个3500+行配置脚本填充了Makevars,它是一个很难解析。

我很感激任何人的帮助 - 我的最后一招是把所有东西都放到RcppGSL中,但对于一个已经整齐有序的图书馆而言,这似乎很麻烦而且不够优雅。

1 个答案:

答案 0 :(得分:7)

不要查看自动生成的configure脚本 - 查看configure.ac哪个是它的来源,哪个是5行重要(见下文)加上5设置和完成线。

简而言之,您可能只需要为两个标头(通过-I...)和链接(通过-L... -l...)加载值。

为此,我们在src/Makevars.in

中执行此操作
# set by configure
GSL_CFLAGS = @GSL_CFLAGS@
GSL_LIBS   = @GSL_LIBS@

# combine with standard arguments for R
PKG_CPPFLAGS = $(GSL_CFLAGS) -I../inst/include
PKG_LIBS = $(GSL_LIBS) 

@GSL...@表示的两个变量都是通过configureconfigure.ac设置的(实质上)在断言我们拥有它之后调用gsl-config

## Use gsl-config to find arguments for compiler and linker flags
##
## Check for non-standard programs: gsl-config(1)
AC_PATH_PROG([GSL_CONFIG], [gsl-config])
## If gsl-config was found, let's use it
if test "${GSL_CONFIG}" != ""; then
    # Use gsl-config for header and linker arguments
    GSL_CFLAGS=`${GSL_CONFIG} --cflags`
    GSL_LIBS=`${GSL_CONFIG} --libs`
else
    AC_MSG_ERROR([gsl-config not found, is GSL installed?])
fi

在过去十年左右创建的许多其他库使用了一个名为pkg-config的类似(但更通用)的工具,其用途相同:将编译和链接器标志传递给使用该库的程序。

需要两者,你的评论

  

我想相信Makevars正确指向库,因为它能够在第一次安装检查时找到头文件

表示您已将编译整理出来但链接或可能不是您库的系统配置。同样,对于RcppGSL,构建期间的最后一行是以下(为简洁起见编辑)

g++ -shared -L/usr/lib/R/lib -o RcppGSL.so \
 RcppExports.o fastLm.o setErrorHandler.o \
 -L/usr/lib/x86_64-linux-gnu -lgsl -lgslcblas \
 -lm -L/usr/lib/R/lib -lR

它将三个源文件与两个与GSL相关的库以及R和数学库相链接。您必须在构建中看到类似的内容,或者未正确设置。

编辑:如果您将BayesOpt捆绑在软件包中,则需要将其构建到静态库中并在src/Makevars中列出。这是一个不同的用例:对于RcppGSL,我们寻找系统 GSL安装。本地不同。您可以研究处理这两种情况的nloptr包。