[Rcpp-commits] r4086 - in pkg/Rcpp: . R inst src
noreply at r-forge.r-project.org
noreply at r-forge.r-project.org
Wed Dec 5 20:50:11 CET 2012
Author: jjallaire
Date: 2012-12-05 20:50:11 +0100 (Wed, 05 Dec 2012)
New Revision: 4086
Modified:
pkg/Rcpp/ChangeLog
pkg/Rcpp/R/Attributes.R
pkg/Rcpp/TODO
pkg/Rcpp/inst/NEWS.Rd
pkg/Rcpp/src/Attributes.cpp
pkg/Rcpp/src/AttributesGen.cpp
pkg/Rcpp/src/AttributesGen.h
Log:
direct hookup of external ptr in sourceCpp
Modified: pkg/Rcpp/ChangeLog
===================================================================
--- pkg/Rcpp/ChangeLog 2012-12-05 19:22:07 UTC (rev 4085)
+++ pkg/Rcpp/ChangeLog 2012-12-05 19:50:11 UTC (rev 4086)
@@ -10,9 +10,13 @@
2012-12-05 JJ Allaire <jj at rstudio.org>
- * src/Attributes.cpp: use code generation for compileAttributes
- * src/AttributesGen.cpp: use code generation for compileAttributes
- * src/AttributesGen.h: use code generation for compileAttributes
+ * src/Attributes.R: direct hookup of external ptr in sourceCpp
+ * src/Attributes.cpp: use code generation for compileAttributes;
+ direct hookup of external ptr in sourceCpp
+ * src/AttributesGen.cpp: use code generation for compileAttributes;
+ direct hookup of external ptr in sourceCpp
+ * src/AttributesGen.h: use code generation for compileAttributes;
+ direct hookup of external ptr in sourceCpp
* src/Module.cpp: fix typo in GetCppCallable
2012-12-04 Dirk Eddelbuettel <edd at debian.org>
Modified: pkg/Rcpp/R/Attributes.R
===================================================================
--- pkg/Rcpp/R/Attributes.R 2012-12-05 19:22:07 UTC (rev 4085)
+++ pkg/Rcpp/R/Attributes.R 2012-12-05 19:50:11 UTC (rev 4086)
@@ -304,6 +304,25 @@
}
+# Take an empty function body and connect it to the specified external symbol
+sourceCppFunction <- function(func, dll, symbol) {
+
+ args <- names(formals(func))
+
+ body <- quote( .Call( EXTERNALNAME, ARG ) )[ c(1:2, rep(3, length(args))) ]
+
+ for (i in seq(along = args))
+ body[[i+2]] <- as.symbol(args[i])
+
+ body[[1L]] <- .Call
+ body[[2L]] <- getNativeSymbolInfo(symbol, dll)$address
+
+ body(func) <- body
+
+ func
+}
+
+
# Print verbose output
.printVerboseOutput <- function(context) {
Modified: pkg/Rcpp/TODO
===================================================================
--- pkg/Rcpp/TODO 2012-12-05 19:22:07 UTC (rev 4085)
+++ pkg/Rcpp/TODO 2012-12-05 19:50:11 UTC (rev 4086)
@@ -93,7 +93,7 @@
o Add unit tests
- o Add docstring parameter to Rcpp::export attribute
+ o Evaluate whether to do anything with RNGScope
o Rcpp.package.skeleton should look for Rcpp::depends in cpp_files
and call inline plugins, etc. as necessary to create a package
Modified: pkg/Rcpp/inst/NEWS.Rd
===================================================================
--- pkg/Rcpp/inst/NEWS.Rd 2012-12-05 19:22:07 UTC (rev 4085)
+++ pkg/Rcpp/inst/NEWS.Rd 2012-12-05 19:50:11 UTC (rev 4086)
@@ -29,6 +29,8 @@
\code{sourceCpp} and \code{compileAttributes} (eliminates
problem with exceptions not being able to cross shared library
boundaries on Windows)
+ \item Functions exported by \code{sourceCpp} now directly
+ hookup to the external symbol pointer
}
}
}
Modified: pkg/Rcpp/src/Attributes.cpp
===================================================================
--- pkg/Rcpp/src/Attributes.cpp 2012-12-05 19:22:07 UTC (rev 4085)
+++ pkg/Rcpp/src/Attributes.cpp 2012-12-05 19:50:11 UTC (rev 4086)
@@ -219,12 +219,19 @@
std::ofstream::out | std::ofstream::trunc);
if (rOfs.fail())
throw Rcpp::file_io_error(generatedRSourcePath());
+
// DLLInfo - hide using . and ensure uniqueness using contextId
std::string dllInfo = "`." + contextId_ + "_DLLInfo`";
rOfs << dllInfo << " <- dyn.load('" << dynlibPath() << "')"
<< std::endl << std::endl;
+
// Generate R functions
- generateRFunctions(rOfs, sourceAttributes, contextId_, dllInfo);
+ generateR(rOfs, sourceAttributes, dllInfo);
+
+ // remove the DLLInfo
+ rOfs << std::endl << "rm(" << dllInfo << ")"
+ << std::endl;
+
rOfs.close();
// discover exported functions, and dependencies
@@ -295,6 +302,31 @@
return buildDirectory_ + fileSep_ + rSourceFilename();
}
+ void generateR(std::ostream& ostr,
+ const SourceFileAttributes& attributes,
+ const std::string& dllInfo) const
+ {
+ // process each attribute
+ for(std::vector<Attribute>::const_iterator
+ it = attributes.begin(); it != attributes.end(); ++it) {
+
+ // alias the attribute and function (bail if not export)
+ const Attribute& attribute = *it;
+ if (!attribute.isExportedFunction())
+ continue;
+ const Function& function = attribute.function();
+
+ // export the function
+ ostr << attribute.exportedName()
+ << " <- Rcpp:::sourceCppFunction("
+ << "function(" << generateRArgList(function) << ") {}, "
+ << dllInfo << ", "
+ << "'" << contextId_ + "_" + function.name()
+ << "')" << std::endl;
+ }
+
+ }
+
private:
std::string cppSourcePath_;
std::string generatedCpp_;
Modified: pkg/Rcpp/src/AttributesGen.cpp
===================================================================
--- pkg/Rcpp/src/AttributesGen.cpp 2012-12-05 19:22:07 UTC (rev 4085)
+++ pkg/Rcpp/src/AttributesGen.cpp 2012-12-05 19:50:11 UTC (rev 4086)
@@ -481,12 +481,51 @@
}
void RExportsGenerator::doWriteFunctions(
- const SourceFileAttributes& attributes,
- bool verbose) {
- if (attributes.hasInterface(kInterfaceR)) {
+ const SourceFileAttributes& attributes,
+ bool verbose) {
+
+ if (attributes.hasInterface(kInterfaceR)) {
+ // process each attribute
+ for(std::vector<Attribute>::const_iterator
+ it = attributes.begin(); it != attributes.end(); ++it) {
+
+ // alias the attribute and function (bail if not export)
+ const Attribute& attribute = *it;
+ if (!attribute.isExportedFunction())
+ continue;
+ const Function& function = attribute.function();
+
+ // print roxygen lines
+ for (size_t i=0; i<attribute.roxygen().size(); i++)
+ ostr() << attribute.roxygen()[i] << std::endl;
+
+ // build the parameter list
+ std::string args = generateRArgList(function);
+
+ // determine the function name
+ std::string name = attribute.exportedName();
+
+ // write the function
+ ostr() << name << " <- function(" << args << ") {"
+ << std::endl;
+ ostr() << " ";
+ if (function.type().isVoid())
+ ostr() << "invisible(";
+ ostr() << ".Call(";
+ ostr() << "'" << package() << "_" << function.name() << "', "
+ << "PACKAGE = '" << package() << "'";
+
+ // add arguments
+ const std::vector<Argument>& arguments = function.arguments();
+ for (size_t i = 0; i<arguments.size(); i++)
+ ostr() << ", " << arguments[i].name();
+ ostr() << ")";
+ if (function.type().isVoid())
+ ostr() << ")";
+ ostr() << std::endl;
- // generate R functions
- generateRFunctions(ostr(), attributes, package());
+ ostr() << "}" << std::endl << std::endl;
+ }
}
}
@@ -689,10 +728,35 @@
// couldn't parse the arg
return std::string();
}
-
+
} // anonymous namespace
+
+ // Generate an R argument list for a function
+ std::string generateRArgList(const Function& function) {
+ std::ostringstream argsOstr;
+ const std::vector<Argument>& arguments = function.arguments();
+ for (size_t i = 0; i<arguments.size(); i++) {
+ const Argument& argument = arguments[i];
+ argsOstr << argument.name();
+ if (!argument.defaultValue().empty()) {
+ std::string rArg = cppArgToRArg(argument.type().name(),
+ argument.defaultValue());
+ if (!rArg.empty()) {
+ argsOstr << " = " << rArg;
+ } else {
+ showWarning("Unable to parse C++ default value '" +
+ argument.defaultValue() + "' for argument "+
+ argument.name() + " of function " +
+ function.name());
+ }
+ }
+
+ if (i != (arguments.size()-1))
+ argsOstr << ", ";
+ }
+ return argsOstr.str();
+ }
-
// Generate the C++ code required to make [[Rcpp::export]] functions
// available as C symbols with SEXP parameters and return
void generateCpp(std::ostream& ostr,
@@ -760,87 +824,6 @@
ostr << "}" << std::endl;
}
}
-
- // Generate R functions from the passed attributes
- void generateRFunctions(std::ostream& ostr,
- const SourceFileAttributes& attributes,
- const std::string& contextId,
- const std::string& dllInfo) {
-
- // process each attribute
- for(std::vector<Attribute>::const_iterator
- it = attributes.begin(); it != attributes.end(); ++it) {
-
- // alias the attribute and function (bail if not export)
- const Attribute& attribute = *it;
- if (!attribute.isExportedFunction())
- continue;
- const Function& function = attribute.function();
-
- // print roxygen lines
- for (size_t i=0; i<attribute.roxygen().size(); i++)
- ostr << attribute.roxygen()[i] << std::endl;
-
- // build the parameter list
- std::ostringstream argsOstr;
- const std::vector<Argument>& arguments = function.arguments();
- for (size_t i = 0; i<arguments.size(); i++) {
- const Argument& argument = arguments[i];
- argsOstr << argument.name();
- if (!argument.defaultValue().empty()) {
- std::string rArg = cppArgToRArg(argument.type().name(),
- argument.defaultValue());
- if (!rArg.empty()) {
- argsOstr << " = " << rArg;
- } else {
- showWarning("Unable to parse C++ default value '" +
- argument.defaultValue() + "' for argument "+
- argument.name() + " of function " +
- function.name());
- }
- }
-
- if (i != (arguments.size()-1))
- argsOstr << ", ";
- }
- std::string args = argsOstr.str();
-
- // determine the function name
- std::string name = attribute.exportedName();
-
- // write the function - use contextId to ensure symbol uniqueness
- ostr << name << " <- function(" << args << ") {"
- << std::endl;
- ostr << " ";
- if (function.type().isVoid())
- ostr << "invisible(";
- ostr << ".Call(";
-
- // Two .Call styles are suppported -- if dllInfo is provided then
- // do a direct call to getNativeSymbolInfo; otherwise we assume that
- // the contextId is a package name and use the PACKAGE argument
- if (!dllInfo.empty()) {
- ostr << "getNativeSymbolInfo('"
- << contextId << "_" << function.name()
- << "', " << dllInfo << ")";
- }
- else {
- ostr << "'" << contextId << "_" << function.name() << "', "
- << "PACKAGE = '" << contextId << "'";
- }
-
- // add arguments
- for (size_t i = 0; i<arguments.size(); i++)
- ostr << ", " << arguments[i].name();
- ostr << ")";
- if (function.type().isVoid())
- ostr << ")";
- ostr << std::endl;
-
- ostr << "}" << std::endl << std::endl;
- }
- }
-
} // namespace attributes
} // namespace Rcpp
Modified: pkg/Rcpp/src/AttributesGen.h
===================================================================
--- pkg/Rcpp/src/AttributesGen.h 2012-12-05 19:22:07 UTC (rev 4085)
+++ pkg/Rcpp/src/AttributesGen.h 2012-12-05 19:50:11 UTC (rev 4086)
@@ -238,16 +238,13 @@
// Standalone generation helpers (used by sourceCpp)
+ std::string generateRArgList(const Function& function);
+
void generateCpp(std::ostream& ostr,
const SourceFileAttributes& attributes,
bool includePrototype,
const std::string& contextId);
-
- void generateRFunctions(std::ostream& ostr,
- const SourceFileAttributes& attributes,
- const std::string& contextId,
- const std::string& dllInfo = std::string());
-
+
} // namespace attributes
} // namespace Rcpp
More information about the Rcpp-commits
mailing list