R:如何编写可中断的C ++函数,并恢复部分结果

时间:2016-11-12 13:51:21

标签: c++ r

我们正在编写一个R包,其核心是用C ++编写的,基本上由一个长时间运行的循环组成:

void core_func(double* data)
{
    while (!done)
    {
        // update 'data'
    }
}

使用R的.C机制进行调用:

ans <- .C("core_func", data = as.double(data))$data

我们希望用户能够中断该功能,并恢复部分结果(即中断点的*data内容)。

问题:这有可能吗?

到目前为止,我们提出解决方案的努力已经产生this post,如果正确解释,它会指示如何干净地退出循环。

void core_func(double* data)
{
    while (!done && !checkInterrupt())
    {
        // update 'data'
    }
}

我们还没想到的是,如何将部分结果传递给调用者(又名.R用户)。

解决方案:似乎解决方案一直都在我们面前。 Simon Urbanek在上述帖子(原帖here)中提出的方法涵盖了所有基础。利用checkInterrupt()函数,可以将C ++代码设计为在用户中断时干净地退出;并且,最重要的是,然后将控制权交还给R中的调用.C函数,该函数可以有序地返回(部分)结果。

感谢@Jeroen清理事务(以及searching for code中关于METACRAN的提示)!

有关Jeroen答案中的更新的说明:我们希望保持C ++代码与R不相关(排除对Rcpp的依赖)。

1 个答案:

答案 0 :(得分:5)

更新:最简单的方法是通过Rcpp调用C ++并通过Rcpp::checkUserInterrupt进行检查。如果中断挂起,则会自动引发异常。请参阅rcpp attributes的第2.4节。

原始答案: R允许通过C API检查SIGINT:

R_CheckUserInterrupt();

但是,如果中断未决,此功能将立即跳回控制台,这会使您的C / C ++代码处于未定义状态。

技巧suggested by Simon Urbanek是使用以下包装器代码:

/* Check for interrupt without long jumping */
void check_interrupt_fn(void *dummy) {
  R_CheckUserInterrupt();
}

int pending_interrupt() {
  return !(R_ToplevelExec(check_interrupt_fn, NULL));
}

您现在可以致电pending_interrupt()来检查中断是否有待处理并自行处理,例如:提出一些特殊的C ++异常或简单地返回中间结果。请务必阅读Simon在帖子中的评论,以了解这种方法的后果。

我个人只在curl包中通过C到interrupt下载使用了这个。对于使用C ++ {/ 1}}的示例,您可以search metacran