首先,免责声明:我使用Rcpp http://dirk.eddelbuettel.com/code/rcpp.html每时每刻。事实上,当(从 Rcpp 更名时)RcppTemplate 已经被孤立并且两年没有更新时,我开始以其最初的名称 Rcpp 来维护它(在这个名称下,它被贡献给了RQuantLib http://dirk.eddelbuettel.com/code/rquantlib.html)。那是大约一年前的事,我做了一些增量更改,您可以在更改日志中找到这些更改。
现在,RcppTemplate 在整整三十五个月没有任何更新或修复后最近又回来了。它包含有趣的新代码,但它似乎不向后兼容,所以我不会在已经使用 Rcpp 的地方使用它。
Rcppbind http://r-forge.r-project.org/projects/rcppbind/每当我检查时都没有非常积极地维护。 Whit Armstrong 还有一个模板化界面包,称为抽象 http://github.com/armstrtw/rabstraction.
Inline http://cran.r-project.org/web/packages/inline/index.html是完全不同的东西:它通过将程序“嵌入”为 R 字符串来简化编译/链接周期,然后进行编译、链接和加载。我已经与 Oleg 讨论了内联支持 Rcpp 的问题,这会很好。
Swig http://www.swig.org也很有趣。 Joe Wang 在那里做了出色的工作,并包装了 R 的所有 QuantLib。但是当我上次尝试它时,由于 R 内部的一些变化,它不再起作用。据 Swig 团队的某人透露,Joe 可能仍在研究它。无论如何,Swig 的目标是更大的库。该项目可能会复兴,但并非没有技术挑战。
另一个提及应该去RInside http://dirk.eddelbuettel.com/code/rinside.html它与 Rcpp 配合使用,让您可以将 R 嵌入到 C++ 应用程序中。
总结一下:Rcpp http://dirk.eddelbuettel.com/code/rcpp.html对我来说效果很好,特别是对于您只想添加一两个功能的小型探索性项目。它的重点是易用性,它允许您“隐藏”一些使用起来并不总是有趣的 R 内部结构。我认识一些其他用户,我曾通过电子邮件时断时续地为他们提供过帮助。所以我想说,就选这个吧。
我的“R HPC 简介”教程提供了一些 Rcpp、RInside 和内联示例。
Edit:让我们看一个具体的例子(取自“HPC with R Intro”幻灯片,借用自 Stephen Milborrow,而 Stephen Milborrow 则来自 Venables 和 Ripley)。任务是枚举每个位置仅包含单个数字的 2x2 矩阵行列式的所有可能组合。这可以通过巧妙的矢量化方式(正如我们在教程幻灯片中讨论的那样)或通过暴力来完成,如下所示:
#include <Rcpp.h>
RcppExport SEXP dd_rcpp(SEXP v) {
SEXP rl = R_NilValue; // Use this when there is nothing to be returned.
char* exceptionMesg = NULL; // msg var in case of error
try {
RcppVector<int> vec(v); // vec parameter viewed as vector of ints
int n = vec.size(), i = 0;
if (n != 10000)
throw std::length_error("Wrong vector size");
for (int a = 0; a < 9; a++)
for (int b = 0; b < 9; b++)
for (int c = 0; c < 9; c++)
for (int d = 0; d < 9; d++)
vec(i++) = a*b - c*d;
RcppResultSet rs; // Build result set to be returned as list to R
rs.add("vec", vec); // vec as named element with name 'vec'
rl = rs.getReturnList(); // Get the list to be returned to R.
} catch(std::exception& ex) {
exceptionMesg = copyMessageToR(ex.what());
} catch(...) {
exceptionMesg = copyMessageToR("unknown reason");
}
if (exceptionMesg != NULL)
Rf_error(exceptionMesg);
return rl;
}
如果您将其另存为,例如,dd.rcpp.cpp
并有Rcpp http://dirk.eddelbuettel.com/code/rcpp.html安装后,只需使用
PKG_CPPFLAGS=`Rscript -e 'Rcpp:::CxxFlags()'` \
PKG_LIBS=`Rscript -e 'Rcpp:::LdFlags()'` \
R CMD SHLIB dd.rcpp.cpp
建立一个共享库。我们用Rscript
(or r
)询问Rcpp http://dirk.eddelbuettel.com/code/rcpp.html关于其标头和库位置。构建完成后,我们可以从 R 加载并使用它,如下所示:
dyn.load("dd.rcpp.so")
dd.rcpp <- function() {
x <- integer(10000)
res <- .Call("dd_rcpp", x)
tabulate(res$vec)
}
同样,您可以轻松地向后端发送各种 R 和 C++ 数据类型的向量、矩阵等。希望这会有所帮助。
编辑2(大约五年多后):
所以这个答案刚刚得到了赞成票,因此在我的队列中出现。 Alot自从我写它以来已经过去了很多年,Rcpp 已经得到了a lot功能更加丰富。所以我很快就写了这个
#include <Rcpp.h>
// [[Rcpp::export]]
Rcpp::IntegerVector dd2(Rcpp::IntegerVector vec) {
int n = vec.size(), i = 0;
if (n != 10000)
throw std::length_error("Wrong vector size");
for (int a = 0; a < 9; a++)
for (int b = 0; b < 9; b++)
for (int c = 0; c < 9; c++)
for (int d = 0; d < 9; d++)
vec(i++) = a*b - c*d;
return vec;
}
/*** R
x <- integer(10000)
tabulate( dd2(x) )
*/
可以将其与文件中的代码一起使用,如下所示/tmp/dd.cpp
R> Rcpp::sourceCpp("/tmp/dd.cpp") # on from any other file and path
R> x <- integer(10000)
R> tabulate( dd2(x) )
[1] 87 132 105 155 93 158 91 161 72 104 45 147 41 96
[15] 72 120 36 90 32 87 67 42 26 120 41 36 27 75
[29] 20 62 16 69 19 28 49 45 12 18 11 57 14 48
[43] 10 18 7 12 6 46 23 10 4 10 4 6 3 38
[57] 2 4 2 3 2 2 1 17
R>
一些主要差异是:
- 更简单的构建:只是
sourceCpp()
它;甚至最后执行 R 测试代码
- 成熟的
IntegerVector
type
- 异常处理包装器自动添加
sourceCpp()
代码生成器