R,。呼叫功能和SEXP结构

时间:2013-09-27 11:07:19

标签: c r

我正在使用针对我的问题的非常具体的模拟退火算法构建R中的包,我对C代码和SEXP有疑问,我无法解决。我不是R的专家,我一直在使用它只有3个星期......但我必须这样做。

据我所知,R中的.Call函数通过引用将参数作为SEXP结构传递给C(即它们不重复)。我对吗?如果我在C中使用另一个需要此SEXP结构的第一个函数调用另一个函数怎么办? (见例)。我问,因为其中一个参数很大并且使用了很多空间(10 ^ 7~10 ^ 18双倍,虽然我不会在每次迭代中都使用它们)而且我会调用这个函数很多次,所以如果我每次调用它时这个参数都会重复,那么我的内存就会耗尽。

MWE:

R电话

MySimAn <- function(def_energy, i_pos, T0, Tfinal){
  ret <- .Call("CMySimAn",def_energy, i_pos, T0, Tfinal, seq0)
  ret
}

C函数

double Energy(SEXP def_energy, SEXP seq0, int i0){
  int i;
  double res=0;
  for(i=0;i<INTEGER(GET_DIM(seq0))[0];i++){
    res += NUMERIC(def_energy)[i0+INTEGER(seq0)[i]];
  }
  return(res);
}

SEXP CmySimAn(SEXP def_energy, SEXP i_pos, SEXP T0, SEXP Tfinal, SEXP seq0){
  SEXP = Ene;
  PROTECT(Ene = NEW_NUMERIC(1));
  REAL(Ene)[0] = Energy(def_energy, seq0, INTEGER(i_pos));
  UNPROTECT(1);
  return Ene;
}

这样的事情是否有效(函数Energy中的代码未被检查,因此可能是错误的)?每当我调用它时,我是否会创建def_energy的副本,无论是在R还是C?非常感谢你的帮助。

1 个答案:

答案 0 :(得分:8)

代码几乎(语法上)正确写入,并且没有内存复制;从R传递给C的参数应该被视为“只读”。

一个常见的范例是编写一个R / C接口层,在纯(非R)C中从该层调用任何函数。所以

double Energy(const double *def_energy, const int *seq0, int dim0, int i0)
{
  int i;
  double res=0;
  for(i = 0; i < dim0; i++) {
    res += def_energy[i0 + seq0[i]];
  }
  return(res);
}

使用const强制执行隐式契约,不应写入从R传递的值。使用R / C包装器

SEXP CmySimAn(SEXP def_energy, SEXP i_pos, SEXP T0, SEXP Tfinal, SEXP seq0){
  double Ene = Energy(REAL(def_energy), INTEGER(seq0), INTEGER(GET_DIM(seq0)[0]),
                      INTEGER(i_pos)[0]);
  return ScalarReal(Ene);
}

数字元素的访问者是REAL()(您在Energy中使用了NUMERIC)。您对PROTECT(...); REAL(Ene)[0] = ...; UNPROTECT(Ene);的使用是正确的。