Rcpp学习笔记之Hello World!

在使用R语言多年以后,我终于开始去学习Rcpp,利用C++来提高运行速度。其实当你能熟练的使用一门语言后,再去学一门新的语言,并没有想象中的那么难,更何况Rcpp把很多脏活累活都给包办了,在里面调用C++还是挺方便。

学习Rcpp的最重要一步是,运行一个”hello world!” 。如果能够运行”hello world!”就表明搞定了环境配置,后面就可以愉快的写代码了。

安装Rcpp的方式为,install.packages("Rcpp"), 安装过程中可能会出现一些问题,对于不同的操作系统需要做不同的准备工作,

  • Windows: 安装Rtools
  • Mac: 安装Xcode,需要在App store下载
  • Linux: 需要有GCC的编译环境

之后就让我们写人生中第一个C++函数, hello,

1
2
3
4
int hello(){
std::cout << "Hello, World!";
return 0;
}

那么问题来了,这个函数应该如何才能让R语言调用呢?最简单的方式就是Rcpp的cppFunction

1
2
3
4
5
6
7
8
library("Rcpp")
cppFunction('
int hello(){
std::cout << "Hello, World!";
return 0;
}
')
hello()

上面语句中,cppFunction中的''中的内容是C++语句。在这条语句中,我们以int hello(){}定义了一个hello函数,这个函数不接受参数,返回一个整型。在函数里面一共有两条语句,每条语句都以;结尾。

第一条是调用了C++的标准库的cout, std::cout, 和R中以包名::函数名调用函数的方法类似。第二条则是return 0,返回结果。

除了利用cppFunction外,另外一种更常用的方法就是将代码放在其他文件中,然后用sourceCpp的方式读取。我们新建一个hello.cpp的文件,里面的内容如下(如果用Rstudio新建C++ 文件,它会提供一个模版用于修改)

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <Rcpp.h>
using namespace Rcpp;
using namespace std;

//[[Rcpp::export]]
int hello(){
cout << "Hello, World!";
return 0;
}

/*** R
hello()
*/

之后在R里面加载并调用,和之前的结果一样。

1
2
3
4
library(Rcpp)

sourceCpp("hello.cpp")
hello()

解释下C++的代码。第一行是用#include <Rcpp.h>语句导入了Rcpp的头文件,类似于R里面的install.package()用于安装R包,然后用using namespace xxx; 的方式加载了两个库,Rcpp和std, 这就类似于R里面的library()函数。

C++里面用///*** 注释语句 */进行代码注释。前者是注释单行,类似于R里面的#注释,后者是注释多行。只不过//[Rcpp::export]]这条注释有特殊的含义,在sourceCpp读取代码解析的过程中,被这条语句注释的函数能够在R里面调用。换句话说,如果你删了这句话,那么这个hello函数在R里面就是无法直接调用的。而/*** R */里面可以放R代码,会c++代码编译结束后运行,常用于代码测试。

假如我们能够成功运行上面的代码,那么接下来要做的事情就是学习C++的基本语法(参考给R使用者的C++最少必要知识),学习Rcpp的数据结构。