Rcpp:无法打开共享对象文件 [英] Rcpp: cannot open shared object file

查看:115
本文介绍了Rcpp:无法打开共享对象文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试开发一个 R 包,它使用了 Arrayfire,感谢 Rcpp图书馆.我已经开始编写示例代码(让我们将其命名为 hello_world.cpp),如下所示:

I'm trying to develop an R package, which makes use of Arrayfire, thanks to Rcpp library. I've started writing a sample code (let's name it hello_world.cpp) which looks like this:

#include <arrayfire.h>

// [[Rcpp::export]]
bool test_array_fire(){
    af::randu(1, 4);    
    return true;
}

然后,我尝试使用 sourceCpp 函数来编译它

Then, I tried to compile it using a sourceCpp function

Rcpp::sourceCpp('src/hello_world.cpp')

我的第一个惊喜是我必须手动设置一些标志(sourceCpp 在编译一段 C++ 代码时似乎忽略了 Makevars 配置).我是这样做的:

My first suprise was the fact I had to set some flags manually (sourceCpp seems to ignore Makevars config when compiling a piece of C++ code). I did it with:

Sys.setenv("PKG_CXXFLAGS"="-std=c++11")
Sys.setenv("PKG_CPPFLAGS"="-I/opt/arrayfire/include/")
Sys.setenv("PKG_LIBS"="-L/opt/arrayfire/lib64/ -laf")

但是,代码仍然无法正确编译.每次试验都以以下输出结束:

However, the code still does not compile properly. Each trial finishes with the following output:

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

不幸的是,我找不到解决我的问题的方法(即使某些 Stack Overflow 问题引发了乍一看或多或少相似的问题).

Unfortunately, I could not find an solution for my problem (even if some Stack Overflow questions raise issues which are more or less similar at first glance).

我该如何解决?

推荐答案

该错误发生在 R 尝试加载共享对象文件的过程中很晚.这意味着在您设置的环境变量的帮助下,编译和链接工作正常.但在最后一步中,运行时链接器 不知道 libaf.so.3 位于何处.这是一种通常在操作系统级别进行的配置,例如在我的系统上

The error occurs very late in the process when R tries to load the shared object file. This means that compilation and linking worked fine with the help of the environment variables you set. But in the final step the run-time linker does not know where libaf.so.3 is located. This is a configuration one normally does at the OS level, e.g. on my system

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 链接的共享对象文件中正常工作:

And if I try your example it works without problems with a shared object file that is linked against 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)

我希望在您的情况下,第一个命令不会提供任何结果,第二个(调整后的)命令会导致找不到文件"(?)错误.

I expect that in your case the first command will provide no result and the second (adjusted) command will lead a "file not found"(?) error.

有几种方法可以告诉运行时链接器库的位置:

There are several ways to tell the run-time linker about the location of the library:

  • 编辑 /etc/ld.so.conf 或(更好)在 /etc/ld.so.conf.d/ 中放置一个文件,c.f.http://arrayfire.org/docs/installing.htm#Linux.立>
  • 设置LD_LIBRARY_PATH.
  • -Wl,-rpath,/opt/arrayfire/lib64/ 添加到 PKG_LIBS
  • 将 ArrayFire 安装到链接器默认搜索的目录中.这就是我所做的,因为我从源代码编译并使用 结果DEB 包.
  • Edit /etc/ld.so.conf or (better) place a file in /etc/ld.so.conf.d/, c.f. http://arrayfire.org/docs/installing.htm#Linux.
  • Set LD_LIBRARY_PATH.
  • Add -Wl,-rpath,/opt/arrayfire/lib64/ to PKG_LIBS
  • Install ArrayFire into a directory that the linker searches by default. That's what I am doing since I compile from source and use the resulting DEB packages.

至于Rcpp::sourceCpp不尊重Makevars文件:问题是你写的C++文件不能直接使用.相反,Rcpp 属性必须创建额外的包装函数,这是在临时目录中完成的.现在原则上也可以将 Makevars 文件复制到该目录中.然而,通常在 Rcpp::pluginsRcpp::depends 属性的帮助下设置这些变量.例如,使用 //[[Rcpp::plugins(cpp11)]] 完成 C++11 的切换.对于其他变量,您可以编写自己的插件,或者我们编写由我的 RcppArrayFire 提供的插件.

As for Rcpp::sourceCpp not respecting a Makevars file: The problem is that the C++ file you write cannot be used directly. Instead Rcpp attributes has to create additional wrapper functions, which is done in a temporary directory. Now one could in principle copy a Makevars file into that directory as well. However, one normally sets such variables with the help of Rcpp::plugins and Rcpp::depends attributes. For example, switching on C++11 is done using // [[Rcpp::plugins(cpp11)]]. For the other variables, you could write your own plugin or us the one provided by my RcppArrayFire.

但是,如果这是您的目标,我建议您从一个包开始.Rcpp::sourceCpp 在很多方面都很棒,但在没有 R 包帮助的情况下与系统安装的库接口不是其中之一.

However, I suggest you start with a package if that is your goal. Rcpp::sourceCpp is great for many things, but interfacing with a system installed library without the help of an R package is not one of them.

这篇关于Rcpp:无法打开共享对象文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