Skip to content

[Rcpp-devel] Passing a pointer to a class via modules

3 messages · Ege Rubak, Dirk Eddelbuettel

#
Hi,

I'm making an R interface to Google's s2 library for geometry on the 
sphere via Rcpp Modules. In general Modules is great for this since it 
allows me to expose a lot of classes and functions without much C++ 
experience.

Now I have encountered a problem which I would be grateful for help on.

Context: A S2Polygon is a region on the sphere consisting of one or more 
loops (of class S2Loop) which may represent e.g. landmass and lakes.

I have successfully exposed these classes using RCPP_EXPOSED_CLASS, and 
everything appears to work, but then at some later point when I try to 
access the loop in the polygon I suddenly get segfaults like:
  *** caught segfault ***
address 0x111, cause 'memory not mapped'
An irrecoverable exception occurred. R is aborting now ...

I think that this happens because the S2Polygon doesn't contain the 
loops that it is made up from but only pointers to these, and it appears 
that when I pass a S2Loop to the S2Polygon (through a S2PolygonBuilder) 
a new copy of the loop is made in C++ land and the S2Polygon points to 
this copy (and I guess eventually it is destroyed since it isn't 
protected by R).

I can construct a S2Loop from a data.frame of (lng,lat)s:
```r
library(s2) ## Version from github.com/spatstat/s2  -- not CRAN!
template <- data.frame(lng = c(1,-1,-1,1), lat = c(1,1,-1,-1))
s2loop <- S2Loop$new(template)
```

Then a S2Polygon can be constructed using a builder like this:
```r
pb <- S2PolygonBuilder$new(S2PolygonBuilderOptions$new())
pb$AddLoop(s2loop)
p <- S2Polygon$new()
unused_edges <- 0
pb$AssemblePolygon(p, unused_edges)
```

The polygon `p` now has a single loop, but this loop is not pointing to 
the one in R as I see output like:
```r
s2loop
## C++ object <0x23c9620> of class 'S2Loop' <0x27a80d0>
p$loop(0)
## C++ object <0xe8a9c0> of class 'S2Loop' <0x27a80d0>
```

In s2polygonbuilder.h the member function AddLoop(S2Loop const* loop) 
doesn't take ownership over the loop according to the source code comment:
https://github.com/spatstat/s2/blob/master/src/geometry/s2/s2polygonbuilder.h#L192-L193

Do you think I have the correct understanding of the problem?
And more importantly do you see a way to fix it? (Which is an 
non-intrusive as possible, since I try to modify the source code as 
little as possible.)

At the bottom of this email is a short script creating a bigger polygon 
from many loops and then accessing the loops, which consistently 
triggers the segfault for me in case it has any interest (probably not 
since it takes several minutes to just install the library from GitHub, 
so I don't expect anyone to waste time on this).

Kind regards,
Ege

############### segfault.R ###############

```r
library(s2) ## Version from github.com/spatstat/s2  -- not CRAN!

template <- data.frame(lng = c(1,-1,-1,1), lat = c(1,1,-1,-1))
looplist <- lapply(1:80, function(s) s*template)
s2loops <- lapply(looplist, S2Loop$new)

pb <- S2PolygonBuilder$new(S2PolygonBuilderOptions$new())
for(l in s2loops) pb$AddLoop(l)

p <- S2Polygon$new()
unused_edges <- 0
pb$AssemblePolygon(p, unused_edges)

p$loop(0)

for(i in 1:p$num_loops()){
   p$loop(i-1)
}
```

#############################################
2 days later
#
Ege,

That's not a simple question, and I don't really have a good answer.
I fear the best approach may just be to prototype a little, maybe with
and without Rcpp Modules.

Cheers, Dirk
#
Hi Dirk,

Thanks for taking your time to have a look. This was exactly what I 
feared, but I just wanted to check if anybody on the list could spot an 
easy solution. Anyway, I will continue my investigations and work around 
it for now.

Cheers,
Ege
On 02/08/2017 04:45 AM, Dirk Eddelbuettel wrote: