由于Rcpp库,我正在尝试开发一个使用Arrayfire的R包。 我已经开始编写示例代码(将其命名为 hello_world.cpp ),如下所示:
#include <arrayfire.h>
// [[Rcpp::export]]
bool test_array_fire(){
af::randu(1, 4);
return true;
}
然后,我尝试使用sourceCpp
函数
Rcpp::sourceCpp('src/hello_world.cpp')
我的第一个惊喜是必须手动设置一些标志(sourceCpp
在编译一段C ++代码时似乎忽略了 Makevars 配置)。
我这样做的是:
Sys.setenv("PKG_CXXFLAGS"="-std=c++11")
Sys.setenv("PKG_CPPFLAGS"="-I/opt/arrayfire/include/")
Sys.setenv("PKG_LIBS"="-L/opt/arrayfire/lib64/ -laf")
但是,代码仍然无法正确编译。每个试验以以下输出结束:
Error in 'dyn.load("/tmp/RtmpHaODIU/sourceCpp-x86_64-pc-linux-gnu-1.0.2/sourcecpp_689c5adb8d/sourceCpp_14.so")':
unable to load shared object '/tmp/RtmpHaODIU/sourceCpp-x86_64-pc-linux-gnu-1.0.2/sourcecpp_689c5adb8d/sourceCpp_14.so':
libaf.so.3: cannot open shared object file: No such file or directory
不幸的是,我找不到解决问题的方法(即使某些堆栈溢出问题引起的问题乍一看也差不多)。
我该如何解决?
答案 0 :(得分:3)
当R尝试加载共享对象文件时,该错误会在处理过程中很晚才发生。这意味着在您设置的环境变量的帮助下,编译和链接可以正常工作。但是在最后一步,运行时链接程序不知道libaf.so.3
的位置。这是通常在OS级别执行的一种配置。在我的系统上
ralf@barra:~$ /sbin/ldconfig -p | grep libaf
libafopencl.so.3 (libc6,x86-64) => /lib/libafopencl.so.3
libafopencl.so (libc6,x86-64) => /lib/libafopencl.so
libafcpu.so.3 (libc6,x86-64) => /lib/libafcpu.so.3
libafcpu.so (libc6,x86-64) => /lib/libafcpu.so
libaf.so.3 (libc6,x86-64) => /lib/libaf.so.3
libaf.so (libc6,x86-64) => /lib/libaf.so
如果我尝试您的示例,则与libaf
链接的共享对象文件不会出现问题:
ralf@barra:~$ ldd /tmp/RtmpcjY9dN/sourceCpp-x86_64-pc-linux-gnu-1.0.2/sourcecpp_13d33790279c/sourceCpp_7.so | grep libaf
libaf.so.3 => /lib/libaf.so.3 (0x00007f21037ed000)
我希望您的情况下,第一个命令不会提供任何结果,第二个(调整后的)命令会导致“找不到文件”(?)错误。
有几种方法可以告诉运行时链接程序有关库的位置:
/etc/ld.so.conf
或(更好)将文件放置在/etc.ld.so.conf.d/
中,请参见http://arrayfire.org/docs/installing.htm#Linux。LD_LIBRARY_PATH
。-Wl,-rpath,/opt/arrayfire/lib64/
添加到PKG_LIBS
对于Rcpp::sourceCpp
不遵守Makevars
文件的问题:问题是您编写的C ++文件不能直接使用。而是Rcpp属性必须创建其他包装函数,这是在临时目录中完成的。现在,原则上也可以将Makevars
文件复制到该目录中。但是,通常使用Rcpp::plugins
和Rcpp::depends
属性来设置此类变量。例如,使用// [[Rcpp::plugins(cpp11)]]
完成打开C ++ 11的操作。对于其他变量,您可以编写自己的插件,也可以编写由我的RcppArrayFire提供的插件。
但是,如果您的目标是,我建议您从一个包装开始。 Rcpp::sourceCpp
在很多方面都很有用,但是在没有R软件包帮助的情况下与系统安装的库进行接口并不是其中之一。
答案 1 :(得分:2)
一些事情,很快:
sourceCpp()
时不使用包裹因此,我可能首先从Rcpp Gallery article about RcppArrayFire重做/重建示例。