C++ 从sourceCpp移动到带有Rcpp的包

C++ 从sourceCpp移动到带有Rcpp的包,c++,r,rcpp,C++,R,Rcpp,我目前有一个.cpp文件,可以使用sourceCpp()进行编译。正如预期的那样,相应的R函数被创建,代码按预期工作 这是: #include <Rcpp.h> using namespace Rcpp; // [[Rcpp::export]] NumericVector exampleOne(NumericVector vectorOne, NumericVector vectorTwo){ NumericVector outputVector = vectorOne

我目前有一个
.cpp
文件,可以使用
sourceCpp()
进行编译。正如预期的那样,相应的R函数被创建,代码按预期工作

这是:

#include <Rcpp.h> 
using namespace Rcpp;

// [[Rcpp::export]]
NumericVector exampleOne(NumericVector vectorOne, NumericVector vectorTwo){

    NumericVector outputVector = vectorOne + vectorTwo; 

    return outputVector;
}
然后我(重新)构建了包,我得到了以下错误:

.Call(“exampleOne”、vectorOne、vectorwo、PACKAGE=“voteR”)中出现错误: C符号名称“exampleOne”不在包“testPackage”的DLL中

有人知道我在获取用sourceCpp()编译的代码并将其用于包中时还需要做什么吗?


我应该注意到,我已经阅读了“编写一个使用Rcpp的包”,并且理解了其中介绍的基本结构。但是,在查看了
RcppExamples
源代码之后,vignettes中的结构似乎与示例包中使用的结构不完全相同。例如,没有使用.h文件。另外,vignette和源代码都没有使用[[Rcpp::export]]属性。这一切都使得我很难准确地找到我的错误所在。

你是以假乱真

sourceCpp()
是一个新函数;这是我们称之为“Rcpp属性”的一部分,它有自己的小插曲(在软件包、我的网站和CRAN上都有相同的标题),您可能想阅读。它还详细介绍了如何将使用
sourceCpp()
编译和运行的内容转换为一个包。这就是你想要的

在文档之间随意跳转对您没有帮助,在真正的源代码文档结束时,最好由包作者编写。或者换一种说法:您使用的是一个新功能,但旧文档没有反映它。尝试用Rcpp编写一个基本包(也可以从另一端开始编写)

最后,还有一个邮件列表…

下面是我的“演练”,介绍如何从使用sourceCpp()过渡到使用Rcpp的包。如果有一个错误,请随时编辑此或让我知道,我会编辑它

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

因此,您已经了解了sourceCpp()的内容,现在需要构建一个包。这并不难,但可能有点棘手,因为关于使用Rcpp构建软件包的信息包括您想要的任何R软件包的详尽文档(但作为一个新手,这超出了您的想象),以及对新手敏感的介绍(可能会遗漏您碰巧需要的细节)

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

以下是我的建议:

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

B.现在使用
Rcpp.package.skeleton()
或使用RStudio中的Project>Create Project>package w/Rcpp向导构建包(强烈建议)。您可以在或中找到有关使用
Rcpp.package.skeleton()的详细信息。与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,请执行“构建并重新加载”,如果不在RStudio中,请执行
compileAttributes()

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

D) 尝试与您在cppfile.cpp中编写的函数相对应的R函数。它有用吗?如果是这样,那就继续吧


E) 现在,您只需在创建新的
.cpp
文件时将其添加到
\src
目录中,如
otherCpp.cpp
。然后,您只需重新构建包,就会生成R包装并为您添加到
RcppExports.R
。在RStudio中,这只是构建菜单中的“构建&重新加载”。如果不使用RStudio,则应运行
compileAttributes()

简而言之,技巧是从包的根目录中调用
compileAttributes()
。比如包
foo

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

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

如果正确使用
compileAttributes
,则无需自己创建R函数。但很大程度上取决于您如何创建包—RStudio和(开发版本的)devtools中的包开发工具将为您处理大部分细节。我的投票仍然是支持手工操作并理解所发生的事情—只需从
rcpp.package.skeleton()开始
它有一个与属性一起使用的选项。谢谢你们两位。正如Hadley所说,我在意识到RcppExports.R文件包含所有相应的R函数(多亏了)之后,转储了R文件的“我的”版本。现在错误消失了。通过尝试创建我自己版本的R文件,它不知怎么搞砸了(可能是共享库?)。我认为就我的目的而言,RStudio路径现在是最好的。在将“编写使用Rcpp的包”中的一般信息应用于代码时,从头开始构建会让我犯很多错误。那里的所有代码都使用了“pre-attribute”方法。也都
$ cd /path/to/foo
$ ls
DESCRIPTION  man  NAMESPACE  R  src
$ R
R> compileAttributes()