使用Rcpp中其他包的C函数

时间:2013-12-09 15:28:54

标签: c++ c r rcpp

我正在尝试从c ++函数中的cubature包调用C例程来执行多维集成。

我正在尝试重现的基本R示例是

library(cubature)
integrand <- function(x) sin(x)
adaptIntegrate(integrand, 0, pi)

我可以在this recipe from the gallery之后从Rcpp调用这个R函数,但是从c / c ++到R来回切换会有一些性能损失。从C ++直接调用C函数似乎更合理。

C例程adapt_integratecubature导出

 // R_RegisterCCallable("cubature", "adapt_integrate", (DL_FUNC) adapt_integrate);

但我不明白如何从c ++中调用它。这是我的跛脚尝试,

sourceCpp(code = '
#include <Rcpp.h>
using namespace Rcpp;

// [[Rcpp::export]]
double integrand(double x){
 return(sin(x));
}

// [[Rcpp::depends(cubature)]]
// [[Rcpp::export]]
Rcpp::List integratecpp(double llim, double ulim)
{
  Rcpp::Function p_cubature = R_GetCCallable("cubature", "adapt_integrate");

  Rcpp::List result = p_cubature(integrand, llim, ulim);
  return(result);
}
'
)

integratecpp(0, pi)

这无法编译;很明显,我正在做一些非常愚蠢的事情,并且缺少一些重要的步骤来将R_GetCCallable的输出转换为Rcpp::Function(或直接调用它?)。我已经阅读了几篇涉及函数指针的相关文章,但还没有看到使用外部C函数的示例。

3 个答案:

答案 0 :(得分:6)

不幸的是cubature没有在inst/include中发送标题,所以你必须从它们那里借用它并在你的代码中做这样的事情:

typedef void (*integrand) (unsigned ndim, const double *x, void *,
           unsigned fdim, double *fval);

int adapt_integrate(
    unsigned fdim, integrand f, void *fdata,
    unsigned dim, const double *xmin, const double *xmax, 
    unsigned maxEval, double reqAbsError, double reqRelError, 
    double *val, double *err)
{
    typedef int (*Fun)(unsigned,integrand,void*,unsigned,
        const double*,const double*, unsigned, double, double, double*, double*) ;
    Fun fun = (Fun) R_GetCCallable( "cubature", "adapt_integrate" ) ;           
    return fun(fdim,f,fdata,dim,xmin,xmax,maxEval,reqAbsError, reqRelError,val,err); 
}

cubature的维护人员进行交谈可能是个好主意,因为他在inst/include中发布了声明,因此您只需要使用LinkingTo

答案 1 :(得分:4)

之前没有看过这个问题,看起来@Romain解决了这个问题。

为了完整起见,xtsRcppXts包提供了各方玩耍时如何执行此操作的工作示例。在xts中,我们在(源)文件inst/include/xtsAPI.h中执行此操作(大约有十个函数):

SEXP attribute_hidden xtsLag(SEXP x, SEXP k, SEXP pad) {     
    static SEXP(*fun)(SEXP,SEXP,SEXP) = NULL;         
    if (fun == NULL)                                  
        fun = (SEXP(*)(SEXP,SEXP,SEXP)) R_GetCCallable("xts","lagXts");   
    return fun(x, k, pad);                               
}  

以及R_registerRoutinesR_RegisterCCallable的常规业务。

RcppXts中,这个(在Rcpp模块中)被选为

function("xtsLag", 
         &xtsLag,    
         List::create(Named("x"), Named("k"), Named("pad")),   
         "Extract the coredata from xts object");

效果很好。有人谴责我更紧凑地写xts方面(因为if NULL是虚假的),我最终将会...... {/ p>

答案 2 :(得分:1)

这个问题现在已经有三年了,但我想指出,现在RcppNumerical库可用,与Rcpp的多维集成可能更容易: https://github.com/yixuan/RcppNumerical

计算积分的例程基于Thomas Hahn的古巴包,也可以在CRAN上的R2Cuba库中找到,所以如果你可以接受古巴例程而不是Cubature函数adaptIntegrate(),那么这个包可能是感兴趣的。