我正在尝试使用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...@
表示的两个变量都是通过configure
和configure.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/