2014-10-31 65 views
2

我正在使用SWIG生成封裝代碼以從R語言訪問C代碼。包裝代碼使用R externalptr類型來保存對C指針的引用。在某些情況下,這些指針在C端爲NULL,在R中顯示時顯示爲零值。在R方面,在externalptr上撥打is.null()is.na()均返回FALSE。例如:如何檢查externalptr是否爲空R

> val = librdf_query_results_get_binding_value(results, 2) 
> val 
An object of class "_p_librdf_node_s" 
Slot "ref": 
<pointer: (nil)> 
> class([email protected]) 
[1] "externalptr" 
> is.null([email protected]) 
[1] FALSE 
> is.na([email protected]) 
[1] FALSE 

如可以從上面的代碼輸出中可以看出,狹槽ref含有externalptr,這是「無」。我如何從R中確定C中的這個指針是NULL?

如果你想在上下文中查看代碼,它可在GitHub上: https://github.com/ropensci/redland-bindings/blob/master/R/redland/inst/tests/test.redland_base.R#L40

+4

我想你可能需要一個C/C++幫助函數來爲你計算外部指針。 – 2014-10-31 02:30:41

+0

我認爲@DirkEddelbuettel是對的。您可能需要考慮'bigmemory :: is.nil'作爲指導。 – 2014-10-31 02:58:57

+0

謝謝@DirkEddelbuettel,我很懷疑。那麼你認爲''externalptr'類型的重寫is.null()是否合理,還是將它放在我自己的包中會更好? – metamattj 2014-10-31 04:49:31

回答

3

爲了完整起見,這裏是我使用的解決方案。按照@DirkEddelbuettel的建議,它需要C端的一個功能,以及一個R端的功能。 C函數是:

#include <Rinternals.h> 

SEXP isnull(SEXP pointer) { 
    return ScalarLogical(!R_ExternalPtrAddr(pointer)); 
} 

而在R中的包裝函數是:

is.null.externalptr <- function(pointer) { 
    stopifnot(is(pointer, "externalptr")) 
    .Call("isnull", pointer) 
} 

對於使用的一個例子來自R內:

> p <- new("externalptr") 
> p 
<pointer: (nil)> 
> is.null.externalptr(p) 
[1] TRUE 
3

C溶液上方是最優雅,但編譯器可能並不總是可用的。不需要編譯代碼的一個解決辦法是這樣的:

identical(pointer, new("externalptr")) 

但是這不會如果對象具有自定義屬性的工作。如果是這樣的話,你可以這樣做:

isnull <- function(pointer){ 
    a <- attributes(pointer) 
    attributes(pointer) <- NULL 
    out <- identical(pointer, new("externalptr")) 
    attributes(pointer) <- a 
    return(out) 
} 

又有點比C解決方案更多地參與,但將在一個簡單的腳本運行在任何平臺上。