2012-12-26 81 views
0

假設我有一個C++代碼(參見下面的簡單示例)。 我想讓日記裁判輕鬆安裝/運行 它。如何(輕鬆地)將C++函數包裝成易於安裝的R'包'

所以我想最簡單的方法是扭曲的,給一個簡單的 [R包般的tar.gz文件,使裁判可以通過簡單地調用install.packages到本地.tar.gz文件安裝 。

這樣做的原因是,我不知道 裁判是用什麼機器,但我敢肯定裁判會 知道如何安裝的R程序包,以便它是 我扭曲我的代碼更容易作爲一個R'包' - 或者無論如何, 的東西足夠類似於它可以通過簡單調用install.package()安裝的 。

回答較早的question似乎表明這 確實是可能的。我跟着建議在其中和 創建/ src目錄與我的cpp代碼(所示的下面 )和含有一個Makevars.win文件:

## This assume that we can call Rscript to ask Rcpp about its locations 
## Use the R_HOME indirection to support installations of multiple R version 
#PKG_LIBS = $(shell $(R_HOME)/bin/Rscript.exe -e "Rcpp:::LdFlags()") 
PKG_CPPFLAGS = -I../inst/include -I. 
PKG_CXXFLAGS = -DEIGEN_DONT_PARALLELIZE $(SHLIB_OPENMP_CXXFLAGS) 
PKG_LIBS = $(shell $(R_HOME)/bin/Rscript.exe -e "Rcpp:::LdFlags()") $(SHLIB_OPENMP_CXXFLAGS) 

和含有Makevars文件:

## Use the R_HOME indirection to support installations of multiple R version 
#PKG_LIBS = `$(R_HOME)/bin/Rscript -e "Rcpp:::LdFlags()"` 
# This was created by RcppEigen.package.skeleton, but the R script that is 
# called creates error message: 
# PKG_CPPFLAGS = `$(R_HOME)/bin/Rscript -e "RcppEigen:::RcppEigenCxxFlags()"` 
PKG_CPPFLAGS = -I../inst/include 
PKG_CXXFLAGS = -DEIGEN_DONT_PARALLELIZE $(SHLIB_OPENMP_CXXFLAGS) 
PKG_LIBS = `$(R_HOME)/bin/Rscript -e "Rcpp:::LdFlags()"` $(SHLIB_OPENMP_CXXFLAGS) 

例如我只是遵循SO帖子中的答案來查看 這是如何在其他軟件包中完成的(我還將RcppEigen添加到依賴關係列表中,因爲 這保證了Eigen安裝在目標機器上)。我還創建含有包含該文件MSE.R一個/ R目錄:

fx01<-function(x){ 
    x<-as.matrix(x) 
    Dp<-rep(0,ncol(x)) 
    fit<-.C("mse",as.integer(nrow(x)),as.integer(ncol(x)),as.single(x),as.single(Dp)) 
    as.numeric(fit[[4]]) 
} 

和空/安裝/包括和一個含有最小(但有效的).Rd文件/ man目錄。 我已經添加含有NAMESPACE文件:

import(Rcpp) 
import(RcppEigen) 
useDynLib(MySmallExample) 

這裏是這樣的問題:

  • C++函數否則編譯/運行良好。有沒有辦法將它翹曲成R包,以便於第三方安裝/運行。

這裏是用於這個例子的C++代碼。

#include <algorithm> 
#include <cstdlib> 
#include <ctime> 
#include <functional> 
#include <fstream> 
#include <iostream> 
#include <math.h> 
#include <time.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <sstream> 
#include <vector> 

#include <Eigen/Dense> 
#include <Eigen/LU> 
#include <Eigen/SVD> 

using namespace std; 
using namespace Eigen; 
using Eigen::MatrixXf; 
using Eigen::VectorXf; 


float median(VectorXf& x) { 
    int n=x.rows(); 
    int half=(n+1)/2; 
    half--;     
    float med; 
    nth_element(x.data(),x.data()+half,x.data()+x.size()); 
    if((n%2)==1){ 
     med=x(half); 
    } else { 
     float tmp0=x(half); 
     float tmp1=x.segment(half+1,half-1).minCoeff(); 
     med=0.5*(tmp0+tmp1); 
    } 
    return med; 
} 
VectorXf fx01(MatrixXf& x){ 
    int p=x.cols(); 
    int n=x.rows(); 
    VectorXf Recept(n); 
    VectorXf Result(p); 
    for(int i=0;i<p;i++){ 
     Recept=x.col(i); 
     Result(i)=median(Recept); 
    } 
    return Result; 
} 
extern "C"{ 
    void mse(int* n,int* p,float* x,float* medsout){ 
     MatrixXf x_cen=Map<MatrixXf>(x,*n,*p); 
     VectorXf MedsOut=fx01(x_cen); 
     Map<VectorXf>(medsout,*p)=MedsOut.array(); 
    } 
} 

回答

2

有一個正確的描述文件是非常重要的。 我用這一個:

Package: MySmallExample 
Type: Package 
Title: MysmallExample 
Version: 0.0.0 
Date: 2012-12-24 
Depends: Rcpp (>= 0.9.10) 
Imports: RcppEigen (>= 0.2.0) 
Suggests: mvtnorm 
LinkingTo: Rcpp, RcppEigen 
Description: A small minimal Package. 
License: GPL (>= 2) 
LazyLoad: yes 
[email protected]: person("joe", "programer", email = 
     "[email protected]_inc.com", role = c("aut", "cre")) 
Collate: 'MSE.R' 
Packaged: 2012-12-24 12:34:56 UTC; andi 
Author: joe programer [aut, cre] 
Maintainer: joe programer <[email protected]_inc.com> 
Repository: CRAN 
Date/Publication: 2012-12-24 12:34:56 

最重要的似乎是「自動分頁:」字段:應適當列出 都在/ R目錄中的文件.R。取決於& Imports字段也應該與NAMESPACE文件一致。

這也是非常重要的文件命名空間包含線

export("fx01","fx02") 

其中「FX01」,「FX02」是在 /R/*.R文件中所有的R函數的名稱(在這種情況下,只是fx01)。

然後,我把所有的東西都包裝成了.tar.gz。並跑

install.packages("MySmallExample.tar.gz",repos=NULL,type="source") 


> install.packages("/MySmallExample.tar.gz",repos=NULL,type="source") 
Installing package(s) into ‘/R/x86_64-pc-linux-gnu-library/2.15’ 
(as ‘lib’ is unspecified) 
* installing *source* package ‘MySmallExample’ ... 
** libs 
g++ -I/usr/share/R/include -DNDEBUG -I../inst/include -I"/R/x86_64-pc-linux-gnu-library/2.15/Rcpp/include" -I"/R/x86_64-pc-linux-gnu-library/2.15/RcppEigen/include" -DEIGEN_DONT_PARALLELIZE -fopenmp -fpic -O3 -pipe -g -c MSE.cpp -o MSE.o 
g++ -shared -o MySmallExample.so MSE.o -L/R/x86_64-pc-linux-gnu-library/2.15/Rcpp/lib -lRcpp -Wl,-rpath,/R/x86_64-pc-linux-gnu-library/2.15/Rcpp/lib -fopenmp -L/usr/lib/R/lib -lR 
installing to /R/x86_64-pc-linux-gnu-library/2.15/MySmallExample/libs 
** R 
** inst 
** preparing package for lazy loading 
** help 
*** installing help indices 
** building package indices 
** testing if installed package can be loaded 

* DONE (MySmallExample) 
4

你看了關於如何與R口的'寫作R附加軟件說明書?

你是當然是可以自由地做到這一點沒有Rcpp,但是我們寫了Rcpp供我們使用,因爲我們發現它使得這些交換變得更加簡單。在CRAN上使用Rcpp的94個軟件包似乎同意...

您正在使用Eigen,並且希望爲第三方打包(「裁判」)。現在,如果您要使用RcppEigen ,您可以確信Eigen存在,因爲它位於RcppEigen內。用你做的,你不是......

另外,.C()是一個更爲嚴格的界面,.Call()

+0

不,我沒有看過那個文件。我希望有人能指點我一個更短的版本(我不打算很快提交給任何人 - 只是將R的基礎設施作爲載體)。謝謝,你的第三段是強調RcppEigen - 我已經編輯了相應的問題。我同意.Call()和.C()的優點,但是在這一點上,我的代碼已經寫在了R中。我只是尋找一種無憂無慮的方式,使得它可以很容易地運行/安裝由不需要計算機熟練的人(超過小費'安裝.package'在R) – user189035

+0

問題解決。謝謝!我會寫我做錯了什麼... – user189035