我有一个名为coolStuff.h
的头文件,其中包含我想在cpp源文件中使用的函数awesomeSauce(arg1)
。
目录结构:
守则:
#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
我已经移动了整个地方的文件和目录,似乎无法让它工作。我看到使用第三方标题的例子就是这样说的:
#include <boost/array.hpp>
(来自Hadley / devtools)
https://github.com/hadley/devtools/wiki/Rcpp
那是什么给出的?我整个上午一直在寻找,并且找不到像我这样简单事情的答案。
好了,现在我已经想出如何在Rstudio中构建使用Rcpp的软件包,让我重新解释一下这个问题。我有一个独立的头文件coolStuff.h,它包含我想在我的cpp代码中使用的函数。
1)我应该在包目录结构中放置coolStuff.h,以便它包含的函数可以由theCppFile.cpp使用吗?
2)如何在cpp文件中调用coolStuff.h?再次感谢你的帮助。我从上次谈话中学到了很多东西。
注意:我读了小插图&#34;编写一个使用Rcpp&#34;它没有解释如何做到这一点。
好的,让我总结一下我的问题的答案,因为它分散在这个页面上。如果我得到一个错误的细节,请随时编辑或告诉我,我将对其进行编辑:
因此,您找到了一个.h
或.cpp
文件,其中包含您要编写的.cpp
文件中要使用的函数或其他一些代码,以便与{{1}一起使用}}。
让我们继续调用此找到的代码Rcpp
并调用您要使用的函数coolStuff.h
。让我们调用您正在编写的文件awesomeSauce()
。
(我应该注意,.h文件和.cpp文件中的代码都是C ++代码,它们之间的区别在于C ++程序员以正确的方式保持组织。我将讨论差异在这里,但在SO上的简单搜索会引导你讨论差异。对于你需要使用你发现的代码的R程序员,没有真正的区别。)
简称:您可以使用theCppFile.cpp
这样的文件,前提是它不会调用其他库,只需剪切并粘贴到coolStuff.h
,或者创建一个包可以将文件放在带有theCppFile.cpp
文件的\src
目录中,并使用您正在编写的文件顶部的theCppFile.cpp
。后者更灵活,允许您在其他#include "coolStuff.h"
文件中使用coolStuff.h
中的函数。
详情:
1).cpp
不得调用其他库。这意味着它不能在顶部包含任何include语句。如果是这样,我在下面详述的内容可能无法正常工作,并且使用调用其他库的已找到代码超出了此答案的范围。
2)如果您想使用coolStuff.h
编译文件,则需要将sourceCpp()
剪切并粘贴到coolStuff.h
。我被告知存在异常,但theCppFile.cpp
旨在编译一个sourceCpp()
文件,因此这是最佳路径。
(注意:我不保证简单的剪切和粘贴可以开箱即用。您可能必须重命名变量,或者更有可能切换所使用的数据类型与您在{{{ 1}}。但到目前为止,使用6种不同的简单.cpp
文件,剪切和粘贴对我来说很简单。
3)如果您只需要使用theCppFile.cpp
中.h
的代码而不是其他地方的代码,那么您应该将其剪切并粘贴到coolStuff.h
。
(我再也不保证看到上面关于剪切和粘贴的说明)
4)如果要使用theCppFile.cpp
和其他theCppFile.cpp
文件中coolStuff.h
中包含的代码,则需要研究构建包。这并不难,但可能有点棘手,因为有关使用Rcpp构建软件包的信息范围从您想要的任何R软件包的详尽彻底的文档(但是作为新手高于您的头脑),以及新手敏感介绍(可能会遗漏一些你正好需要的)。
以下是我的建议:
A)首先获取theCppFile.cpp
的版本,其中.cpp
代码剪切并粘贴到theCppFile.cpp
,并使用coolStuff.h
进行编译,并按预期工作。这不是必须的,但是如果您不熟悉Rcpp OR软件包,那么在转移到下面更复杂的情况之前,确保您的代码在这种简单的情况下工作是很好的。
B)现在使用theCppFile.cpp
构建您的包或使用RStudio中的Build功能(强烈推荐)。您可以在hadley/devtools或Rcpp Attributes Vignette中找到有关使用sourceCpp()
的详细信息。使用Rcpp编写软件包的完整文档在Writing a package that uses Rcpp中,但是这个假设您已经很好地了解了C ++,并且没有使用新的&#34;属性&#34;做Rcpp的方式。
别忘了&#34; Build&amp;刷新&#34;如果您不在RStudio中使用RStudio或Rcpp.package.skeleton()
C)现在您应该在\ R目录中看到一个名为Rcpp.package.skeleton()
的文件。打开它并检查出来。在compileAttributes()
中,您应该看到RcppExports.R
目录中所有.cpp文件的R包装函数。很甜蜜。
D)尝试与您在RcppExports.R
中编写的功能相对应的R功能。它有用吗?如果是这样的话。
E)建立您的软件包后,您可以\src
将theCppFile.cpp
移动到coolStuff.h
文件夹中。
F)现在你可以从src
和theCppFile.cpp
的顶部(以及你想使用coolStuff.h中的代码的任何其他.cpp文件)中删除剪切和粘贴代码。在theCppFile.cpp
之后theCppFile.cpp
。请注意,ranker.h周围没有括号,而是有#34;&#34;。当包含用户提供的本地文件而不是像Rcpp或STL等库文件时,这是一个C ++约定...
G)现在你必须重建包。在RStudio,这只是&#34; Build&amp;刷新&#34;在“生成”菜单中。如果您不使用RStudio,则应运行#include "coolStuff.h"
H)现在再次尝试R功能,就像在步骤D)中那样,希望它能正常工作。
答案 0 :(得分:20)
问题是sourceCpp
明确设计为仅构建一个独立的源文件。如果您希望sourceCpp
具有依赖关系,那么它们必须是:
在系统包含目录(即/usr/local/lib
或/usr/lib
);或
在您在Rcpp::depends
属性
正如Dirk所说,如果你想构建多个源文件,那么你应该考虑使用R包而不是sourceCpp
。
请注意,如果您正在处理包并在包的src目录中的文件上执行sourceCpp,它将构建它就像它在包中一样(即,您可以包含来自src目录或inst / include目录)。
答案 1 :(得分: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 ++编译并链接flags。通常可以使用pkg-config:
获取此信息pkg-config --cflags --libs mylib
为了更好地理解,我建议使用带有详细输出的sourceCpp来打印g ++编译和链接命令:
sourceCpp("mysource.cpp", verbose=TRUE, rebuild=TRUE)
答案 2 :(得分:4)
在调用sourceCpp
之前,我能够使用R中的以下全局命令链接一个boost库Sys.setenv("PKG_CXXFLAGS"="-I \path-to-boost\")
基本上镜像这篇文章,但使用不同的编译器选项:http://gallery.rcpp.org/articles/first-steps-with-C++11/
答案 3 :(得分:2)
一些事情:
在您的主题中使用“第三方标题库”毫无意义。
第三方标题可以通过模板化代码工作,其中只需要标题,即只有一个包含步骤,编译器会解决问题。
一旦你需要库和目标代码的实际链接,除非你通过插件(或env.vars)给它提供元信息,否则你可能无法使用强大且有用的sourceCpp
。
因此,在这种情况下,请写一个包。
简单而简单的事情就是使用Rcpp和新属性,或旧的内联和cxxfunction
。更多用于复杂用途---外部库 更复杂,您需要查阅文档。为此我们为Rcpp添加了几个小插曲。
答案 4 :(得分:1)
尖括号&lt;&gt;用于系统包括,例如标准库。
对于您自己项目的本地文件,请使用引号:&#34;&#34;。
此外,如果您将标题放在不同的目录中,则应在包含它的源文件的本地指定标题路径。
因此,对于您的示例,这应该有效:
#include "../cppHeaders/coolStuff.h"
您可以配置搜索路径,以便可以在不执行此操作的情况下找到该文件,但对于您希望包含在多个项目中的内容,或者其他人希望有人能够这样做,通常只会这样做。 ;安装&#39;
答案 5 :(得分:1)
我们可以通过将路径写入PKG_CXXFLAGS
文件的.R/Makevars
变量中的标头来添加它,如下所示。以下是在macOS中添加与Anaconda一起安装的xtensor
头文件的示例。
⋊> ~ 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
答案 6 :(得分:0)
这在Windows中对我有用:
Sys.setenv("PKG_CXXFLAGS"='-I"C:/boost/boost_1_66_0"')
编辑:实际上,如果您使用Boost Headers(感谢Ralf Stubner),则不需要:
// [[Rcpp::depends(BH)]]