如何从R调用C函数?

Yes*_*ter 3 c r

如何使用R数据从R级别使用用C编写的某些函数。例如。使用如下功能:

double* addOneToVector(int n, const double* vector) {
    double* ans = malloc(sizeof(double)*n);
    for (int i = 0; i < n; ++i)
        ans[i] = vector[i] + 1
    return ans;
}
Run Code Online (Sandbox Code Playgroud)

在上下文中:

x = 1:3
x = addOneToVector(x)
x # 2, 3, 4
Run Code Online (Sandbox Code Playgroud)

Yes*_*ter 5

我首先搜索了stackoverflow,但是我发现这里没有答案。
总体思路是(用于linux的命令,但在其他OS下是相同的思路):

  1. 创建仅使用指向基本类型的指针的函数,并通过副作用完成所有操作(返回void)。例如:

    void addOneToVector(int* n, double* vector) {
        for (int i = 0; i < *n; ++i)
            vector[i] += 1.0;
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 将文件C源代码编译为动态库,可以使用R快捷方式执行此操作:

    $ R CMD SHLIB lib.c
    
    Run Code Online (Sandbox Code Playgroud)
  3. 从R加载动态库:

    dyn.load("foo.so")
    
    Run Code Online (Sandbox Code Playgroud)
  4. 使用.CR函数IE 调用C函数:

    x = 1:3
    ret_val = .C("addOneToVector", n=length(x), vector=as.double(x))
    
    Run Code Online (Sandbox Code Playgroud)

它返回列表,您可以在调用函数后从中获取输入值。

ret_val$x # 2, 3, 4
Run Code Online (Sandbox Code Playgroud)

您现在可以包装它,以便能够更轻松地使用R。

有一个漂亮的页面描述了整个过程,此处有更多详细信息(也涵盖了Fortran):

http://users.stat.umn.edu/~geyer/rc/

  • 在这种情况下,“inline”包也很方便: `addOne = inline::cfunction(sig = c(n = "integer", vector = "numeric"), body = 'for(int i = 0; i &lt; *n; ++i) vector[i] += 1.0;', convention = ".C")` 然后 `addOne(length(x), as.double(x))$vector`。 (3认同)
  • 想要提及的是,在使用这种方法时,我注意到以下几点。`foo.so` 在 Mac 中创建,而在 Windows 上,相应的文件是 `foo.dll` (2认同)