【问题标题】:Function .C -- argument setup fails compilationFunction .C -- 参数设置编译失败
【发布时间】:2014-05-04 06:37:03
【问题描述】:

我目前正在学习在 R 中调用已编译的 C 代码。昨天我为无限 pi 系列创建了一个函数,当在 R 中运行时,它返回一个长度为 1 的数字向量 (pi),效果很好。今天我正在研究一个输出可变长度数值向量的函数,该函数是为用户定义的n 计算的斐波那契数列。

编写 R 扩展中,注意到“编译后的代码不应该返回任何东西,除非通过它的参数”。这就是我遇到麻烦的地方。我不知道如何设置下面的C代码,即final中的参数 else 语句,这样在调用@之后不会触发错误987654324@.

我在 C 程序中编译了一个稍微不同的版本,它可以工作。但是,编译要在 R 中调用的代码的设置不同。我必须对其进行调整以适应 R 函数 .C 的规范。

如何更改以下函数,使其编译时没有警告或错误,并且可以在 R 函数 .C 中调用?

要编译的C代码:

void fibonacci(int *n, int *ans)
{
  # *ans = 0;  I tried this, didn't work

  if(*n == 1 || *n == 2){
    *ans = 1;
  } else if(*n == 0){
    *ans = 0;
  } else {
    *ans = fibonacci(n - 2) + fibonacci(n - 1); # tried 'ans' in arguments
  }                                             # here, didn't work
}

此处出现错误:

## compile and create shared library
> system('gcc -Wall -g -c -fPIC fibonacciR.c -o fibonacciR.o')
fibonacciR.c: In function ‘fibonacci’:
fibonacciR.c:8:5: error: too few arguments to function ‘fibonacci’
fibonacciR.c:1:6: note: declared here
fibonacciR.c:8:5: error: too few arguments to function ‘fibonacci’
fibonacciR.c:1:6: note: declared here

将 C 代码中的最后一行 ans 更改为

} else {
  *ans = fibonacci(n - 2, ans) + fibonacci(n - 1, ans);
}

产生不同的错误

> system('gcc -Wall -g -c -fPIC fibonacciR.c -o fibonacciR.o')
fibonacciR.c: In function ‘fibonacci’:
fibonacciR.c:10:5: error: void value not ignored as it ought to be
fibonacciR.c:10:5: error: void value not ignored as it ought to be

我绝对不是专业的 C 程序员,而且我不知道如何忽略一个论点。此外,这个函数的设置方式,当我在 R 中调用它时,它只会返回一个值。所以我认为我需要为用户定义的参数n 循环.C。对吗?


一旦我解决了错误,请致电关注。

system('gcc -Wall -g fibonacciR.o -shared -o libfibonacciR.so')
## load compiled program into R
dyn.load('libfibonacciR.so')
## create function to call compiled program
fibonacci <- function(n)
{
  .C('fibonacci', as.integer(n), ans = as.integer(ans))$ans
}
## call function - result should be first 10 fibonacci numbers
fibonacci(n = 10)
## expected result
[1]  1 1 2 3 5 8 13 21 34 55

【问题讨论】:

  • fibonacci() 函数有 2 个参数。你只通过了一个(第一个)。试试 fibonacci(n - 2, ans) + fibonacci(n - 1, ans)
  • 对,我试过了。在同一行的评论中注明。
  • 错误还是一样?
  • 另请注意 fibonacci() 不返回值,并且您正在对其返回值进行操作。修复缺少的参数问题后,这将导致另一个编译器错误。
  • 顺便说一句,你不应该使用.C 接口,它太旧了,不推荐使用。而是使用.Call()。另外,也许你不知道内联包?您可能会发现 adv-r.had.co.nz/C-interface.html 很有帮助。

标签: r


【解决方案1】:

您可以加载 Rcpp 只是为了访问其 Rcpp 属性功能。它允许您将其写为(扩展为两行以进行显示;它确实适合一行):

R> cppFunction('double fib(double n) { if (n<2) return(n); 
+                                      else return fib(n-1) + fib(n-2);}')
R> fib(10)
[1] 55
R> 

如果您运行cppFunction(..., verbose=TRUE),您将看到它创建的文件。

一般情况下,避免使用.C() 接口,而将注意力集中在.Call()。这是最新 R 版本的 NEWS 文件中非常明确的建议:

* .C(DUP = FALSE) and .Fortran(DUP = FALSE) are now deprecated, and
  may be disabled in future versions of R.  As their help has long
  said, .Call() is much preferred.

让我们再强调一次.Call() 是首选。有关使用.Call() 的更多信息,请参见例如Hadley's Advanced R Programming draft。他的建议也是直接联系 Rcpp。

【讨论】:

  • 哇,cppFunction 可能会解决我所有的问题。 :) 非常感谢。我有一个 2013 年 9 月 25 日的印刷版“编写 R 扩展”,我想我忘了查看新闻发布。干杯
  • 像您一样“以漫长而艰难的方式”完成它会有所帮助。既然这已经过去了,请享受一些提高生产力的工具:)
【解决方案2】:

您已经知道下一行中的错误。

*ans = fibonacci(n - 2) + fibonacci(n - 1); # tried 'ans' in args here,

我认为,您应该编写一个辅助函数来完成所有工作,从而简化这两个过程。

int fibonacci_helper(n)
{
  if(n == 1 || n == 2){
    return 1;
  } else if(n == 0){
    return 0;
  } else {
    return fibonacci_helper(n-1) + fibonacci_helper(n-2);
  }
}

void fibonacci(int *n, int *ans)
{
  *ans = fibonacci_helper(*n);
}

【讨论】:

    【解决方案3】:

    fibonacci 被声明为接受两个指针作为参数,并且它不返回任何内容。但是在您的 else 块中,您尝试使用单个整数参数调用它并从中捕获返回值。

    在你的 else 块中尝试这样的事情:

    int n1 = *n - 1;
    int n2 = *n - 2;
    int ans1;
    int ans2;
    fibonacci(&n1, &ans1);
    fobonacci(&n2, &ans2);
    *ans = ans1 + ans2;
    

    另外,在您的 else if 块中,应该是 (*n == 0)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-07
      相关资源
      最近更新 更多