Skip to content

Commit 6eeef10

Browse files
committed
Revised version of setRcppClass and new function loadModule. Designed (and now succeeding most of the time) to allow R classes to extend
C++ Classes in modules. Also no longer requires packages to insert code into .onLoad(); the load actions added to R in 2.15.0 are used. (For that reason, these features require at least that version; OTOH setRcppClass never worked before.)
1 parent c009746 commit 6eeef10

24 files changed

+818
-159
lines changed

DESCRIPTION

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ Description: The Rcpp package provides R functions as well as a C++ library
3838
been factored out of Rcpp into the package RcppClassic, and it is still
3939
available for code relying on the older interface. New development should
4040
use alwayse use this Rcpp package instead.
41-
Depends: R (>= 2.12.0), methods
41+
Depends: R (>= 2.12.0)
42+
Imports: methods
4243
Suggests: RUnit, inline, rbenchmark
4344
URL: http://dirk.eddelbuettel.com/code/rcpp.html, http://romainfrancois.blog.free.fr/index.php?category/R-package/Rcpp
4445
License: GPL (>= 2)

NAMESPACE

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ S3method( .DollarNames, "Module" )
1515
exportMethods( prompt, show, .DollarNames, initialize, "formals<-" )
1616

1717
export(
18-
Module, Rcpp.package.skeleton, populate, loadRcppModules, setRcppClass
18+
Module, Rcpp.package.skeleton, populate, loadRcppModules, setRcppClass,
19+
loadModule
1920
)
2021

2122
exportClass(RcppClass)

R/Module.R

