@@ -404,6 +404,13 @@ compileAttributes <- function(pkgdir = ".", verbose = getOption("verbose")) {
404404 depends <- unique(.splitDepends(depends ))
405405 depends <- depends [depends != " R" ]
406406
407+ # check the NAMESPACE file to see if dynamic registration is enabled
408+ namespaceFile <- file.path(pkgdir , " NAMESPACE" )
409+ if (! file.exists(namespaceFile ))
410+ stop(" pkgdir must refer to the directory containing an R package" )
411+ pkgNamespace <- readLines(namespaceFile , warn = FALSE )
412+ registration <- any(grepl(" ^\\ s*useDynLib.*\\ .registration\\ s*=\\ s*TRUE.*$" , pkgNamespace ))
413+
407414 # determine source directory
408415 srcDir <- file.path(pkgdir , " src" )
409416 if (! file.exists(srcDir ))
@@ -415,7 +422,7 @@ compileAttributes <- function(pkgdir = ".", verbose = getOption("verbose")) {
415422 dir.create(rDir )
416423
417424 # get a list of all source files
418- cppFiles <- list.files(srcDir , pattern = " \\ .((c(c|pp))|(h(pp)?))$" )
425+ cppFiles <- list.files(srcDir , pattern = " \\ .((c(c|pp)? )|(h(pp)?))$" )
419426
420427 # derive base names (will be used for modules)
421428 cppFileBasenames <- tools :: file_path_sans_ext(cppFiles )
@@ -449,7 +456,7 @@ compileAttributes <- function(pkgdir = ".", verbose = getOption("verbose")) {
449456
450457 # generate exports
451458 invisible (.Call(" compileAttributes" , PACKAGE = " Rcpp" ,
452- pkgdir , pkgname , depends , cppFiles , cppFileBasenames ,
459+ pkgdir , pkgname , depends , registration , cppFiles , cppFileBasenames ,
453460 includes , verbose , .Platform ))
454461}
455462
@@ -1147,3 +1154,43 @@ sourceCppFunction <- function(func, isVoid, dll, symbol) {
11471154 as.character(token )
11481155}
11491156
1157+ .extraRoutineRegistrations <- function (routines ) {
1158+
1159+ declarations = character ()
1160+ call_entries = character ()
1161+
1162+ # if we are running R 3.4 or higher we can use an internal utility function
1163+ # to automatically discover additional native routines that require registration
1164+ if (getRversion() > = " 3.4" ) {
1165+
1166+ # get the generated code from R
1167+ con <- textConnection(object = NULL , open = " w" )
1168+ on.exit(close(con ), add = TRUE )
1169+ tools :: package_native_routine_registration_skeleton(
1170+ dir = " ." ,
1171+ con = con ,
1172+ character_only = FALSE
1173+ )
1174+ code <- textConnectionValue(con )
1175+
1176+ # look for lines containing call entries
1177+ matches <- regexec(' ^\\ s+\\ {"([^"]+)",.*$' , code )
1178+ matches <- regmatches(code , matches )
1179+ matches <- Filter(x = matches , function (x ) {
1180+ length(x ) > 0
1181+ })
1182+ for (match in matches ) {
1183+ routine <- match [[2 ]]
1184+ if (! routine %in% routines ) {
1185+ declaration <- grep(sprintf(" ^extern .* %s\\ (.*$" , routine ), code ,
1186+ value = TRUE )
1187+ declarations <- c(declarations , sub(" ^extern" , " RcppExport" , declaration ))
1188+ call_entries <- c(call_entries , match [[1 ]])
1189+ }
1190+ }
1191+ }
1192+
1193+ # return extra declaratiosn and call entries
1194+ list (declarations = declarations ,
1195+ call_entries = call_entries )
1196+ }
0 commit comments