Skip to content

Instantly share code, notes, and snippets.

@Sleepingwell
Created November 3, 2014 03:50
Show Gist options
  • Save Sleepingwell/8588c5ee844ce0242d05 to your computer and use it in GitHub Desktop.
Save Sleepingwell/8588c5ee844ce0242d05 to your computer and use it in GitHub Desktop.
Holding a large number of SEXPs in C++
#include <vector>
#include <utility>
#include <iterator>
#include <R.h>
#include <Rdefines.h>
template<typename Iter>
SEXP makePolygon(Iter b, Iter e) {
SEXP
coords;
double
*xi,
*yi;
size_t
n(static_cast<size_t>(std::distance(b, e)));
PROTECT(coords = allocMatrix(REALSXP, n, 2));
xi = REAL(coords);
yi = xi + n;
for(; b!=e; ++b, ++xi, ++yi) {
*xi = b->first;
*yi = b->second;
}
// make call to Polygon_c to make the polygon here in practice,
// but just return the matrix for this little example
UNPROTECT(1);
return coords;
}
SEXP makePolygonsFromPairList(SEXP pairList) {
// make call to Polygons_c to make the polygons here in practice,
// but just return the list of 'polygons' for this little example.
return coerceVector(pairList, VECSXP);
}
struct PolyHolder {
PolyHolder(void) {
PROTECT_WITH_INDEX(currentRegion = R_NilValue, &icr);
PROTECT_WITH_INDEX(regions = R_NilValue, &ir);
}
~PolyHolder(void) {
UNPROTECT(2);
}
void notifyEndRegion(void) {
REPROTECT(regions = CONS(makePolygonsFromPairList(currentRegion), regions), ir);
REPROTECT(currentRegion = R_NilValue, icr);
}
template<typename Iter>
void addSubPolygon(Iter b, Iter e) {
REPROTECT(currentRegion = CONS(makePolygon(b, e), currentRegion), icr);
}
SEXP getPolygons(void) {
return regions;
}
private:
PROTECT_INDEX
ir,
icr;
SEXP
currentRegion,
regions;
};
// The function to be used by .Call
// A silly little example that creates two 'regions', each
// of which contains two copies of the same polygon.
extern "C" SEXP testPolyHolder() {
typedef std::pair<double, double> Point;
typedef std::vector<Point> Polygon;
Polygon
p(5);
PolyHolder
ph;
// a unit square with lower left at origin
p[0] = p[4] = Point(0.0, 0.0);
p[1] = Point(0.0, 1.0);
p[2] = Point(1.0, 1.0);
p[3] = Point(1.0, 0.0);
for(int i(0); i<2; ++i) {
for(int j(0); j<2; ++j) {
ph.addSubPolygon(p.begin(), p.end());
}
ph.notifyEndRegion();
}
return ph.getPolygons();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment