44

我有一个名为的头文件coolStuff.h,其中包含awesomeSauce(arg1)我想在我的 cpp 源文件中使用的函数。

目录结构:

  • 工作目录
    • 源Cpp
      • Cpp文件.cpp
    • cppHeaders
      • 酷东西

编码:

#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 的包”,它没有解释如何执行此操作。

答案:

好的,让我总结一下我的问题的答案,因为它分散在这个页面上。如果我有错误的细节,请随时编辑或让我知道,我会编辑它:

因此,您找到了一个.hor文件,其中包含要在您正在编写.cpp的文件中使用的函数或其他一些代码,以便与..cppRcpp

让我们继续调用这个找到的代码coolStuff.h并调用你想要使用的函数awesomeSauce()。让我们调用您正在编写的文件theCppFile.cpp

(在这里我应该注意,.h 文件和 .cpp 文件中的代码都是 C++ 代码,它们之间的区别在于 C++ 程序员可以让事情以正确的方式组织起来。我将在这里讨论不同之处,但是在这里对 SO 进行简单搜索将引导您讨论差异。对于需要使用您找到的一些代码的 R 程序员来说,没有真正的区别。)

简而言之:您可以使用coolStuff.h不调用其他库的文件,方法是剪切并粘贴到theCppFile.cpp中,或者如果您创建一个包,您可以将文件放在文件所在的\src目录中并在theCppFile.cpp文件#include "coolStuff.h"顶部使用你在写。后者更灵活,允许您coolStuff.h在其他.cpp文件中使用函数。

细节:

1)coolStuff.h不得调用其他库。所以这意味着它不能在顶部有任何包含语句。如果是这样,我在下面详述的内容可能不起作用,并且使用调用其他库的找到的代码超出了此答案的范围。

2)如果要编译文件,sourceCpp()需要剪切并粘贴coolStuff.htheCppFile.cpp. 我被告知有例外,但sourceCpp()旨在编译一个.cpp文件,所以这是最好的途径。

(注意:我不保证简单的剪切和粘贴可以开箱即用。您可能必须重命名变量,或者更有可能将正在使用的数据类型切换为与您在 中使用的一致theCppFile.cpp。但到目前为止,使用 6 个不同的简单.h文件,剪切和粘贴对我来说非常简单)

3) 如果您只需要使用coolStuff.hintheCppFile.cpp而没有其他地方的代码,那么您应该将其剪切并粘贴到theCppFile.cpp.

(我再次不保证请参阅上面关于剪切和粘贴的说明)

4) 如果你想使用AND 其他文件中包含coolStuff.h的代码,你需要考虑构建一个包。这并不难,但可能有点棘手,因为那里有关使用 Rcpp 构建包的信息范围从您想要的任何 R 包的详尽彻底的文档(但对于新手来说,这超出了您的头顶),以及新手敏感介绍(可能会遗漏碰巧需要的细节)。theCppFile.cpp.cpp

这是我的建议:

A)首先从剪切和粘贴theCppFile.cpp代码中获得一个版本,该版本可以编译并按您期望的方式工作。这不是必须的,但如果您是 Rcpp OR 包的新手,最好确保您的代码在这种简单情况下工作,然后再转到下面更复杂的情况。coolStuff.htheCppFile.cppsourceCpp()

B) 现在使用Rcpp.package.skeleton()或使用 RStudio 中的构建功能构建您的包(强烈推荐)。Rcpp.package.skeleton()您可以在hadley/devtoolsRcpp Attributes Vignette中找到有关使用的详细信息。使用 Rcpp 编写包的完整文档在编写使用 Rcpp 的包中,但是本文假设您对 C++ 的使用方式相当了解,并且不使用新的“属性”方式来执行 Rcpp。

compileAttributes()如果使用 RStudio 或者您不在 RStudio 中,请不要忘记“构建和重新加载” 。

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

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

coolStuff.hE)构建好包后,您可以src使用theCppFile.cpp.

F) 现在您可以从theCppFile.cpp. 请注意,ranker.h 周围没有括号,而是有“”。当包含用户提供的本地文件而不是 Rcpp 或 STL 等库文件时,这是 C++ 约定...theCppFile.cpp#include "coolStuff.h"#include <Rcpp.h>

G) 现在你必须重建包。在 RStudio 中,这只是 Build 菜单中的“Build & Reload”。如果您不使用 RStudio,您应该运行compileAttributes()

