如何从R中检查externalptr是否为NULL

时间:2014-10-31 02:23:39

标签: r swig

我使用SWIG生成包装代码以从R语言中访问C代码。包装器代码使用R externalptr类型来保存对C指针的引用。在某些情况下,这些指针在C端是NULL,在显示时在R中显示为nil值。在R方面,is.null()上的is.na()externalptr都会返回FALSE。例如:

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

从上面的代码输出中可以看出,ref广告位包含externalptr,其为&#34; nil&#34;。如何从R中确定C中的这个指针是否为NULL?

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

2 个答案:

答案 0 :(得分: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

答案 1 :(得分: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解决方案更复杂,但可以在任何平台上以简单的脚本工作。