useDynLib() 错误和 compileAttributes returns 无:将 C 库嵌入到 R 包中

useDynLib() error and compileAttributes returns nothing: embedding a C library into an R package

我有一个 C 包,它构建了一个带有多个参数标志的可执行文件。一个使用 Makefile 编译代码(我知道,这需要针对 R 包进行更改)并通过

创建一个可执行文件 运行

$ ./codeName -f path/inputfile -o path/outputfile -p ## -s "type"

我的目标是集成此 C 程序包中使用的几个函数以与 R 库一起使用。我看一下使用 C 的 R 包 github.com/cran 的一些示例。在编写 R 扩展中,它解释了我如何使用 .Call()Makevars 从 R 调用 C 函数。我想避免像瘟疫一样。但是,看起来这需要使用 SEXP 对象进行大量重写——所以我求助于 Rcpp(是的!)

我创建包 Rcpp.package.skeleton("packageName")

太棒了。在 R 中,我执行以下操作:

$ R
> library(devtools)
> build()  # works!
> install() # works!
> library(packageName)
> rcpp_hello_world()
## expected output

一切正常。然后我将我的 C 包添加到 /src。然后,我通过 R 在包根目录中执行 Rcpp::compileAttributes()——没有任何反应,也没有任何输出,这是预料之中的,因为我根本还没有更改 C 代码。

我尝试使用上面的命令安装:devtools::build()devtools::install()。通过 Makefile,看起来 C 代码可以完美编译!但是还有这个问题:

** R
** preparing package for lazy loading
** help
*** installing help indices
** building package indices
** testing if installed package can be loaded
Error in library.dynam(lib, package, package.lib) : 
  shared object ‘packageName.so’ not found
Error: loading failed
Execution halted'
ERROR: loading failed

好吧,这有点令人困惑,我不知道为什么会这样,但问题是 NAMESPACE 中的 useDynLib("packageName")。如果我删除它,C 代码似乎可以编译,并且通过上面的 build/install 命令安装包。 rcpp_hello_world() 仍然有效。

(1) 为什么现在会出现这个错误‘packageName.so’ not found,我能绕过它吗?

(此题与Rcpp无关。)

然后,我转到 .c 文件。我加

#include <Rcpp.h>
using namespace Rcpp;

*.c 文件和 //[[Rcpp::export]] 我想导入的函数之前。 (我不确定这在 *.c 或 C 头文件中是否有效。)

接下来,我转到包根目录,打开 R 并尝试以下操作:

$ R
> library(Rcpp)
> compileAttributes()

运行没有错误。但是,没有生成 RcppExports.RRcppExports.cpp。编译C代码也会报找不到#include <Rcpp.h>的错误。

(2) 为什么 compileAttributes() 在此环境中不起作用?我一定是错误地使用了 Rcpp//[[Rcpp::export]] 以便将这些 C 函数包装成 R 可用的格式。

你会怎么称呼这个函数? C代码?

int fib(int n) { 
   if (n < 2) return n;
   return fib(n-1) + fib(n-2);
}

它作为 C 和 C++ 代码通过。所以我们称它为 C 代码。

您可以通过 Rcpp 与以下调用者清楚地从 R 接口:

// [[Rcpp::export]]
int callFib(int n) {
   return fib(n);
}

将它们全部粘在一起到一个 C++ 文件中,这样 Rcpp 就可以对它们进行操作(见评论),你就完成了。

R> library(Rcpp)
R> sourceCpp("/tmp/ex.cpp")

R> callFib(10)
[1] 55
R> 

完整文件如下。

#include <Rcpp.h>

int fib(int n) { 
  if (n < 2) return n;
  return fib(n-1) + fib(n-2);
}


// [[Rcpp::export]]
int callFib(int n) {
  return fib(n);
}

/*** R
callFib(10)
*/