H) 现在再次尝试 R 函数,就像在步骤 D) 中所做的那样,希望它可以工作。

4

7 回答 7

22

问题是它sourceCpp被明确设计为只构建一个独立的源文件。如果您想sourceCpp拥有依赖项,那么它们需要是:

  1. 在系统中包含目录(即/usr/local/lib/usr/lib);或者

  2. Rcpp::depends在您在属性中列出的 R 包中

正如 Dirk 所说,如果您想构建多个源文件,那么您应该考虑使用 R 包而不是sourceCpp.

请注意,如果您正在处理一个包并对包的 src 目录中的文件执行 sourceCpp ,它将在包中一样构建它(即您可以包含来自 src 目录或 inst/include 目录的文件)。

于 2012-12-21T19:34:05.393 回答
7

我可以通过在调用 sourceCpp 之前设置两个环境变量来链接任何库(在这种情况下为 MPFR):

Sys.setenv("PKG_CXXFLAGS"="-I/usr/include")
Sys.setenv("PKG_LIBS"="-L/usr/lib/x86_64-linux-gnu/ -lm -lmpc -lgmp -lmpfr")

第一个变量包含库头的路径。第二个包括库二进制文件的路径及其文件名。在这种情况下,还需要其他依赖库。有关更多详细信息,请检查 g++ 编译和链接标志。这些信息通常可以使用 pkg-config 获得:

pkg-config --cflags --libs mylib

为了更好地理解,我建议使用带有详细输出的 sourceCpp 来打印 g++ 编译和链接命令:

sourceCpp("mysource.cpp", verbose=TRUE, rebuild=TRUE)
于 2016-04-01T11:15:51.607 回答
4

在调用 sourceCpp 之前,我能够在 R 中使用以下全局命令链接 boost 库

Sys.setenv("PKG_CXXFLAGS"="-I \path-to-boost\")

基本上反映了这篇文章,但使用了不同的编译器选项: http: //gallery.rcpp.org/articles/first-steps-with-C++11/

于 2013-08-15T20:25:56.020 回答
2

几件事:

  1. 您的主题中的“第三方头库”毫无意义。

  2. 第三方标头可以通过模板代码工作,其中标头就是您所需要的,即只有一个包含步骤,编译器会解决问题。

  3. sourceCpp一旦您需要库和目标代码的实际链接,除非您通过插件(或环境变量)为其提供元信息,否则您可能无法获得强大和有用的功能。

  4. 所以在这种情况下,写一个包。

简单的事情就是使用 Rcpp 和新属性,或者旧的内联和cxxfunction. 更复杂的使用 --- 而外部库复杂,您需要查阅文档。为此,我们在 Rcpp 中添加了几个小插曲。

于 2012-12-21T19:29:22.653 回答
1

尖括号 <> 用于系统包含,例如标准库。

对于您自己项目的本地文件,请使用引号:“”。

此外,如果您将头文件放在不同的目录中,则头文件路径应指定为包含它的源文件的本地路径。

因此,对于您的示例,这应该有效:

#include "../cppHeaders/coolStuff.h"

您可以配置搜索路径,这样就可以在不这样做的情况下找到文件,但通常只对您想要包含在多个项目中的东西这样做是值得的,否则会期望有人“安装”。

于 2012-12-21T18:36:44.627 回答
1

我们可以通过将路径写入文件PKG_CXXFLAGS变量中的标头来添加它,.R/Makevars如下所示。以下是xtensor在 macOS 中添加随 Anaconda 一起安装的头文件的示例。

⋊&gt; ~ cat ~/.R/Makevars                                                                                                                              
CC=/usr/local/bin/gcc-7
CXX=/usr/local/bin/g++-7
CPLUS_INCLUDE_PATH=/opt/local/include:$CPLUS_INCLUDE_PATH
PKG_CXXFLAGS=-I/Users/kuroyanagi/.pyenv/versions/miniconda3-4.3.30/include
LD_LIBRARY_PATH=/opt/local/lib:$LD_LIBRARY_PATH
CXXFLAGS= -g0 -O3 -Wall
MAKE=make -j4
于 2018-02-01T04:17:58.000 回答
0

这在 Windows 中对我有用:

Sys.setenv("PKG_CXXFLAGS"='-I"C:/boost/boost_1_66_0"')

编辑:实际上,如果您使用 Boost Headers,则不需要这个(感谢 Ralf Stubner):

// [[Rcpp::depends(BH)]]

于 2018-09-14T00:47:24.720 回答