使用 Rcpp 在 R 包中添加外部库

Posted

技术标签:

【中文标题】使用 Rcpp 在 R 包中添加外部库【英文标题】:Adding an external library in R package using Rcpp 【发布时间】:2016-06-10 16:32:24 【问题描述】:

我正在尝试开发一个 R 包,它使用 Sundials C 库来求解微分方程。为了不让用户安装库,我将库的源代码放在我的包中。

我已将库中的所有头文件放在我的包文件夹的 /inst/include/sundials-2.6.2.c 文件中的 src/sundials-2.6.2 中。

根据我阅读有关此主题的 SO 帖子,sourceCpp 多个文件中的代码(例如,如果将它们构造为包的一部分,则单独的 .h.cpp 文件应该可以工作。我是尝试从 Sundials 包中运行示例代码文件

我的代码(只有开始部分)看起来像

#include <Rcpp.h>

#include "../inst/include/sundials-2.6.2/cvode/cvode.h"             /* prototypes for CVODE fcts., consts. */
#include "../inst/include/sundials-2.6.2/nvector/nvector_serial.h"  /* serial N_Vector types, fcts., macros */
#include "../inst/include/sundials-2.6.2/cvode/cvode_dense.h"      /* prototype for CVDense */
#include "../inst/include/sundials-2.6.2/sundials/sundials_dense.h" /* definitions DlsMat DENSE_ELEM */
#include "../inst/include/sundials-2.6.2/sundials/sundials_types.h" /* definition of type realtype */

但是,我收到一个错误

fatal error: sundials/sundials_nvector.h: No such file or directory

我在以下 github 存储库中做了类似的示例

Rcppsundials - https://github.com/AleMorales/RcppSundials.R/blob/master/src/cvode.cpp

使用

调用头文件
#include <cvodes/cvodes.h>           // CVODES functions and constants
#include <nvector/nvector_serial.h>  // Serial N_Vector
#include <cvodes/cvodes_dense.h>     // CVDense

并在/inst/include/文件夹下合并了头文件。

这是我尝试开发的第一个包,而且我还没有广泛使用 C/C++,所以我尝试编译这个程序的方式可能有些愚蠢。

只是附注 - 我能够在我的 OSX 机器上安装和运行一个示例,但目前我正在使用没有安装日晷的 Windows 机器工作。它确实安装了Rtools,所以我可以编译并运行示例Rcpp 程序。

谢谢 序列号

【问题讨论】:

尝试将-I src/solver/ 添加到Makevars 中的PKG_CXXFLAGS 变量,因为src/solver/sundials/ 中有sundials/ @nrussell 他链接的 repo 是一个不同的项目,他用作参考来编写自己的项目。 啊。错过了那部分。 【参考方案1】:

外部库链接应通过以下设置完成:

R/
inst/
  |- include/
     |- sundials/ 
  |- header.h
src/
  |- sundials/
  |- Makevars
  |- Makevars.win
  |- action.cpp
man/
DESCRIPTION
NAMESPACE

然后添加以下内容:

PKG_LIBS = $(LAPACK_LIBS) $(BLAS_LIBS) $(FLIBS)
PKG_CPPFLAGS =  -I../inst/include/ -I src/sundials

MakevarsMakevars.win

在这里,我选择从文件夹名称中删除日晷版本号。

编辑

我已经进行了编译包所需的修复:

https://github.com/sn248/Rcppsbmod/pull/1

注意:

结构是:

inst/
  |- include/
     |- sundials/  
        |- arkode/
        .....
        |- nvector/  
        |- sundials/ 
  |- header.h

这将强制包含语句:

#include <sundials/cvodes/cvodes.h>           // CVODES functions and constants
#include <sundials/nvector/nvector_serial.h>  // Serial N_Vector
#include <sundials/cvodes/cvodes_dense.h>     // CVDense

我改变了它:

inst/
  |- include/
     |- arkode/
     .....
     |- nvector/  
     |- sundials/ 
  |- header.h

所以,语句将永远是:

#include <cvodes/cvodes.h>           // CVODES functions and constants
#include <nvector/nvector_serial.h>  // Serial N_Vector
#include <cvodes/cvodes_dense.h>     // CVDense

【讨论】:

谢谢@Coatless 和@nrussell。我在src 文件夹中添加了MakevarsMakevars.win 文件。我尝试了#include &lt;sundials/cvode.cvode.h&gt;#include "../inst/include/sundials/cvode/cvode.h" (我将文件夹名称更改为sundials)。我仍然遇到同样的错误 - sundials_test.cpp:5:103: fatal error: ..inst/include/sundials/cvode/cvode.h: No such file or directory 谢谢@Coatless。您的建议在我的 OS X 机器上有效,我还没有在 Windows 上尝试过。我在 -github.com/sn248/Rcppsbmod/tree/master/src 发布了代码。 /src/sundials_test.cpp 尚未完成。我在代码的line 30 上收到C++ requires a type specifier for all declarations 错误(与此问题无关)。在我的 OS X 上运行的库中的原始完整代码位于要点 - gist.github.com/sn248/b2e7726f609625df01f463715d5aa414。希望你能帮助我找出这个错误。谢谢。 非常感谢@Coatless 的解释和修复代码。我将查看拉取请求并继续尝试编译和运行库的示例。 谢谢@Coatless,在您的帮助下,我成功地完成了sourcesundials_test.cpp 文件。但是,在RStudio 中运行load allclean and rebuild 命令时,我收到错误ld: warning: directory not found for option '-L/usr/local/lib/gcc/x86_64-apple-darwin13.0.0/4.8.2' ld: library not found for -lgfortran clang: error: linker command failed with exit code 1 (use -v to see invocation) make: *** [Rcppsbmod.so] Error 1 ERROR: compilation failed for package ‘Rcppsbmod’。你能帮我解决这个错误吗?谢谢! 在这里查看我的帖子@SN248:thecoatlessprofessor.com/programming/…

以上是关于使用 Rcpp 在 R 包中添加外部库的主要内容,如果未能解决你的问题,请参考以下文章

将外部库添加到 CMakeList.txt c++

将Rcpp头文件导入NAMESPACE中的R包中

尝试使用外部库时未定义的引用

在 npm 包中重新导出外部类型

在 R 中转换单位

使用 Rcpp 模块向 R 公开简单的 C++ Student 类