我最近从亚马逊下载了 2013 Rcpp 书,以学习如何更好地在我的 R 代码中使用 C++,并且我正在尝试使用第一个斐波那契递归函数和包装器的第一个编译示例,看看我是否可以做到。我使用的是带有最新 R 的 Ubuntu。
首先是我的 C++:
/* Cpp based recurive function */
int fibonacci(const int x){
if(x == 0) return(0);
if(x == 1) return(1);
return(fibonacci(x - 1) + fibonacci(x - 2));
}
/* Wrapper */
extern "C" SEXP fibWrapper(SEXP xs) {
int x = Rcpp::as<int>(xs);
int fib = fibonacci(x);
return(Rcpp::wrap(fib));
}
然后我启动 sh 并输入:
PKG_CXXFLAGS=`Rscript -e 'Rcpp:::CxxFlags()'`
PKG_LIBS=`Rscript -e 'Rcpp:::LdFlags()'`
R CMD SHLIB Fibonacci.cpp
但我明白:
g++ -I/usr/share/R/include -DNDEBUG -fpic -O3 -pipe -g -c Fibonacci.cpp -o Fibonacci.o
Fibbonacci.cpp:10:12: error: 'SEXP' does not name a type
make: *** [Fibonacci.o] Error 1
我想也许我的 C++ 代码中需要包含指令,所以我再次执行此操作,但这次在 C++ 文件顶部使用
#include<Rcpp.h>
,并再次在 sh 中执行相同的命令,但仍然没有喜悦:
g++ -I/usr/share/R/include -DNDEBUG -fpic -O3 -pipe -g -c Fibonacci.cpp -o Fibonacci.o
Fibonacci.cpp:1:18: fatal error: Rcpp.h: No such file or directory
compilation terminated.
make: *** [Fibbonacci.o] Error 1
我做错了什么? 如果我查询我在 sh:
中设置的值$PKG_CXXFLAGS
sh: 9: -I/local/yrq12edu/R/x86_64-pc-linux-gnu-library/3.0/Rcpp/include: not found
$PKG_LIBS
sh: 10: -L/local/yrq12edu/R/x86_64-pc-linux-gnu-library/3.0/Rcpp/lib: not found
但我认为未找到的消息只是因为 -L 标志,因为如果我 cd 到目录,文件就在那里。
你似乎忽略了一个重要的细节。当你这样做时
PKG_CXXFLAGS=`Rscript -e 'Rcpp:::CxxFlags()'`
PKG_LIBS=`Rscript -e 'Rcpp:::LdFlags()'`
R CMD SHLIB Fibonacci.cpp
前两个结果应该被赋值并导出到 shell。你在这里所做的就是“分配并忘记”。
您从清单 2.1 中错过了这一点(或者可能是电子书删除了它——我没有电子书)是非常重要尾随反斜杠,它使所有内容都成为一行:
PKG_CXXFLAGS=`Rscript -e 'Rcpp:::CxxFlags()'` \
PKG_LIBS=`Rscript -e 'Rcpp:::LdFlags()'` \
R CMD SHLIB Fibonacci.cpp
现在,赋值发生在与 R(shell 脚本本身)调用相同的执行中,它具有值,并将它们传递到对 g++ 的调用中。
您可以通过接下来的两行看出我完全引用了包含所有必需的 -I 和 -L 部分的结果命令。因此(编译和链接步骤)都会跨越多行。
所以这本书是正确的,如果按照所示的方式完成,所有这些都会起作用。 内联(在本章后面讨论)和属性(也在同一章后面讨论)基本上都为您进行
PKG_CXXFLAGS
和 PKG_LIBS
分配。
编辑:另外,你的测试是错误的。你的意思可能是这样的
$ PKG_CXXFLAGS=`Rscript -e 'Rcpp:::CxxFlags()'`
$ echo $PKG_CXXFLAGS
-I/usr/local/lib/R/site-library/Rcpp/include
$
您不能只是“调用”shell 变量,因此会得到“未找到”答案。
编辑 2:无论如何,您尝试的示例实际上只是为了激发第 2.4 节中的其余讨论,该讨论详细说明了这是多么费力、容易出错……——导致第 2.5 节和第 2.6 节关于内联和属性。 两者都好得多;使用那些。
r-base-dev
软件包。
关于代码,你不需要包装器。您可以将其放入
.cpp
文件中:
#include <Rcpp.h>
using namespace Rcpp ;
// [[Rcpp::export]]
int fibonacci(const int x){
if(x == 0) return(0);
if(x == 1) return(1);
return(fibonacci(x - 1) + fibonacci(x - 2));
}
并且只是
sourceCpp
这个文件:
> sourceCpp( "fib.cpp" )
> fibonacci(6)
[1] 8