如何从外部PTR中检查外部PTR是否为空

如何从外部PTR中检查外部PTR是否为空,r,swig,R,Swig,我使用SWIG生成包装器代码,以便从R语言中访问C代码。包装器代码使用Rexternalptr类型保存对C指针的引用。在某些情况下,这些指针在C端是空的,在R中显示为nil值。在R端,在externalptr上调用is.null()和is.na()都返回FALSE。例如: > val = librdf_query_results_get_binding_value(results, 2) > val An object of class "_p_librdf_node_s" Slot

我使用SWIG生成包装器代码,以便从R语言中访问C代码。包装器代码使用R
externalptr
类型保存对C指针的引用。在某些情况下,这些指针在C端是空的,在R中显示为nil值。在R端,在
externalptr
上调用
is.null()
is.na()
都返回
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
val=librdf\u查询\u结果\u获取\u绑定\u值(结果,2) >瓦尔 类为“\p\u librdf\u node\u s”的对象 插槽“参考”: >阶级(val@ref) [1] “外部PTR” >is.null(val@ref) [1] 假的 >是的(val@ref) [1] 假的 从上面的代码输出可以看出,
ref
插槽包含一个
externalptr
,即“nil”。如何从R中确定C中的这个指针为NULL

如果要在上下文中查看代码,可以在GitHub中找到:

为了完整起见,这里是我使用的解决方案。正如@DirkEddelbuettel所建议的那样,它需要一个C端函数,一个R端函数。C函数是:

#include <Rinternals.h>

SEXP isnull(SEXP pointer) {
  return ScalarLogical(!R_ExternalPtrAddr(pointer));
}
#包括
SEXP为空(SEXP指针){
返回ScalarLogical(!R_ExternalPtrAddr(指针));
}
R中的包装函数是:

is.null.externalptr <- function(pointer) {
  stopifnot(is(pointer, "externalptr"))
  .Call("isnull", pointer)
}
is.null.externalptr p
>is.null.externalptr(p)
[1] 真的

上面的
C
解决方案是最优雅的,但编译器可能并不总是可用的。不需要编译代码的解决方案可以是:

identical(pointer, new("externalptr"))
但是,如果对象具有自定义属性,则这将不起作用。如果是这种情况,您可以执行以下操作:

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

isnull我认为您可能需要一个C/C++帮助函数来为您计算外部指针。我认为@DirkEddelbuettel是正确的。您可能想考虑<代码> BigMealth::I.NIL<代码>作为指南。谢谢DirkEddelbuettel,我怀疑很多。那么您认为对
externalptr
类型重写is.null()是合理的,还是最好将其放在我自己的包中?
isnull <- function(pointer){
  a <- attributes(pointer)
  attributes(pointer) <- NULL
  out <- identical(pointer, new("externalptr"))
  attributes(pointer) <- a
  return(out)
}