Rcpp:无法加载共享对象,未定义符号
Rcpp: unable to load shared object, undefined symbol
我正试图使用Rcpp将BayesOpt C++库的功能扩展到R中。我是一个长期的R用户,但对C++相对陌生,遇到了一些问题。我已经按照Rcpp的小插曲设置了一个包,我知道这是引入外部C++库的最佳方式。
我已经将src/Makevars中的PKG_CPPFLAGS和PKG_LIBS设置为BayesOpt-include文件夹和库,并且我在src/中有一个.cpp文件(称为test.cpp),它对BayesOpt中的一些头文件使用#include。在这个文件中,我在要导出的函数上方有// [[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头的第一个对象。我到处寻找解决方案,但似乎找不到。我相信Makevars正确地指向了库,因为它能够在第一次安装检查期间找到头文件——只有在加载候选包时,我才会得到这个未定义的符号错误。我看过一个使用外部库的Rcpp示例,但Dirk在我看过的答案中指出的RcppGSL
有一个3500多行的配置脚本,它填充了Makevars,解析起来有点困难。
我非常感谢任何人的帮助——我的最后手段是将所有内容都转储到src
中,但对于一个已经组织整齐的图书馆来说,这似乎很麻烦,也不那么优雅。
不要看自动生成的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...@
表示的两个变量都是通过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
的类似(但更通用)工具,该工具具有相同的目的:将编译和链接器标志传达给使用该库的程序。
您确实需要两者,您的评论
我相信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包。
- 在销毁期间从另一个线程调用对象上调用方法是否未定义行为?
- 为什么销毁被放置 new 覆盖的对象不是未定义的行为?
- 未定义的对象(〔basic.life〕/8):为什么允许引用重新绑定(和常量修改)
- 正在通过const-ref未定义的行为捕获新构造的对象
- 仅标头类 + 仅当返回该类的对象时,对函数的未定义引用
- 如果用户尝试从 JS 调用对象的未定义函数C++则回调C++代码
- C++:在共享对象中调用抽象基类构造函数/未定义的符号
- Cython:共享对象中未定义的符号
- 对"车辆的 vtable"的未定义引用 - 面向对象的编程练习
- 为什么内置类型的对象上的溢出会导致异常/未定义的行为?
- 正在加载共享对象:文件中未定义版本Qt_5
- 对象文件中的未定义引用 - 如何查找哪个库包含它
- static_cast实际上不是对象类型的类型是未定义的行为吗?
- 尝试与从 CUDA 对象构建的共享库链接时未定义的符号
- C++ / G++ Maxmind geolite2++ 第三方共享对象未定义引用
- 对象在函数中未定义
- C++ 未定义的对象引用
- 通过在此指针上放置新位置重新初始化对象时未定义的行为
- 无法加载共享对象:未定义的符号
- 模板和静态对象(未定义的引用和必需的引用)