英文:
Building custom R package leads to undefined symbol
问题
我目前正在开发一个依赖于Eigen、EigenRand和GSL的R包。当它只依赖于Eigen和GSL时,我成功地构建了这个包。但现在,当我构建时,编译是成功的,但R无法链接.so文件。
这是我的Makevars文件:
PKG_LIBS = $(R_HOME)/bin/Rscript -e "Rcpp:::LdFlags()" `gsl-config --libs`
PKG_CPPFLAGS = -I '/path/to/include/eigen-3.4.0' -I '/path/to/include/EigenRand'
这是错误信息:
Error: package or namespace load failed for ‘pkgname’ in dyn.load(file, DLLpath = DLLpath, ...):
unable to load shared object '/tmp/RtmpwgpGqO/Rinst855c41160545/00LOCK-pkgname/00new/pkgname/libs/pkgname.so':
/tmp/RtmpwgpGqO/Rinst855c41160545/00LOCK-pkgname/00new/pkgname/libs/pkgname.so: undefined symbol: _ZN4Rcpp9RcppEigen10eigen_wrapIN5Eigen5ArrayIiLin1ELin1ELi0ELin1ELin1EEEEEP7SEXPRECRKT_
Error: loading failed
Execution halted
ERROR: loading failed
我已将实际名称更改为“pkgname”以适应情况。
在代码只涉及Eigen和GSL时,我成功地编译并链接到了一个包,所以我不认为这是这两个库的问题。安装RcppEigen导致未知包含错误,所以我没有切换到RcppEigen。
编辑:我认为我可以使用这个设置复现问题。我猜我无法构建Eigen,但因为我没有返回使用Eigen创建的数组,编译器为我进行了优化。不过,我仍然有兴趣知道出了什么问题,因为即使我要使用RcppEigen库,我仍然需要导入EigenRand,而这个库目前还没有R包。
src/pkgexports.cpp:
#include <Rcpp.h>
using namespace Rcpp;
List pkgfn();
RcppExport SEXP pkgfn_pkgfn() {
BEGIN_RCPP
Rcpp::RObject __result;
Rcpp::traits::input_parameter<int>::type seed(seedSEXP);
__result = Rcpp::wrap(pkgfn());
return __result;
END_RCPP
}
src/pkgfn.cpp:
#include <R.h>
#include <Rmath.h>
#include <Rcpp.h>
#include <Eigen/Dense>
using Rcpp::List;
using Rcpp::_;
using namespace Eigen;
List pkgfn(){
ArrayXd r_beta = ArrayXd::Random(4);
return List::create(_["r_beta"] = r_beta);
}
Makevars:
PKG_CPPFLAGS = -I '/usr/local/include/eigen3'
编辑2:我已经在另一个环境中使用Mamba/Conda安装了所有其他库,但由于Eigen和EigenRand似乎没有适用于它们的通道,所以我从源代码安装了它们,并将它们添加到了/usr/local/include
中。
英文:
I'm currently working on a R package that depends on Eigen, EigenRand, and GSL. I was able to successfully build the package when it just depended on Eigen and GSL. Now, when I build, the compile is successful, but R is not able to link the .so file.
this is my Makevars file:
PKG_LIBS = $(R_HOME)/bin/Rscript -e "Rcpp:::LdFlags()"` `gsl-config --libs`
PKG_CPPFLAGS = -I '/path/to/include/eigen-3.4.0' -I '/path/to/include/EigenRand'
this is the error message:
Error: package or namespace load failed for ‘pkgname’ in dyn.load(file, DLLpath = DLLpath, ...):
unable to load shared object '/tmp/RtmpwgpGqO/Rinst855c41160545/00LOCK-pkgname/00new/pkgname/libs/pkgname.so':
/tmp/RtmpwgpGqO/Rinst855c41160545/00LOCK-pkgname/00new/pkgname/libs/pkgname.so: undefined symbol: _ZN4Rcpp9RcppEigen10eigen_wrapIN5Eigen5ArrayIiLin1ELin1ELi0ELin1ELin1EEEEEP7SEXPRECRKT_
Error: loading failed
Execution halted
ERROR: loading failed
I’ve changed the actual name to “pkgname” where it fits.
I was able to successfully compile and link to a package when the code just involved Eigen and GSL so I don’t think it’s a problem with these two libraries, and installing RcppEigen led to error with unknown includes, so I didn’t switch to RcppEigen.
Edit: I think I can reproduce the problem with this setup. I guess I couldn't build with Eigen, but because I didn't return the array created with Eigen, the compiler optimised it away for me. I would still be interested in knowing what went wrong though because even if I were to use the RcppEigen library, I still need to import EigenRand, which does not have a R package yet.
src/pkgexports.cpp:
#include <Rcpp.h>
using namespace Rcpp;
List pkgfn();
RcppExport SEXP pkgfn_pkgfn() {
BEGIN_RCPP
Rcpp::RObject __result;
Rcpp::traits::input_parameter< int >::type seed(seedSEXP);
__result = Rcpp::wrap(pkgfn());
return __result;
END_RCPP
}
src/pkgfn.cpp:
#include <R.h>
#include <Rmath.h>
#include <Rcpp.h>
#include <Eigen/Dense>
using Rcpp::List;
using Rcpp::_;
using namespace Eigen;
List pkgfn(){
ArrayXd r_beta = ArrayXd::Random(4);
return List::create(_["r_beta"] = r_beta);
}
Makevars:
PKG_CPPFLAGS = -I '/usr/local/include/eigen3'
Edit2: I've installed all other libraries using Mamba/Conda in another enviroment, but because Eigen & EigenRand doesn't seem to have channels for that I have installed them from source and added them to /usr/local/include
答案1
得分: 1
以下是您要翻译的内容:
I would write that this way (and note that the [[Rcpp::depends(RcppEigen)]]
would not be needed in your test package, just have a LinkingTo: RcppEigen
there).
In particular the second one-line version is pretty good, but if you want to get by with just Rcpp
you can also use the first.
Code
#include <RcppEigen.h> // single header all you need
// need just for the Rcpp::sourceCpp() demo
// [[Rcpp::depends(RcppEigen)]]
// [[Rcpp::export]]
std::vector<double> pkgfun() {
Eigen::ArrayXd r_beta = Eigen::ArrayXd::Random(4);
auto r_beta_vec = std::vector<double>(r_beta.data(), r_beta.data()+4);
return r_beta_vec;
}
// [[Rcpp::export]]
Eigen::ArrayXd pkgfun2() {
return Eigen::ArrayXd::Random(4);
}
/*** R
pkgfun()
pkgfun2()
#### Output
Calling `sourceCpp()` compiles, links and loads the code -- and also sources the R portion at the bottom inside `/*** R ... */` for you:
```r
> Rcpp::sourceCpp("~/git/stackoverflow/76600261/answer.cpp")
> pkgfun();
[1] -0.9803230 -0.2274045 0.0327535 0.8861597
> pkgfun2()
[1] -0.427496 -0.891072 0.897365 -0.876335
>
英文:
I would write that this way (and note that the [[Rcpp::depends(RcppEigen)]]
would not be needed in your test package, just have a LinkingTo: RcppEigen
there).
In particular the second one-line version is pretty good, but if you want to get by with just Rcpp
you can also use the first.
Code
#include <RcppEigen.h> // single header all you need
// need just for the Rcpp::sourceCpp() demo
// [[Rcpp::depends(RcppEigen)]]
// [[Rcpp::export]]
std::vector<double> pkgfun() {
Eigen::ArrayXd r_beta = Eigen::ArrayXd::Random(4);
auto r_beta_vec = std::vector<double>(r_beta.data(), r_beta.data()+4);
return r_beta_vec;
}
// [[Rcpp::export]]
Eigen::ArrayXd pkgfun2() {
return Eigen::ArrayXd::Random(4);
}
/*** R
pkgfun()
pkgfun2()
*/
Output
Calling sourceCpp()
compiles, links and loads the code -- and also sources the R portion at the bottom inside /*** R ... */
for you:
> Rcpp::sourceCpp("~/git/stackoverflow/76600261/answer.cpp")
> pkgfun();
[1] -0.9803230 -0.2274045 0.0327535 0.8861597
> pkgfun2()
[1] -0.427496 -0.891072 0.897365 -0.876335
>
答案2
得分: 0
这似乎解决了问题。包含这些库没有问题。
src/pkgfn.cpp:
#include <R.h>
#include <Rmath.h>
#include <Rcpp.h>
#include <Eigen/Dense>
using Rcpp::List;
using Rcpp::_;
using namespace Eigen;
List pkgfn(){
ArrayXd r_beta = ArrayXd::Random(4);
auto r_beta_vec = vector<double>(r_beta.data(), r_beta.data()+4);
return List::create(_["r_beta"] = r_beta_vec);
}
英文:
This seems to solve the problem. There was nothing wrong with including the libraries.
src/pkgfn.cpp:
#include <R.h>
#include <Rmath.h>
#include <Rcpp.h>
#include <Eigen/Dense>
using Rcpp::List;
using Rcpp::_;
using namespace Eigen;
List pkgfn(){
ArrayXd r_beta = ArrayXd::Random(4);
auto r_beta_vec = vector<double>(r_beta.data(), r_beta.data()+4);
return List::create(_["r_beta"] = r_beta_vec);
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论