2

I'm using SWIG to generate wrapper code to access C code from within the R language. The wrapper code uses the R externalptr type to hold references to C pointers. In some situations, those pointers are NULL on the C side, which show up in R as a nil value when displayed. On the R side, calling is.null() and is.na() on the externalptr both return FALSE. For example:

> 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

As can be seen from the code output above, the ref slot contains an externalptr, which is "nil". How do I determine from within R that this pointer in C is NULL?

If you want to see the code in context, it is available in GitHub: https://github.com/ropensci/redland-bindings/blob/master/R/redland/inst/tests/test.redland_base.R#L40

3
  • 4
    I think you may need a C/C++ helper function that evaluates the external pointer for you. Commented Oct 31, 2014 at 2:30
  • I think @DirkEddelbuettel is right. You might want to consider bigmemory::is.nil as a guide. Commented Oct 31, 2014 at 2:58
  • Thanks @DirkEddelbuettel, I suspected as much. So do you think that overriding is.null() for the externalptr type would be reasonable, or would it be better to put it in my own package? Commented Oct 31, 2014 at 4:49

2 Answers 2

7

The C solution above is most elegant, but a compiler might not always be available. A solution that does not require compiled code could be something like:

identical(pointer, new("externalptr"))

However this would not work if the object has custom attributes. If this is the case, you could do:

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

Again a bit more involved than the C solution, but will work in a simple script on any platform.

Sign up to request clarification or add additional context in comments.

Comments

4

For completeness, here's the solution I used. It required a function on the C side, and one on the R side, as suggested by @DirkEddelbuettel. The C function is:

#include <Rinternals.h>

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

And the wrapper function in R is:

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

For an example of use from within R:

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.