我们正在编写一个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的依赖)。
答案 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。