Lines changed: 49 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ setMethod("initialize", "Module",
5656
moduleName = "UNKNOWN",
5757
packageName = "",
5858
pointer = .badModulePointer, ...) {
59-
env <- new.env(TRUE, emptyenv())
59+
env <- new.env(TRUE, emptyenv())
6060
as(.Object, "environment") <- env
6161
assign("pointer", pointer, envir = env)
6262
assign("packageName", packageName, envir = env)
@@ -79,12 +79,12 @@ setMethod("initialize", "Module",
7979
body(f) <- if( info[[2]] ) {
8080
substitute( {
8181
.External( InternalFunction_invoke, fun_pointer, ... )
82-
invisible(NULL)
83-
}, stuff )
82+
invisible(NULL)
83+
}, stuff )
8484
} else {
8585
substitute( {
8686
.External( InternalFunction_invoke, fun_pointer, ... )
87-
}, stuff )
87+
}, stuff )
8888
}
8989
out <- new( "C++Function", f, pointer = fun_ptr, docstring = doc, signature = sign )
9090
if( ! is.null( formal_args ) ){
@@ -98,11 +98,11 @@ setMethod("initialize", "Module",
9898
value@generator <- get("refClassGenerators",envir=x)[[as.character(value)]]
9999
value
100100
}
101-
101+
102102
setMethod( "$", "Module", function(x, name){
103103
pointer <- .getModulePointer(x)
104104
storage <- get( "storage", envir = as.environment(x) )
105-
storage[[ name ]]
105+
storage[[ name ]]
106106
} )
107107

108108
new_CppObject_xp <- function(module, pointer, ...) {
@@ -136,16 +136,16 @@ cpp_object_dummy <- function(.self, .refClassDef) {
136136
assign(".pointer", pointer, envir = selfEnv)
137137
assign(".cppclass", fields$.pointer, envir = selfEnv)
138138
.self
139-
}
139+
}
140140

141141
cpp_object_maker <- function(typeid, pointer){
142142
Class <- Rcpp:::.classes_map[[ typeid ]]
143143
new( Class, .object_pointer = pointer )
144144
}
145145

146-
Module <- function( module, PACKAGE = getPackageName(where), where = topenv(parent.frame()), mustStart = FALSE ) {
147-
if(is(module, "DLLInfo") && missing(mustStart)) mustStart <- TRUE
148-
if(is(module, "Module")) {
146+
Module <- function( module, PACKAGE = methods::getPackageName(where), where = topenv(parent.frame()), mustStart = FALSE ) {
147+
if(inherits(module, "DLLInfo") && missing(mustStart)) mustStart <- TRUE
148+
if(inherits(module, "Module")) {
149149
xp <- .getModulePointer(module, FALSE)
150150
if(!missing(PACKAGE))
151151
warning("ignoring PACKAGE argument in favor of internal package from Module object")
@@ -164,20 +164,20 @@ Module <- function( module, PACKAGE = getPackageName(where), where = topenv(pare
164164
## and just check whether it's been reset from that (bad) value
165165
xp <- module
166166
moduleName <- .Call( Module__name, xp )
167-
module <- new("Module", pointer = xp, packageName = PACKAGE,
167+
module <- methods::new("Module", pointer = xp, packageName = PACKAGE,
168168
moduleName = moduleName)
169-
} else if(is(module, "character")) {
169+
} else if(is.character(module)) {
170170
moduleName <- module
171171
xp <- .badModulePointer
172-
module <- new("Module", pointer = xp, packageName = PACKAGE,
172+
module <- methods::new("Module", pointer = xp, packageName = PACKAGE,
173173
moduleName = moduleName)
174174
}
175175
if(identical(xp, .badModulePointer)) {
176176
if(mustStart) {
177177
name <- sprintf( "_rcpp_module_boot_%s", moduleName )
178178
symbol <- tryCatch(getNativeSymbolInfo( name, PACKAGE ),
179179
error = function(e)e)
180-
if(is(symbol, "error"))
180+
if(inherits(symbol, "error"))
181181
stop(gettextf("Failed to initialize module pointer: %s",
182182
symbol), domain = NA)
183183
xp <- .Call( symbol )
@@ -194,17 +194,17 @@ Module <- function( module, PACKAGE = getPackageName(where), where = topenv(pare
194194
if(environmentIsLocked(where))
195195
where <- .GlobalEnv # or???
196196
generators <- list()
197-
197+
198198
storage <- new.env()
199-
199+
200200
for( i in seq_along(classes) ){
201201
CLASS <- classes[[i]]
202-
202+
203203
clname <- as.character(CLASS)
204204

205205
fields <- cpp_fields( CLASS, where )
206206
methods <- cpp_refMethods(CLASS, where)
207-
generator <- setRefClass( clname,
207+
generator <- methods::setRefClass( clname,
208208
fields = fields,
209209
contains = "C++Object",
210210
methods = methods,
@@ -221,54 +221,54 @@ Module <- function( module, PACKAGE = getPackageName(where), where = topenv(pare
221221
else Rcpp:::cpp_object_dummy(.self, .refClassDef)
222222
}
223223
)
224-
224+
225225
rm( .self, .refClassDef )
226-
227-
classDef <- getClass(clname)
226+
227+
classDef <- methods:::getClass(clname)
228228
## non-public (static) fields in class representation
229229
## <fixme> Should these become real fields? </fixme>
230230
fields <- classDef@fieldPrototypes
231231
assign(".pointer", CLASS@pointer, envir = fields)
232232
assign(".module", xp, envir = fields)
233233
assign(".CppClassName", clname, envir = fields)
234234
generators[[clname]] <- generator
235-
235+
236236
# [romain] : should this be promoted to reference classes
237237
# perhaps with better handling of j and ... arguments
238238
if( any( grepl( "^[[]", names(CLASS@methods) ) ) ){
239239
if( "[[" %in% names( CLASS@methods ) ){
240-
setMethod( "[[", clname, function(x, i, j, ..., exact = TRUE){
240+
methods::setMethod( "[[", clname, function(x, i, j, ..., exact = TRUE){
241241
x$`[[`( i )
242242
}, where = where )
243243
}
244-
244+
245245
if( "[[<-" %in% names( CLASS@methods ) ){
246-
setReplaceMethod( "[[", clname, function(x, i, j, ..., exact = TRUE, value){
246+
methods::setReplaceMethod( "[[", clname, function(x, i, j, ..., exact = TRUE, value){
247247
x$`[[<-`( i, value )
248248
x
249249
} , where = where )
250250
}
251-
251+
252252
}
253-
253+
254254
}
255255
if(length(classes)) {
256256
module$refClassGenerators <- generators
257257
}
258-
258+
259259
for( i in seq_along(classes) ){
260260
CLASS <- classes[[i]]
261261
clname <- as.character(CLASS)
262262
demangled_name <- sub( "^Rcpp_", "", clname )
263263
.classes_map[[ CLASS@typeid ]] <- storage[[ demangled_name ]] <- .get_Module_Class( module, demangled_name, xp )
264264
}
265-
265+
266266
# functions
267267
functions <- .Call( Module__functions_names, xp )
268268
for( fun in functions ){
269269
storage[[ fun ]] <- .get_Module_function( module, fun, xp )
270270
}
271-
271+
272272
assign( "storage", storage, envir = as.environment(module) )
273273
module
274274
}
@@ -277,37 +277,37 @@ dealWith <- function( x ) if(isTRUE(x[[1]])) invisible(NULL) else x[[2]]
277277

278278
method_wrapper <- function( METHOD, where ){
279279
f <- function(...) NULL
280-
280+
281281
stuff <- list(
282282
class_pointer = METHOD$class_pointer,
283283
pointer = METHOD$pointer,
284284
CppMethod__invoke = CppMethod__invoke,
285285
CppMethod__invoke_void = CppMethod__invoke_void,
286286
CppMethod__invoke_notvoid = CppMethod__invoke_notvoid,
287-
dealWith = dealWith,
287+
dealWith = dealWith,
288288
docstring = METHOD$info("")
289289
)
290-
290+
291291
extCall <- if( all( METHOD$void ) ){
292292
# all methods are void, so we know we want to return invisible(NULL)
293-
substitute(
293+
substitute(
294294
{
295295
docstring
296296
.External(CppMethod__invoke_void, class_pointer, pointer, .pointer, ...)
297297
invisible(NULL)
298298
} , stuff )
299299
} else if( all( ! METHOD$void ) ){
300-
# none of the methods are void so we always return the result of
300+
# none of the methods are void so we always return the result of
301301
# .External
302-
substitute(
302+
substitute(
303303
{
304304
docstring
305305
.External(CppMethod__invoke_notvoid, class_pointer, pointer, .pointer, ...)
306306
} , stuff )
307307
} else {
308-
# some are void, some are not, so the voidness is part of the result
308+
# some are void, some are not, so the voidness is part of the result
309309
# we get from internally and we need to deal with it
310-
substitute(
310+
substitute(
311311
{
312312
docstring
313313
dealWith( .External(CppMethod__invoke, class_pointer, pointer, .pointer, ...) )
@@ -319,17 +319,17 @@ method_wrapper <- function( METHOD, where ){
319319
## create a named list of the R methods to invoke C++ methods
320320
## from the C++ class with pointer xp
321321
cpp_refMethods <- function(CLASS, where) {
322-
finalizer <- eval( substitute(
322+
finalizer <- eval( substitute(
323323
function(){
324324
.Call( CppObject__finalize, class_pointer , .pointer )
325-
},
326-
list(
327-
CLASS = CLASS@pointer,
328-
CppObject__finalize = CppObject__finalize,
325+
},
326+
list(
327+
CLASS = CLASS@pointer,
328+
CppObject__finalize = CppObject__finalize,
329329
class_pointer = CLASS@pointer
330330
)
331331
) )
332-
mets <- c(
332+
mets <- c(
333333
sapply( CLASS@methods, method_wrapper, where = where ),
334334
"finalize" = finalizer
335335
)
@@ -348,14 +348,16 @@ binding_maker <- function( FIELD, where ){
348348
else
349349
.Call( CppField__set, class_pointer, pointer, .pointer, x)
350350
}, list(class_pointer = FIELD$class_pointer,
351-
pointer = FIELD$pointer,
352-
CppField__get = CppField__get,
351+
pointer = FIELD$pointer,
352+
CppField__get = CppField__get,
353353
CppField__set = CppField__set ))
354354
environment(f) <- where
355355
f
356356
}
357-
357+
358358
cpp_fields <- function( CLASS, where){
359359
sapply( CLASS@fields, binding_maker, where = where )
360360
}
361361

362+
.CppClassName <- function(name)
363+
paste0("Rcpp_",name)

0 commit comments

Comments
 (0)