我正在用 C 编写一些代码,以便从 R 动态调用。
此代码生成随机泊松过程的路径,直至所需时间 T。 因此,在每次调用我的 C 函数时,返回的 vector 的长度将根据生成的随机数而有所不同。
我必须创建什么 R 数据结构? LISTSXP?另一个?
我如何创建它,如何附加到它?尤其是我怎样才能把它还给 R?
感谢您的帮助。
最佳答案
将什么用作临时结构完全取决于您,因为最终您无论如何都必须为结果分配一个 vector 。因此,无论您将使用什么,都不会返回。有几种可能:
- 使用
Calloc
+Realloc
+Free
允许您根据需要扩展临时内存。获得完整集合后,分配结果 vector 并将其返回。 - 如果您可以轻易地高估大小,则可以过度分配结果 vector 并在返回之前使用
SETLENGTH
。但是,这存在一些问题,因为结果将保持过度分配,直到稍后复制。 - 您可以使用您所暗示的 vector block 链表,即分配和保护一对列表,您可以根据需要将 vector 附加到尾部。最后,您分配返回 vector 并复制您分配的 block 的内容。这比上述两者都更复杂。
它们各有优缺点,因此真正取决于您的应用来选择最适合您的。
编辑:添加了一个使用配对列表方法的示例。我仍然会推荐 Realloc
方法,因为它更容易,但是:
#define BLOCK_SIZE xxx /* some reasonable size for increments - could be adaptive, too */
SEXP block; /* last vector block */
SEXP root = PROTECT(list1(block = allocVector(REALSXP, BLOCK_SIZE)));
SEXP tail = root;
double *values = REAL(block);
int count = 0, total = 0;
do { /* your code to generate values - if you want to add one
first try to add it to the existing block, otherwise allocate new one */
if (count == BLOCK_SIZE) { /* add a new block when needed */
tail = SETCDR(tail, list1(block = allocVector(REALSXP, BLOCK_SIZE)));
values = REAL(block);
total += count;
count = 0;
}
values[count++] = next_value;
} while (...);
total += count;
/* when done, we need to create the result vector */
{
SEXP res = allocVector(REALSXP, total);
double *res_values = REAL(res);
while (root != R_NilValue) {
int size = (CDR(root) == R_NilValue) ? count : BLOCK_SIZE;
memcpy(res_values, REAL(CAR(root)), sizeof(double) * size);
res_values += size;
root = CDR(root);
}
UNPROTECT(1);
return res;
}
关于c - 将动态 vector 从 C 返回到 R,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8796675/