【问题标题】:Calling compiled C from R with .C()使用 .C() 从 R 调用编译后的 C
【发布时间】:2011-01-16 20:57:27
【问题描述】:

我正在尝试从 R 调用一个程序(C 可执行文件measurementDensities_out 中的函数getNBDensities)。该函数传递了几个数组和变量double runsum。现在,getNBDensities 函数基本上什么都不做:它打印以筛选传递参数的值。我的问题是调用函数的语法:

array(.C("getNBDensities",
            hr = as.double(hosp.rate), # a vector (s x 1)
            sp = as.double(samplingProbabilities), # another vector (s x 1)
            odh = as.double(odh), # another vector (s x 1)
            simCases = as.integer(x[c("xC1","xC2","xC3")]), # another vector (s x 1)
            obsCases = as.integer(y[c("yC1","yC2","yC3")]), # another vector (s x 1)
            runsum = as.double(runsum), # double
            DUP = TRUE, NAOK = TRUE, PACKAGE = "measurementDensities_out")$f,
            dim = length(y[c("yC1","yC2","yC3")]),
            dimnames = c("yC1","yC2","yC3"))

在正确执行函数后(即正确的输出打印到屏幕),我得到的错误是

Error in dim(data) <- dim : attempt to set an attribute on NULL

我不清楚我应该传递函数的维度是多少:它应该是s x 5 + 1(长度为s 的五个向量和一个双倍)?我尝试了各种组合(包括sx5+1),但在网上只发现了看似矛盾的描述/示例,说明这里应该发生的事情。

有兴趣的可以看下C代码:

#include &lt;R.h&gt;
#include &lt;Rmath.h&gt;
#include &lt;math.h&gt;
#include &lt;Rdefines.h&gt;
#include &lt;R_ext/PrtUtil.h&gt;
#define NUM_STRAINS 3
#define DEBUG
void getNBDensities(  double *hr, double *sp, double *odh, int *simCases, int *obsCases, double *runsum );
void getNBDensities( double *hr, double *sp, double *odh, int *simCases, int *obsCases, double *runsum ) {
#ifdef DEBUG
  for ( int s = 0; s < NUM_STRAINS; s++ ) {
    Rprintf("\nFor strain %d",s); 
    Rprintf("\n\tHospitalization rate = %lg", hr[s]);
    Rprintf("\n\tSimulation probability = %lg",sp[s]);
    Rprintf("\n\tSimulated cases = %d",simCases[s]);
    Rprintf("\n\tObserved cases = %d",obsCases[s]);
    Rprintf("\n\tOverdispersion parameter = %lg",odh[s]);
}
  Rprintf("\nRunning sum = %lg",runsum[0]);
#endif
}

简单的解决方案

虽然可能存在更好(即可能更快或语法更清晰)的解决方案(请参阅下面 Dirk 的回答),但以下代码简化是可行的:

     out<-.C("getNBDensities",
            hr = as.double(hosp.rate),
            sp = as.double(samplingProbabilities),
            odh = as.double(odh),
            simCases = as.integer(x[c("xC1","xC2","xC3")]),
            obsCases = as.integer(y[c("yC1","yC2","yC3")]),
            runsum = as.double(runsum))

变量可以在&gt;out中访问。

【问题讨论】:

  • 你的函数没有返回任何东西,那么你为什么要把任何东西都变成数组呢?
  • @hadley:我认为您正在研究这个问题。我正在研究我在代码中调用的另一个 C 函数的示例,它确实操作了一个大数组。这个函数最终只会从数组中读取来计算runsum,然后我的 R 程序的其余部分将使用它。但是,仅调用 out&lt;-(.C("getNBDensities",...)) 只会为 out 返回 NULL...
  • 我总是会推荐.Call() 而不是.C()
  • 我的代码实际上已经在其他地方使用了.C() 调用。当我使用Rprof 而不是.C() 时,.Call() 出现在顶部附近——我认为这意味着它已经在内部进行了优化。底线是我的语法很糟糕,我担心如果我无法在这里掌握一个简单的.C() 调用,我将无法使用.Call() 重写我的其他函数调用。跨度>
  • 历史上,.C() 排在第一位。但它的功能也受到更多限制。大多数理智的人推荐.Call()

标签: c r


【解决方案1】:

您可能想查看inline 包,它使 C、C++ 或 Fortran 代码的编译、链接和加载变得轻而易举。

也就是说,特别是如果 C++ 是您的另一个选择,还请查看 Rcpp 包,它允许您轻松地来回传输 R 和 C++ 对象。

【讨论】:

  • 这应该是一个非常小而快速的函数(它只是计算三个样本的负二项式密度之和),所以 C++ 是多余的;正如我所写的,我还在其他地方调用已编译的 C。如果我无法弄清楚这一点以及未来的项目,我会调查inline——谢谢你的参考。
  • Rcpp 不仅有助于 运行速度更快的代码,而且 IMNSHO 也有助于 编写速度更快的代码,因为它消除了 C 语言的许多蜘蛛网API。看看,问题通常会在rcpp-devel 列表中得到友好的回答。
  • 谢谢,我去看看。我更喜欢 C++。然而,这个程序(R 包pomp 的实现)已经编写好了——我的目标只是改进运行时。对于未来的项目,学习 Rcpp 的小障碍肯定是值得的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-10-21
  • 2010-10-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-03
相关资源
最近更新 更多