我目前有一个.cpp
文件,我可以使用sourceCpp()
编译。正如预期的那样,创建了相应的R函数,代码按预期工作。
这是:
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector exampleOne(NumericVector vectorOne, NumericVector vectorTwo){
NumericVector outputVector = vectorOne + vectorTwo;
return outputVector;
}
我现在正在使用Rcpp
将项目转换为包。所以我用rStudio创建了骨架,并开始研究如何将事物转换过来。
在Hadley的excellent primer on Cpp中,他在第34节中说道;在一个包中使用Rcpp&#34;:
如果您的包使用Rcpp :: export属性,则需要在包构建过程中增加一个步骤。 compileAttributes函数扫描包中的源文件以获取Rcpp :: export属性,并生成将函数导出到R所需的代码。
每当添加,删除函数或更改其签名时,都应重新运行compileAttributes。请注意,如果使用RStudio或devtools构建程序包,则会自动执行此步骤。
因此看起来使用sourceCpp()
编译的代码应该与包中的代码一样。
我创建了相应的R文件。
exampleOne <- function(vectorOne, vectorTwo){
outToR <- .Call("exampleOne", vectorOne, vectorTwo, PACKAGE ="testPackage")
outToR
}
然后我(重新)构建了包,我收到了这个错误:
Error in .Call("exampleOne", vectorOne, vectorTwo, PACKAGE = "voteR") :
C symbol name "exampleOne" not in DLL for package "testPackage"
有没有人知道在使用sourceCpp()编译然后在包中使用它时需要做什么?
我应该注意到我已经读过:&#34;编写一个使用Rcpp&#34; http://cran.rstudio.com/web/packages/Rcpp/vignettes/Rcpp-package.pdf并了解那里提出的基本结构。但是,在查看RcppExamples
源代码后,似乎晕影中的结构与示例包中使用的结构不完全相同。例如,没有使用.h文件。插图和源代码也不使用[[Rcpp :: export]]属性。这一切都很难准确追踪我的错误。
答案 0 :(得分:8)
这是我如何从使用sourceCpp()到使用Rcpp的包的“演练”。如果有错误,请随时编辑或让我知道,我将编辑它。
[注意:我强烈建议在此过程中使用RStudio。]
因此,您需要对sourceCpp()事情进行调整,现在需要构建一个包。这并不难,但可能有点棘手,因为有关使用Rcpp构建软件包的信息范围从您想要的任何R软件包的详尽彻底的文档(但是作为新手高于您的头脑),以及新手敏感介绍(可能会遗漏你碰巧需要的细节)。
在这里,我使用oneCpp.cpp
和twoCpp.cpp
作为您将在包中使用的两个.cpp文件的名称。
以下是我的建议:
一个。首先,我假设您有一个theCppFile.cpp
版本,可以使用sourceCpp()进行编译,并按预期工作。这不是必须的,但是如果您不熟悉Rcpp OR软件包,那么在转移到下面更复杂的情况之前,确保您的代码在这种简单的情况下工作是很好的。
B中。现在使用Rcpp.package.skeleton()
构建您的包,或者使用RStudio中的Project&gt; Create Project&gt; Package w / Rcpp向导(强烈推荐)。您可以在[hadley / devtools] [1]或[Rcpp Attributes Vignette] [2]中找到有关使用Rcpp.package.skeleton()的详细信息。使用Rcpp编写软件包的完整文档在[编写一个使用Rcpp的软件包] [3],但是这个假设您已经很好地了解了C ++,并且不使用新的“属性”方式来执行Rcpp。如果你转向制作更复杂的包装,那将是非常宝贵的。
您现在应该拥有包的目录结构,如下所示:
yourPackageName
- DESCRIPTION
- NAMESPACE
- \R\
- RcppExports.R
- Read-and-delete-me
- \man\
- yourPackageName-package.Rd
- \src\
- Makevars
- Makevars.win
- oneCpp.cpp
- twoCpp.cpp
- RcppExports.cpp
设置好所有内容后,如果使用RStudio,请执行“Build&amp; Reload”;如果不在RStudio中,请执行compileAttributes()
。
℃。您现在应该在\ R目录中看到一个名为RcppExports.R
的文件。打开它并检查出来。在RcppExports.R
中,您应该看到.cpp
目录中所有\src
个文件的R包装函数。很甜蜜,嗯?。
D)尝试与您在theCppFile.cpp
中编写的功能相对应的R功能。它有用吗?如果是这样的话继续前进。
E)您现在可以在创建.cpp
目录时将新otherCpp.cpp
文件添加到\src
目录中。然后你只需要重建包,然后生成R包装并将其添加到RcppExports.R
。在RStudio中,这只是Build菜单中的“Build&amp; Reload”。如果您不使用RStudio,则应运行compileAttributes()
答案 1 :(得分:4)
简而言之,诀窍是从包的根目录中调用compileAttributes()
。例如,对于包foo
$ cd /path/to/foo
$ ls
DESCRIPTION man NAMESPACE R src
$ R
R> compileAttributes()
此命令将生成缺少的RcppExports.cpp
和RcppExports.R
。
答案 2 :(得分:2)
你错过了树林。
sourceCpp()
是最近的功能;它是我们称之为“Rcpp属性”的一部分,它有自己的小插图(在包中,在我的网站上和CRAN上具有相同的标题),您可能想要阅读它。除其他外,详细说明了如何将使用sourceCpp()
编译和运行的内容转换为包。这就是你想要的。
在文档之间随机跳转对您没有帮助,在包装作者的真正源文档的最后可能更好。或者对它进行不同的旋转:您使用的是新功能,但旧的文档却没有反映出来。尝试用Rcpp编写一个基本包,也就是从另一端来到它。
最后,有一个邮件列表......