Index: pkg/R/00classes.R =================================================================== --- pkg/R/00classes.R (revision 0) +++ pkg/R/00classes.R (revision 0) @@ -0,0 +1,91 @@ +# base class of all C++ objects that are wrapped up as external +# pointers +setClass( "C++Object", representation(pointer = "externalptr"), contains = "VIRTUAL" ) +setClass( "C++Class", representation(cppclass="character") ) +setClass( "vector", contains = "C++Object" ) + +# indicates if cppclass is a class known to extend "C++Object" +isCppClass <- function(cppclass){ + subclasses <- getClass("C++Object")@subclasses + for( cl in subclasses ){ + if( identical( cppclass, cl@subClass ) ) return(TRUE) + } + FALSE +} + +CPP <- function( cppclass ){ + if( isCppClass(cppclass) ){ + new( "C++Class", cppclass=cppclass ) + } else{ + stop( sprintf("`%s` is not known as a C++ class", cppclass) ) + } +} + +# creates a routine signature +getRoutineSignature <- function( cppclass, routine, ...){ + + # so that vector gets a valid name + # clname <- gsub( "<", "_lt_", cppclass , fixed = TRUE ) + # clname <- gsub( ">", "_gt_", clname , fixed = TRUE ) + clname <- gsub( "[<>]", "_", cppclass ) + + # we replace "." with "_dot_" so that "as.vector" can be a valid + # C symbol + routine <- gsub( "[.]", "_dot_", routine ) + + dots <- list(...) + if( !length(dots) ){ + sprintf( "%s___%s", clname, routine ) + } else{ + types <- sapply( dots, function(x){ + type <- typeof(x) + if( identical(type, "S4" ) ){ + type <- sprintf( "S4_%s", class(x) ) + } + type + } ) + sprintf( "%s___%s___%s", clname, routine, paste( types, collapse = "__" ) ) + } +} + +setGeneric( "new" ) +setMethod( "new", "C++Class", function(Class, ...){ + # we need to find a constructor that is suitable + # for the ... parameters + # this is achieved by a convention of symbol name in the + # dll where the class is defined + cppclass <- Class@cppclass + clazz <- getClass( cppclass ) + pkg <- clazz@package + + routine <- getRoutineSignature( cppclass, "new", ... ) + xp <- .Call( routine, ..., PACKAGE = pkg ) + new( cppclass, pointer = xp ) +} ) + +setMethod( "$", "C++Object", function(x, name ){ + # TODO: deal with fields + # we need some sort of reflection mechanism + # to query/set the fields of a class + # but for now, let's just do methods + + # methods : + function(...) { + clazz <- class(x) + + # we cook the signature name based on the class + # and the types of the parameters + routine <- getRoutineSignature( clazz, name, ... ) + + # we assume that the routine is in the package where the + # S4 class is defined, it seems silly otherwise + pkg <- getClass(clazz)@package + + # call this routine + res <- .Call( routine , x, ..., PACKAGE = pkg ) + if( is.null(res) ) invisible(NULL) else res + } + +} ) + + Index: pkg/src/vector_int_.cpp =================================================================== --- pkg/src/vector_int_.cpp (revision 0) +++ pkg/src/vector_int_.cpp (revision 0) @@ -0,0 +1,83 @@ +#include "vector_int_.h" + +namespace rcpp{ + + void vector_int____finalizer(SEXP p){ + if( TYPEOF(p) == EXTPTRSXP ){ + std::vector* ptr = (std::vector*) EXTPTR_PTR(p) ; + delete ptr ; + } + } + + SEXP vector_int____new(){ + std::vector *p = new std::vector ; + SEXP ptr = PROTECT(R_MakeExternalPtr( (void*)p , R_NilValue, R_NilValue)); + R_RegisterCFinalizerEx( ptr, vector_int____finalizer , FALSE ) ; + UNPROTECT(1) ; /* ptr */ + return ptr ; + } + + SEXP vector_int____push_back___integer(SEXP x, SEXP p1){ + std::vector *p = (std::vector*)EXTPTR_PTR(R_do_slot( x, Rf_install("pointer") ) ) ; + for( int i=0; ipush_back( INTEGER(p1)[i] ) ; + } + return(R_NilValue) ; + } + + SEXP vector_int____size(SEXP x){ + std::vector *p = (std::vector*)EXTPTR_PTR(R_do_slot( x, Rf_install("pointer") ) ) ; + return Rf_ScalarInteger( p->size() ) ; + } + + SEXP vector_int____capacity(SEXP x){ + std::vector *p = (std::vector*)EXTPTR_PTR(R_do_slot( x, Rf_install("pointer") ) ) ; + return Rf_ScalarInteger( p->capacity() ) ; + } + + SEXP vector_int____max_size(SEXP x){ + std::vector *p = (std::vector*)EXTPTR_PTR(R_do_slot( x, Rf_install("pointer") ) ) ; + return Rf_ScalarInteger( p->max_size() ) ; + } + + SEXP vector_int____resize___integer__integer(SEXP x, SEXP p1, SEXP p2){ + std::vector *p = (std::vector*)EXTPTR_PTR(R_do_slot( x, Rf_install("pointer") ) ) ; + p->resize( INTEGER(p1)[0], INTEGER(p2)[0] ) ; + return R_NilValue ; + } + + SEXP vector_int____resize___integer__integer(SEXP x, SEXP p1){ + std::vector *p = (std::vector*)EXTPTR_PTR(R_do_slot( x, Rf_install("pointer") ) ) ; + p->resize( INTEGER(p1)[0], 0 ) ; + return R_NilValue ; + } + + SEXP vector_int____empty(SEXP x){ + std::vector *p = (std::vector*)EXTPTR_PTR(R_do_slot( x, Rf_install("pointer") ) ) ; + return( Rf_ScalarLogical( p->empty() ) ) ; + } + + SEXP vector_int____clear(SEXP x){ + std::vector *p = (std::vector*)EXTPTR_PTR(R_do_slot( x, Rf_install("pointer") ) ) ; + p->clear() ; + return R_NilValue ; + } + + SEXP vector_int____reserve___integer(SEXP x, SEXP p1){ + std::vector *p = (std::vector*)EXTPTR_PTR(R_do_slot( x, Rf_install("pointer") ) ) ; + p->reserve( INTEGER(p1)[0] ) ; + return R_NilValue ; + } + + SEXP vector_int____assign___integer( SEXP x, SEXP p1){ + std::vector *p = (std::vector*)EXTPTR_PTR(R_do_slot( x, Rf_install("pointer") ) ) ; + p->assign( INTEGER(p1), INTEGER(p1)+LENGTH(p1) ) ; + return R_NilValue ; + } + + SEXP vector_int____as_dot_vector(SEXP x){ + std::vector *p = (std::vector*)EXTPTR_PTR(R_do_slot( x, Rf_install("pointer") ) ) ; + return RcppSexp(*p).asSexp() ; + } + +} Index: pkg/src/vector_int_.h =================================================================== --- pkg/src/vector_int_.h (revision 0) +++ pkg/src/vector_int_.h (revision 0) @@ -0,0 +1,23 @@ +#include "Rcpp.h" + +namespace rcpp{ + + // finalizer + RcppExport void vector_int____finalizer(SEXP); + + // constructors + RcppExport SEXP vector_int____new() ; + + // methods + RcppExport SEXP vector_int____push_back___integer(SEXP, SEXP) ; + RcppExport SEXP vector_int____size(SEXP); + RcppExport SEXP vector_int____capacity(SEXP); + RcppExport SEXP vector_int____max_size(SEXP); + RcppExport SEXP vector_int____resize___integer(SEXP, SEXP); + RcppExport SEXP vector_int____resize___integer__integer(SEXP, SEXP, SEXP); + RcppExport SEXP vector_int____empty(SEXP); + RcppExport SEXP vector_int____clear(SEXP); + RcppExport SEXP vector_int____reserve___integer(SEXP, SEXP); + RcppExport SEXP vector_int____assign___integer(SEXP, SEXP); + RcppExport SEXP vector_int____as_dot_vector(SEXP) ; +} Index: pkg/NAMESPACE =================================================================== --- pkg/NAMESPACE (revision 207) +++ pkg/NAMESPACE (working copy) @@ -11,3 +11,11 @@ exportMethods( setCMethod ) + +importFrom( methods, new ) + +exportMethods( new, "$" ) + +export( CPP ) +exportClasses( "C++Object", "C++Class", "vector" ) +