2016-11-12 34 views
2

謹此的R包,它的芯用C++編寫和基本上由一個長運行循環的: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

你是什麼意思中斷?用戶可以中斷,例如通過某個按鍵進行操作? – dimm

+0

@dimm是的,從用戶的角度來看,這將是最簡單的解決方案(例如,擊中'Crtl-c')。 –

+0

我的建議是將循環嵌套在'try' - 'catch'塊中,並在檢測到中斷時引發異常。這應該夠了。 – Gonmator

回答

3

更新:最簡單的方法是通過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在帖子中的評論,以瞭解這種方法的後果。

我個人只使用這個通過C到interrupt下載的捲曲包。對於使用C++中的R_CheckUserInterrupt的示例,您可能可以使用search metacran

+0

同意 - 我有這種感覺,我們有這裏的帖子(或者在Rcpp名單上?)。我會放棄'.C()' - 這太過於束縛,每個人都會泄氣。 –

+0

@DirkEddelbuettel在Rcpp API中採用'pending_interrupt'或類似的方法可能會很好。 – Jeroen

+0

你能否提出問題或更好的準備PR? ;-) –