在包BAR中使用R package FOO的c ++代码的最佳方法

时间:2014-01-07 21:27:00

标签: c++ r rcpp

我正在尝试使用Rcpp定义一个加速的函数。情况如下:

  • 我有一个包含很多C ++代码的软件包(我自己的软件包,当前没有使用Rcpp),它已经定义了一组函数,例如: foo_a和foo_b。
  • 在另一个包BAR(使用Rcpp)中我定义了一个函数(使用Rcpp Attributes),我想调用函数foo_a和foo_b。

我该如何解决这个问题?在其他帖子中看一点我得到的是我在某种程度上在FOO中包含头文件并在BAR中使用属性// [[Rcpp::depends(FOO)]],但我似乎错过了一些观点。关于如何做的任何提示?

最佳拉斯

编辑:感谢评论我喜欢Kevin Usheys的方法,并尝试实施它。然而,经过一些编码后,我意识到我实际上不需要来自FOO的函数,而是需要一个类及其公共函数。我想我不能做你为一堂课建议的技巧。我最终把这个类的源文件放在了BAR src目录中的FOO(不是最好的方法,因为我现在有两个版本的相同代码)。但是目前这个黑客对我有用。

3 个答案:

答案 0 :(得分:8)

我会推荐其中一个选项:

如果foo_afoo_b足够简单,只需将inline函数放在FOO的标题中,并将这些标题放在FOO/inst/include/FOO.h中。当您在Rcpp::depends(FOO)上调用compileAttributes(或load_all)时,BAR将包含此文件。

否则,请考虑使用R的注册模型注册函数。这是一项更多的工作,但这是可以忍受的。编写R扩展名有详细信息。我建议将所有注册逻辑放在FOO中,以便客户端包BAR只需要使用它。例如,我在foo_a的标题中有FOO这样的内容,例如在FOO/inst/include/FOO.h

#ifdef COMPILING_FOO
inline int foo_a(int x, double y, const std::string& z){
    typedef int (*Fun)(int, double, const std::string&) ;
    static Fun fun = (Fun)R_GetCCallable( "FOO", "foo_a" ) ;
    return fun(x,y,z) ;
}
#else 
// just declare it
int foo_a(int x, double y, const std::string& z) ;
#endif

以及foo_a中某些.cpp文件中FOO/src的实际定义:

#define COMPILING_FOO
#include <FOO.h>

int foo_a(int x, double y, const std::string& z){
   // do stuff
}

然后,您需要在foo_a函数中使用R_RegisterCCallable注册R_init_FOO

extern "C" void R_init_FOO( DllInfo* info ){
    R_RegisterCCallable( "FOO", "foo_a", (DL_FUNC)foo_a );
}

答案 1 :(得分:4)

如果您不介意将Rcpp介绍到包FOO中,请另外选择 - 请跟随Section 3.5 of Rcpp-attributes并执行以下操作:

  1. // [[Rcpp::interfaces(cpp)]]放在.cpp源文件的顶部,其中包含您希望其他软件包可用的函数,

  2. // [[Rcpp::export]]放在您要导出的功能之前,

  3. compileAttributes()的包目录中调用FOO以生成inst/include中的文件,然后BAR可以使用包// [[Rcpp::depends(FOO)]]

  4. 安装包FOO

  5. 如果你正确设置了这个,你应该可以使用这样的模板调用一个函数(假设foo_aFOO中的导出函数):

    // [[Rcpp::depends(FOO)]]
    
    #include <Rcpp.h>
    #include <FOO.h>
    using namespace Rcpp;
    
    // [[Rcpp::export]]
    SEXP some_function() {
      return FOO::foo_a();
    }
    

答案 2 :(得分:2)

RcppXts包只针对众所周知的xts包中的一系列函数执行此操作。

编辑:以下是来自xts的一些代码。

首先,xts :: src / init.c通过十几个声明(如

)进行注册
R_RegisterCCallable("xts","do_is_ordered",(DL_FUNC) &do_is_ordered);

其次,xts :: inst / include / xtsApi.h为客户端包提供了一个标题,例如

SEXP attribute_hidden xtsIsOrdered(SEXP x, SEXP increasing, SEXP strictly) {
    static SEXP(*fun)(SEXP,SEXP,SEXP) = NULL;
    fun = (SEXP(*)(SEXP,SEXP,SEXP)) R_GetCCallable("xts","do_is_ordered");
    return fun(x, increasing, strictly);
}

第三,在像RcppXts这样的客户端软件包中,我们将此(使用Rcpp模块)定义为

function("xtsIsOrdered",
         &xtsIsOrdered,
         List::create(Named("x"),
                      Named("increasing") = true,
                      Named("strictly") = true),
         "Tests whether object is (strictly) (increasing) ordered");

将它暴露给R.我们同样可以从C ++代码中调用C函数xtsIsOrdered

我删除了错误的早期评论,其中的功能必须符合'SEXP in,SEXP out'。