【问题标题】:Rcpp: Call C function from a package within RcppRcpp:从 Rcpp 中的包调用 C 函数
【发布时间】:2015-03-13 08:46:56
【问题描述】:

我想用 Rcpp 编写一个 C++ 函数,该函数使用 hypred 包中的 C 函数,该包位于 CRAN here

我阅读了using C function from other package in Rcpp,但不明白这是否适用于我,如果适用,该怎么办。

所需的函数在源文件 /src/hypredRoutines.c 中,名为 meiosisFUNAllChr

到目前为止,我根据这个 SO 问题 here 所做的是:

  1. 我将函数 meiosisFUNAllChr 与其余代码分开,并将其放在一个名为 meiosisFUNAllChr.c 的新文件中。
  2. 我创建了一个名为 meiosisFUNAllChr.h 的头文件,其中包含:

    #ifndef MEIOSISFUNALLCHR_H
    #define MEIOSISFUNALLCHR_H
    void meiosisFUNallChr (...);
    #endif 
    
  3. 用它编译

    gcc -c -o meiosisFUNAllChr.o meiosisFUNAllChr.c
    
  4. 创建了一个虚拟 c++ 函数

    #include <Rcpp.h>
    using namespace Rcpp;
    
    extern "C" {
     #include "meiosisFUNallChr.h"
    }
    
    // [[Rcpp::export]]
    int timesTwo(int x) {
     return x * 2;
    }
    

此时,使用 sourceCpp 编译不起作用。你能告诉我如何让它工作吗?

非常感谢!

编辑

用 sourceCpp 编译给了我:

meiosisFUNallChr.h: file or directory not found

【问题讨论】:

  • 我不是 Rcpp 方面的专家,但我发现 RStudio 非常有用,因为它为它提供了模板。当你创建一个项目时,你可以指定它使用 Rcpp 并且它简化了很多事情。
  • 我知道这些工具并且已经使用它们,但我不知道这将如何帮助我让 C 函数在我的代码中工作:-)
  • 你试过使用sourceCpp吗?
  • @DominicComtois 是的,我做到了
  • 好吧...当你说它不起作用时,你得到了什么?错误信息?还是该功能不可用?

标签: r rcpp


【解决方案1】:

hypred 注册了它的两个函数,在 R 级别你可以像这样获取你想要的一个:

xp <- getDLLRegisteredRoutines( getLoadedDLLs()[["hypred"]] )[[".C"]][["meiosisFUNallChr"]]$address

我相信你可以像这样在 C++ 中访问函数指针:

DL_FUNC meiosisFUNallChr = reinterpret_cast<DL_FUNC>( R_ExternalPtrAddr(xp) ) ;

但是,如果您可以证明您确实需要直接调用 C 函数,那么您最好与包作者协商他​​们实现 this scheme

【讨论】:

  • +1 关于注册方案——在 Rcpp 宇宙中有几个包可以做到这一点。我最简单的可能是 RApiSerialize。 @romain:getDLLRegisteredRoutine(...) 方法是否被 CRAN “祝福”(或至少可以容忍),即您用于 mlxR 的方法是什么?
  • 不知道。我不明白为什么不这样做,我只调用允许的 R 函数 getDLLRegisteredRoutinesgetLoadedDLLs ... mlxR 是一种完全不同的鸟
  • 是的,完全不同的鸟——不是 R 控制下的库。从你的所作所为中有什么可以概括的吗?我们可能对 Rblpapi 有类似的问题。
  • 我们使用的可能不适合分发。基本上没有任何代码或示例直接引用底层 c++ 库。用户应该先安装了一些软件,mlxR 在运行时从该软件编译一个 R 包,因此 CRAN 不需要知道该软件...
【解决方案2】:

简单地说:

  • 您想使用另一个源文件(可能在合适的许可下可用)。

  • 您想从您的新文件中调用它。

  • 所以你已经有两个文件了。

现在警报应该响起,你真的,真的,想要创建一个包

Rcpp 文档在 许多 的地方有详细说明。在 CRAN 上有 340 多个使用 Rcpp 的包,其中许多包也在执行调用 C 文件的问题。挑一两个,研究它们的结构;还可以选择由完整记录的 Rcpp 工具创建的一两个,例如 Rcpp.package.skeleton(),事情应该会变得更加清晰。

编辑: 显然,这种方式只有在其他包没有导出其功能的情况下才需要。如果您可以让其作者导出,请在 Romain 的回答中使用它。导出/使用的包对是 zoo/xts、xts/RcppXts、expm/RcppKalman(不在 CRAN 上)、RApiSerialize/RcppRedis、...

【讨论】:

  • 谢谢你,Dirk,我会按照你的建议去做。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-06-25
  • 1970-01-01
  • 2013-11-13
  • 2019-01-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多