Building custom R package leads to undefined symbol

huangapple go评论64阅读模式
英文:

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 &quot;Rcpp:::LdFlags()&quot;` `gsl-config --libs`
PKG_CPPFLAGS = -I &#39;/path/to/include/eigen-3.4.0&#39; -I &#39;/path/to/include/EigenRand&#39;

this is the error message:

Error: package or namespace load failed for ‘pkgname’ in dyn.load(file, DLLpath = DLLpath, ...):
 unable to load shared object &#39;/tmp/RtmpwgpGqO/Rinst855c41160545/00LOCK-pkgname/00new/pkgname/libs/pkgname.so&#39;:
  /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 &lt;Rcpp.h&gt;
using namespace Rcpp;

List pkgfn();
RcppExport SEXP pkgfn_pkgfn() {
BEGIN_RCPP
    Rcpp::RObject __result;
    Rcpp::traits::input_parameter&lt; int &gt;::type seed(seedSEXP);

    __result = Rcpp::wrap(pkgfn());
    return __result;
END_RCPP
} 

src/pkgfn.cpp:

#include &lt;R.h&gt;
#include &lt;Rmath.h&gt;
#include &lt;Rcpp.h&gt;
#include &lt;Eigen/Dense&gt;

using Rcpp::List;
using Rcpp::_;
using namespace Eigen;

List pkgfn(){
    ArrayXd r_beta = ArrayXd::Random(4);
  	return List::create(_[&quot;r_beta&quot;] = r_beta);
}

Makevars:

PKG_CPPFLAGS = -I &#39;/usr/local/include/eigen3&#39;  

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 &lt;RcppEigen.h&gt; // single header all you need

// need just for the Rcpp::sourceCpp() demo
// [[Rcpp::depends(RcppEigen)]]

// [[Rcpp::export]]
std::vector&lt;double&gt; pkgfun() {
    Eigen::ArrayXd r_beta = Eigen::ArrayXd::Random(4);
    auto r_beta_vec = std::vector&lt;double&gt;(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:

&gt; Rcpp::sourceCpp(&quot;~/git/stackoverflow/76600261/answer.cpp&quot;)

&gt; pkgfun();
[1] -0.9803230 -0.2274045  0.0327535  0.8861597

&gt; pkgfun2()
[1] -0.427496 -0.891072  0.897365 -0.876335
&gt; 

答案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 &lt;R.h&gt;
#include &lt;Rmath.h&gt;
#include &lt;Rcpp.h&gt;
#include &lt;Eigen/Dense&gt;

using Rcpp::List;
using Rcpp::_;
using namespace Eigen;

List pkgfn(){
    ArrayXd r_beta = ArrayXd::Random(4);
    auto r_beta_vec = vector&lt;double&gt;(r_beta.data(), r_beta.data()+4);
  	return List::create(_[&quot;r_beta&quot;] = r_beta_vec);
}

huangapple
  • 本文由 发表于 2023年7月3日 02:28:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/76600261.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定