R语言轻巧简洁,便于开发新算法。但是R函数运行速度较慢, 在进行迭代计算或者跑蒙特卡罗马尔科夫链时,常常不能满足要求。 此外, 由于用C或者C++已经有很多算法库,人们希望能直接调用这些库中的函数。Rcpp正是为了让R开发者更方便地运用C++函数生的。 本文简要介绍如何编写一个含有C++函数的R程序包。
要在Windows下创建R程序包,首先要安装:
- R软件 http://cran.r-project.org/bin/windows/base/,
- Rtools http://cran.r-project.org/bin/windows/Rtools/,以及
- Miktex http://miktex.org,
然后,还需要安装 Rcpp (http://cran.r-project.org/web/packages/Rcpp/index.html )程序包。
并配置好启动 路径, 即将所需要的任何exe文件的路径, 拷贝到 电脑>属性>高级系统设置>高级>环境变量>系统变量>路径 中 如:
此外, 这里假设读者使用文本编辑器 Notepad++ 。
Rcpp程序包已经提供了多种C++的类模板, 可以让C++函数返回多种R对象。假设现有一个C++函数, 名叫Eccentricity,该函数用于计算某天体的轨道偏心率随时间的变化,输入参数为儒略日(日期的某种记录方法), 在正常的C++语法中, 该函数定义如下:
1 | double Eccentricity(double JD) |
现在我们需要有一个Rcpp形成的包骨架(package skeleton),假设名叫 skycalc。在R中运行如下命令生成基于Rcpp的R包骨架:
1 | library(Rcpp) |
skycalc保存在getwd()所示的文件夹下, 有 man、R、src三个文件夹以及DESCRIPTION、NAMESPACE 以及 Read-and-delete-me三个文本文件,这个三个文件没有任何扩展名。
- man文件夹保存的是所有R函数以及R程序包的帮助文件文件,遵循是Latex格式,需要逐项填写。
- R文件夹保存的是R函数的文件,每个R函数单独一个文件
- src文件夹放的是cpp文件, 即c++的源文件
默认的情况下,各文件夹下有以下示例文件:
- man文件夹中包含 rcpp_hello_world.Rd 文件,
- R文件夹中包含RcppExports.R文件
- src 文件夹中包含rcpp_hello_world.cpp 和 RcppExports.cpp 两个C++源文件
这些示例文件在本例中均可以删除。
我们的目标是:将Eccentricity函数,放在C++源代码中。假设函数保存在名为Eccentricity.cpp的纯文本文件, 为了能够在R中直接调用该函数, 需要将其参数数据类型以及返回值的数据类型更改为R能够识别的格式。因为R只能识别一种称为SEXP的数据类型, 所以这里做如下更改:
1 | RcppExport SEXP Eccentricity(SEXP JD) |
在类型前,更加上RcppExport,返回值return里面,先套用wrap函数,以便返回为R能识别的SEXP数据类型。
为在Eccentricity.cpp文件中加上引用的头文件:
1 |
|
此时, Eccentricity.cpp文件内容如下:
1 | ///////////////cpp文件开始////////////////////// |
这样 Eccentricity.cpp 文件就准备好了,将其保存在src文件夹中。
为了能够在R中调用编译后的C++函数,可使用R的.Call()函数调用dll库(cpp文件经过编译后, 在Windows中编译为dll文件)。但为了更为方便地使用这些函数,一般为编写一个与C++函数形式上类似的R函数,该R函数的名称和各参数最好能与C++函数对应。为此,我们可以写一个R函数EccentricityR, 该R函数可定义如下:
1 | EccentricityR <- function(JD) { |
其中JD为该R函数的参数, 直接通过.Call传递给DLL中的Eccentricity。
在Notepad++中,拷贝以上R函数, 并且另存为 EccentricityR.R 文件, 放在skycalc程序包下的R文件夹下。
为了生成该EccentricityR函数的帮助文件,需要将该函数粘贴到Rconsole中, 之后运行R命令 prompt(EccentricityR),所形成的EccentricityR.Rd 文件需要进一步根据参数的意义填写和编辑。之后放到man文件夹下。
编辑和填写DESCRIPTION以及NAMESPACE两个文本文件 (参考 http://blog.sciencenet.cn/blog-255662-247614.html )。删除 Read-and-delete-me文件。这样,程序包的源文件就做好了。
下面准备编译或安装R程序包的Window批处理文件,bat文件
R包的检查的bat文件
新建一个纯文本文件,并将扩展名txt更改为.bat,将以下内容拷贝到该文件夹中:
1 | Rcmd check skycalc |
将该文件命名为 check skycalc package.bat, 双击该bat文件, 可以对skycalc程序包中的错误进行检查。 如果要提交程序包到CRAN,检查过程中不能有任何错误或者warning。
建立Windows版本的安装包的bat文件
(2)新建一个纯文本文件,并将扩展名txt更改为.bat
将以下内容拷贝到该文件夹中
1 | Rcmd INSTALL --build skycalc |
将该文件命名为 build skycalc package Windows Binary.bat, 双击该文件, 可以建立Windows系统下的R程序包。
创建源代码包的bat文件
新建一个纯文本文件,并将扩展名txt更改为.bat,将以下内容拷贝到该文件夹中
1 | Rcmd build skycalc |
将该文件命名为 build skycalc package Linux Source Code.bat, 双击该文件,可以建立Linux系统下的安装包,其实是源文件。
直接安装程序包的bat文件
新建一个纯文本文件,并将扩展名txt更改为.bat,将以下内容拷贝到该文件夹中:
1 | Rcmd INSTALL skycalc |
将该文件命名为 install skycalc package.bat, 双击该文件, 可以安装skycalc到当前的R中。
运行批处理命令
将以上四个.bat文件, 放置到skycalc文件夹所在的文件夹(例如, skycalc所 在的文件夹为study, 则bat文件需要放置在study文件夹下)
双击文件, 即可完成程序包的编译和检查等。
注意: 如果使用的64bit的Windows,源代码 skycalc文件夹下, 每次都会生成 src-x64 和 src-i386两个文件夹, 在编译linux源代码的时候, 需要删除。