我正在尝试使用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给出typeinfo for bayesopt::DiscreteModel,这是我的test.cpp文件中使用BayesOpt header 的第一个对象。我一直在寻找解决方案,但似乎没有找到解决方案。我想相信Makevars正确指向了库,因为它能够在第一次安装检查期间找到头文件-仅在加载候选程序包时,我才得到此 undefined symbol 错误。我看过一个使用外部库的Rcpp示例,但Dirk指向的是RcppGSL,它包含一个3500+行的配置脚本,该脚本填充了Makevars,很难解析,这是我所查看的答案。 。

我将不胜感激任何人的帮助-我的最后一招是将所有内容都转储到src中,但是对于已经整齐有序的库来说,这似乎很麻烦并且不够优雅。

最佳答案

不要看自动生成的configure脚本,而是看它的源代码configure.ac,这是所有5行重要的内容(请参阅下文)以及5行设置和完成。

简而言之,您可能只需要为 header (通过-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,该工具具有相同的目的:使用该库将编译和链接器标志传递给程序。

而您都需要,您的评论



表示您已整理好编译内容,但没有链接,或者库的系统设置没有。同样,对于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软件包。

关于c++ - Rcpp:无法加载共享对象, undefined symbol ,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/36232051/

10-12 17:55