14

我目前有一个.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关于 Cpp 的优秀入门书中,他在“在包中使用 Rcpp”一节中说:

如果您的包使用 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() 编译的代码然后在包中使用它时我还需要做什么?

我应该注意到我已阅读:“编写使用 Rcpp 的包” http://cran.rstudio.com/web/packages/Rcpp/vignettes/Rcpp-package.pdf并了解那里提供的基本结构。但是,在查看RcppExamples源代码后,似乎小插图中的结构与示例包中使用的结构并不完全相同。例如,没有使用 .h 文件。此外,小插图和源代码都没有使用 [[Rcpp::export]] 属性。这一切都让我很难准确追踪我的错误在哪里。

4

3 回答 3

10

这是我关于如何从使用 sourceCpp() 到使用 Rcpp 的包的“演练”。如果有错误,请随时编辑或让我知道,我会编辑它。

[注意:我强烈建议在此过程中使用 RStudio。]

所以你有 sourceCpp() 的东西,现在你需要构建一个包。这并不难,但可能有点棘手,因为那里有关使用 Rcpp 构建包的信息范围从您想要的任何 R 包的详尽彻底的文档(但对于新手来说,这超出了您的头顶),以及新手敏感介绍(可能会遗漏您碰巧需要的细节)。

在这里,我使用oneCpp.cpptwoCpp.cpp作为您将在包中使用的两个 .cpp 文件的名称。

这是我的建议:

A. 首先,我假设您有一个theCppFile.cpp使用 sourceCpp() 编译的版本,并且可以按照您的预期工作。这不是必须的,但如果您是 Rcpp OR 包的新手,最好确保您的代码在这种简单的情况下工作,然后再转到下面更复杂的情况。

B. 现在使用Rcpp.package.skeleton()或使用 RStudio 中的 Project>Create Project>Package w/Rcpp 向导构建您的包(强烈推荐)。Rcpp.package.skeleton()您可以在hadley/devtoolsRcpp Attributes Vignette中找到有关使用的详细信息。使用 Rcpp 编写包的完整文档在编写使用 Rcpp 的包中,但是本文假设您非常了解 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,或者compileAttributes()您不在 RStudio 中,请执行“构建和重新加载”。

C. 您现在应该在您的\R目录中看到一个名为RcppExports.R. 打开它并检查一下。您应该会看到目录中所有文件RcppExports.R的 R 包装函数。很甜,嗯?.cpp\src

D) 尝试与您在 中编写的函数相对应的 R 函数theCppFile.cpp。它有效吗?如果是这样继续。

E)您现在可以在创建目录时将新.cpp文件添加otherCpp.cpp\src目录中。然后你只需要重建包,R 包装器就会RcppExports.R为你生成和添加。在 RStudio 中,这只是 Build 菜单中的“Build & Reload”。如果您不使用 RStudio,您应该运行compileAttributes()

于 2013-01-13T22:05:49.540 回答
4

简而言之,诀窍是compileAttributes()从包的根目录中调用。所以例如对于包foo

$ cd /path/to/foo
$ ls
DESCRIPTION  man  NAMESPACE  R  src
$ R
R> compileAttributes()

此命令将生成缺少的RcppExports.cppRcppExports.R

于 2013-12-01T16:54:36.100 回答
3

你只见树木不见森林。

sourceCpp()是最近的函数;它是我们所谓的“Rcpp 属性”的一部分,它有自己的小插图(在包中、我的网站和 CRAN 上具有相同的标题),您可能想阅读它。除其他外,它详细说明了如何将您编译和运行的内容sourceCpp()转换为包。这就是你想要的。

在文档之间随机跳转对您没有帮助,并且包作者在真正源文档的末尾可能更可取。或者换个说法:您使用的是新功能,但旧文档没有反映它。试着用 Rcpp 写一个基本的包,也就是从另一端来。

最后,有一个邮件列表...

于 2013-01-12T01:32:14.323 回答