假设我有一个 C++ 代码(请参阅下面的简单示例)。 我想让期刊审稿人轻松安装/运行
所以我认为最简单的方法是将其变形为简化的 类 R 包的 tar.gz 文件,以便裁判可以安装它 通过简单地调用 install.packages 到本地 .tar.gz 文件。
原因是不知道是什么机器 裁判正在使用,但我很确定裁判会 知道如何安装 R 包,这样更容易 我将我的代码变形为 R“包”——或者无论如何, 与它足够相似的东西,它可能是 通过简单调用 install.package() 安装。
对先前 question 的回答似乎暗示这个 确实有可能。我遵循了其中的建议并且 用我的 cpp 代码创建了一个/src 目录(显示的那个 下面)和一个包含以下内容的 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]])
}
和一个空的/inst/include 和一个包含最小(但有效).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();
}
}
最佳答案
您是否阅读过关于如何与 R 交互的“Writing R Extensions”手册?
在没有 Rcpp 的情况下,您当然可以自由地执行此操作,但我们编写 Rcpp 供我们使用,因为我们发现它使这些交换变得更加容易。 CRAN 上使用 Rcpp 的 94 个包似乎同意...
您正在使用 Eigen,并且您希望将其打包供第三方(“裁判”)使用。现在,如果你要使用 RcppEigen 你会确保 Eigen 存在于 RcppEigen 中。通过你所做的,你不是...
另外,.C()
是一个比 .Call()
限制更多的接口(interface)。
关于c++ - 如何(轻松)将 C++ 函数包装到易于安装的 R 'package',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14034868/