gpt4 book ai didi

c++ - Rcpp:无法加载共享对象, undefined symbol

转载 作者:可可西里 更新时间:2023-11-01 18:31:11 26 4
gpt4 key购买 nike

我正在尝试使用 Rcpp 来扩展 BayesOpt 的功能C++ 库到 R。我是 R 的长期用户,但对 C++ 比较陌生,我遇到了一些问题。我已经按照 Rcpp vignettes 设置了一个包,我知道这是引入外部 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

在错误日志中。 回声_ZTIN8bayesopt13DiscreteModelE | c++filt 为 bayesopt::DiscreteModel 提供 typeinfo,这是我的 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,它具有相同的目的:将编译和链接器标志传递给使用该库的程序.

而你确实两者都需要,你的评论

I would like to believe that the Makevars points at the library correctly, because it is able to find the header files during the first installation check

表示您已经整理好汇编,但没有您图书馆的链接或系统提供。同样,对于 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,我们寻找一个 system GSL 安装。地方不一样。您可以研究处理这两种情况的 nloptr 包。

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

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com