我试图使用包rlas
中的c ++类(在CRAN上)。我写了以下内容:
#include <Rcpp.h>
#include <rlasstreamer.h>
// [[Rcpp::depends(rlas)]]
using namespace Rcpp;
// [[Rcpp::export]]
void f(CharacterVector file)
{
RLASstreamer lasstreamer(file);
return;
}
我还在LinkingTo: Rcpp,rlas
中添加了DESCRIPTION
。包编译,因此找到标题但是库没有链接:
undefined symbol: _ZN12RLASstreamerD1Ev
联动命令看起来与rlas
g++ -shared -L/usr/lib/R/lib -Wl,-Bsymbolic-functions -Wl,-z,relro -o pkgname.so function_f.o RcppExports.o -L/usr/lib/R/lib -lR
作为一种解决方案,我通过创建一个Makevars
作为解决方案,其中包含了我home/
中库的硬编码路径。
PKG_LIBS= /home/user/R/x86_64-pc-linux-gnu-library/3.4/rlas/libs/rlas.so
它有效!
我认为这是Rcpp::depends
标签的工作。我错过了哪一个正确链接另一个R包?它可能来自rlas
可能不正确的包裹吗?
答案 0 :(得分:1)
您可以在Makevars
期间动态创建合适的条目,而不是在configure
中使用硬编码路径。这里有一些可用于查找库位置的R代码:
libs.dir <- system.file( "libs", package = "rlas")
paste0(libs.dir, .Platform$file.sep, "rlas", .Platform$dynlib.ext)
您甚至可以将其与rlas
功能一起添加到rlas.package.skeleton
。例如,参见我的RcppArrayFire包:
编辑:这是一个成功的例子:
创建包骨架,更改目录
$ Rscript -e "Rcpp::Rcpp.package.skeleton()"
$ cd anRpackage
创建或更新一些文件:
$ cat configure
#!/bin/sh
RLAS_LIBS=`Rscript -e "cat(system.file('libs', 'rlas.so', package = 'rlas'))"`
sed -e "s|@RLAS_LIBS@|${RLAS_LIBS}|" src/Makevars.in > src/Makevars
$ cat cleanup
#!/bin/sh
rm -f src/Makevars src/*.o src/*.so
$ cat src/Makevars.in
PKG_LIBS = @RLAS_LIBS@
$ cat src/rcpp_hello_world.cpp
#include <Rcpp.h>
#include <rlasstreamer.h>
// [[Rcpp::export]]
void rcpp_hello_world() {
RLASstreamer lasstreamer("foo");
return;
}
$ grep rlas DESCRIPTION
LinkingTo: Rcpp, rlas
编译Rcpp属性:
$ Rscript -e "Rcpp::compileAttributes()"
构建,检查并安装软件包:
$ R CMD build .
[...]
$ R CMD check anRpackage_1.0.tar.gz
[...]
$ R CMD INSTALL anRpackage_1.0.tar.gz
[...]
g++ -shared -L/usr/lib/R/lib -Wl,-z,relro -o anRpackage.so RcppExports.o rcpp_hello_world.o /usr/local/lib/R/site-library/rlas/libs/rlas.so -L/usr/lib/R/lib -lR
[...]
此处链接器的命令行很有意义。它显示rlas.so
包含在完整路径中。现在试试这个包:
$ Rscript -e "anRpackage::rcpp_hello_world()"
ERROR: cannot open file 'foo'
ERROR: cannot open lasreadertxt with file name 'foo'
Fehler in anRpackage::rcpp_hello_world() :
LASlib internal error. See message above.
Execution halted
因此,当我们收到错误时,这是来自LASlib的错误,它包含在rlas.so
中。如果我们查看ldd
的输出,我们会再次看到rlas.so
包含在完整路径中,这与其他链接库不同:
$ ldd ~/R/x86_64-pc-linux-gnu-library/3.5/anRpackage/libs/anRpackage.so
linux-vdso.so.1 (0x00007ffe4c79d000)
/usr/local/lib/R/site-library/rlas/libs/rlas.so (0x00007fede63fc000)
libR.so => /usr/lib/libR.so (0x00007fede5d7a000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fede59f8000)
[...]