【发布时间】:2012-12-21 18:23:01
【问题描述】:
我有一个名为 coolStuff.h 的头文件,其中包含我想在我的 cpp 源文件中使用的函数 awesomeSauce(arg1)。
目录结构:
- Rworking 目录
- sourceCpp
- CppFile.cpp
- cppHeaders
- coolStuff.h
- sourceCpp
代码:
#include <Rcpp.h>
#include <cppHeaders/coolStuff.h>
using namespace Rcpp;
// [[Rcpp::export]]
double someFunctionCpp(double someInput){
double someOutput = awesomeSauce(someInput);
return someOutput;
}
我得到错误:
theCppFile.cpp:2:31: error: cppHeaders/coolStuff.h: No such file or directory
我已将文件和目录移动到各处,但似乎无法正常工作。我看到到处都是使用 3rd 方标头的示例,这些示例说只需这样做:
#include <boost/array.hpp>
(来自 Hadley/devtools)
https://github.com/hadley/devtools/wiki/Rcpp
那是什么?我整个上午都在搜索,但找不到对我来说似乎很简单的事情的答案。
更新 01.11.12
好的,现在我已经弄清楚了如何在 Rstudio 中构建使用 Rcpp 的包,让我重新表述一下这个问题。我有一个独立的头文件coolStuff.h,其中包含我想在我的cpp 代码中使用的函数。
1) 我应该将coolStuff.h 放在包目录结构的什么位置,以便CppFile.cpp 可以使用它包含的功能?
2) 如何在 cpp 文件中调用coolStuff.h?再次感谢您的帮助。我从上次的谈话中学到了很多。
注意:我阅读了小插图“编写使用 Rcpp 的包”,但没有说明如何执行此操作。
答案:
好吧,让我总结一下我的问题的答案,因为它分散在这个页面上。如果我有错误的细节,请随时编辑或让我知道,我会编辑它:
因此,您找到了一个 .h 或 .cpp 文件,其中包含您要在您正在编写的与 Rcpp 一起使用的 .cpp 文件中使用的函数或其他一些代码。
让我们继续调用这个找到的代码coolStuff.h 并调用你想使用的函数awesomeSauce()。让我们调用你正在编写的文件theCppFile.cpp。
(在这里我应该注意,.h 文件和 .cpp 文件中的代码都是 C++ 代码,它们之间的区别在于 C++ 程序员可以让事情以正确的方式组织起来。我将讨论区别在这里,但是在 SO 上的简单搜索将引导您讨论区别。对于需要使用您找到的一些 o' 代码的 R 程序员来说,没有真正的区别。)
简而言之:您可以使用像 coolStuff.h 这样的文件,前提是它不调用其他库,方法是剪切并粘贴到 theCppFile.cpp,或者如果您创建一个可以放置的包\src 目录中的文件与theCppFile.cpp 文件并在您正在编写的文件的顶部使用#include "coolStuff.h"。后者更灵活,允许您在其他.cpp 文件中使用coolStuff.h 中的函数。
详情:
1) coolStuff.h 不得调用其他库。所以这意味着它不能在顶部有任何包含语句。如果是这样,我在下面详述的内容可能不起作用,并且使用调用其他库的找到的代码超出了此答案的范围。
2) 如果要编译带有sourceCpp() 的文件,则需要将coolStuff.h 剪切并粘贴到theCppFile.cpp 中。有人告诉我有例外,但sourceCpp() 旨在编译一个.cpp 文件,所以这是最好的方法。
(注意:我不保证简单的剪切和粘贴可以开箱即用。您可能需要重命名变量,或者更有可能切换正在使用的数据类型以与您在 @987654351 中使用的数据类型保持一致@. 但是到目前为止,剪切和粘贴对我来说已经很简单了,有 6 个不同的简单 .h 文件)
3) 如果您只需要在theCppFile.cpp 中使用来自coolStuff.h 的代码而不需要其他任何地方,那么您应该将其剪切并粘贴到theCppFile.cpp 中。
(我再次不保证请参阅上面关于剪切和粘贴的说明)
4) 如果您想在theCppFile.cpp 和其他.cpp 文件中使用包含在coolStuff.h 中的代码,您需要考虑构建一个包。这并不难,但可能有点棘手,因为那里有关使用 Rcpp 构建包的信息范围从您想要的任何 R 包的详尽彻底的文档(但对于新手来说,这超出了您的头顶),以及新手敏感介绍(可能会遗漏您碰巧需要的细节)。
这是我的建议:
A) 首先获取theCppFile.cpp 的版本,将coolStuff.h 中的代码剪切并粘贴到theCppFile.cpp 中,该版本与sourceCpp() 一起编译并按照您的预期工作。这不是必须的,但如果您是 Rcpp OR 包的新手,最好确保您的代码在这种简单的情况下工作,然后再转到下面更复杂的情况。
B) 现在使用 Rcpp.package.skeleton() 构建您的包或使用 RStudio 中的构建功能(强烈推荐)。您可以在hadley/devtools 或Rcpp Attributes Vignette 中找到有关使用Rcpp.package.skeleton() 的详细信息。使用 Rcpp 编写包的完整文档在 Writing a package that uses Rcpp 中,但是这个文档假设您对 C++ 的使用非常了解,并且不使用新的“属性”方式来执行 Rcpp。
如果使用 RStudio,请不要忘记“构建和重新加载”,如果您不在 RStudio 中,请不要忘记 compileAttributes()。
C) 现在您应该在 \R 目录中看到一个名为 RcppExports.R 的文件。打开它并检查一下。在RcppExports.R 中,您应该看到\src 目录中所有.cpp 文件的R 包装函数。很甜。
D) 尝试与您在theCppFile.cpp 中编写的函数相对应的 R 函数。它有效吗?如果是这样继续。
E) 构建好包后,您可以将 coolStuff.h 移动到带有 theCppFile.cpp 的 src 文件夹中。
F) 现在您可以从theCppFile.cpp 和theCppFile.cpp(以及您想使用coolStuff.h 代码的任何其他.cpp 文件)顶部删除剪切和粘贴代码,只需将#include "coolStuff.h"在#include <Rcpp.h> 之后。请注意,ranker.h 周围没有括号,而是有“”。这是包含用户提供的本地文件而不是 Rcpp 或 STL 等库文件时的 C++ 约定...
G) 现在你必须重建包。在 RStudio 中,这只是 Build 菜单中的“Build & Reload”。如果你没有使用 RStudio,你应该运行 compileAttributes()
H) 现在再次尝试 R 函数,就像在步骤 D) 中所做的那样,希望它可以工作。
【问题讨论】:
-
#include "../cppHeaders/coolStuff.h" -
没有骰子:我试过了:
#include "../cppHeaders/coolStuff.h"#include <"../cppHeaders/coolStuff.h">#include <../cppHeaders/coolStuff.h>仍然:: No such file or directory -
如果你的结构和描述的一样,它应该可以工作。名称或包含路径中是否有拼写错误?您的文件系统是否区分大小写并且您弄错了大小写?
-
在一个包中,您需要提供一个 Makevars 来将目录添加到编译中,例如PKG_CPPFLAGS += -I../inst/include/
-
很好的答案 - 感谢您提供详细信息。在相关的文章中,我发现 Hadley 的 reference 在编写包以在细节和可读性之间取得良好的平衡。特别是,它以非常友好的方式讨论了在包中使用 Rcpp。