[Rcpp-commits] r4082 - in pkg/Rcpp: . inst src
noreply at r-forge.r-project.org
noreply at r-forge.r-project.org
Wed Dec 5 18:41:52 CET 2012
Author: jjallaire
Date: 2012-12-05 18:41:52 +0100 (Wed, 05 Dec 2012)
New Revision: 4082
Modified:
pkg/Rcpp/ChangeLog
pkg/Rcpp/inst/NEWS.Rd
pkg/Rcpp/src/Attributes.cpp
pkg/Rcpp/src/AttributesGen.cpp
pkg/Rcpp/src/AttributesGen.h
pkg/Rcpp/src/Module.cpp
Log:
use code generation for compileAttributes
Modified: pkg/Rcpp/ChangeLog
===================================================================
--- pkg/Rcpp/ChangeLog 2012-12-05 04:34:17 UTC (rev 4081)
+++ pkg/Rcpp/ChangeLog 2012-12-05 17:41:52 UTC (rev 4082)
@@ -1,3 +1,10 @@
+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/Module.cpp: fix typo in GetCppCallable
+
2012-12-04 Dirk Eddelbuettel <edd at debian.org>
* inst/include/Rcpp/hash/hash.h: Added include inttypes.h for intptr_t
Modified: pkg/Rcpp/inst/NEWS.Rd
===================================================================
--- pkg/Rcpp/inst/NEWS.Rd 2012-12-05 04:34:17 UTC (rev 4081)
+++ pkg/Rcpp/inst/NEWS.Rd 2012-12-05 17:41:52 UTC (rev 4082)
@@ -23,6 +23,13 @@
\item More efficient version of \code{duplicated} base on \code{IndexHash}
\item More efficient version of \code{self_match} base on \code{IndexHash}
}
+ \item Changes in Rcpp attributes:
+ \itemize{
+ \item Use code generation rather than modules to implement
+ \code{sourceCpp} and \code{compileAttributes} (eliminates
+ problem with exceptions not being able to cross shared library
+ boundaries on Windows)
+ }
}
}
Modified: pkg/Rcpp/src/Attributes.cpp
===================================================================
--- pkg/Rcpp/src/Attributes.cpp 2012-12-05 04:34:17 UTC (rev 4081)
+++ pkg/Rcpp/src/Attributes.cpp 2012-12-05 17:41:52 UTC (rev 4082)
@@ -134,187 +134,6 @@
using namespace Rcpp::attributes;
-// Generator helpers
-namespace {
-
- // Generate the C++ code required to make [[Rcpp::export]] functions
- // available as C symbols with SEXP parameters and return
- std::string generateCpp(const SourceFileAttributes& attributes,
- bool includePrototype,
- const std::string& contextId) {
-
- // source code we will build up
- std::ostringstream ostr;
-
- // 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();
-
- // include prototype if requested
- if (includePrototype) {
- ostr << "// " << function.name() << std::endl;
- ostr << function << ";";
- }
-
- // write the SEXP-based function
- ostr << std::endl << "RcppExport SEXP ";
- if (!contextId.empty())
- ostr << contextId << "_";
- ostr << function.name() << "(";
- const std::vector<Argument>& arguments = function.arguments();
- for (size_t i = 0; i<arguments.size(); i++) {
- const Argument& argument = arguments[i];
- ostr << "SEXP " << argument.name() << "SEXP";
- if (i != (arguments.size()-1))
- ostr << ", ";
- }
- ostr << ") {" << std::endl;
- ostr << "BEGIN_RCPP" << std::endl;
- for (size_t i = 0; i<arguments.size(); i++) {
- const Argument& argument = arguments[i];
-
- // Rcpp::as to c++ type
- ostr << " " << argument.type().name() << " " << argument.name()
- << " = " << "Rcpp::as<" << argument.type().name() << " >("
- << argument.name() << "SEXP);" << std::endl;
- }
-
- ostr << " ";
- if (!function.type().isVoid())
- ostr << function.type() << " result = ";
- ostr << function.name() << "(";
- for (size_t i = 0; i<arguments.size(); i++) {
- const Argument& argument = arguments[i];
- ostr << argument.name();
- if (i != (arguments.size()-1))
- ostr << ", ";
- }
- ostr << ");" << std::endl;
-
- std::string res = function.type().isVoid() ? "R_NilValue" :
- "Rcpp::wrap(result)";
- ostr << " return " << res << ";" << std::endl;
- ostr << "END_RCPP" << std::endl;
- ostr << "}" << std::endl;
- }
-
- return ostr.str();
- }
-
- // Generate R functions from the passed attributes
- std::string generateRFunctions(const SourceFileAttributes& attributes,
- const std::string& contextId,
- const std::string& dllInfo = std::string()) {
-
- // source code we will build up
- std::ostringstream ostr;
-
- // 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;
- }
-
- return ostr.str();
- }
-
- // Generate the R code used to .Call the exported C symbols
- std::string generateR(const SourceFileAttributes& attributes,
- const std::string& contextId,
- const std::string& dynlibPath) {
-
- // source code we will build up
- std::ostringstream ostr;
-
- // DLLInfo - hide using . and ensure uniqueness using contextId
- std::string dllInfo = "`." + contextId + "_DLLInfo`";
- ostr << dllInfo << " <- dyn.load('" << dynlibPath << "')"
- << std::endl << std::endl;
-
- // Generate R functions and return
- ostr << generateRFunctions(attributes, contextId, dllInfo);
- return ostr.str();
- }
-
-
-
-} // anonymous namespace
-
-
-
// Implementation helpers for sourceCppContext
namespace {
@@ -385,7 +204,9 @@
SourceFileAttributesParser sourceAttributes(cppSourcePath_);
// generate cpp for attributes and append them
- generatedCpp_ = generateCpp(sourceAttributes, false, contextId_);
+ std::ostringstream ostr;
+ generateCpp(ostr, sourceAttributes, false, contextId_);
+ generatedCpp_ = ostr.str();
std::ofstream cppOfs(generatedCppSourcePath().c_str(),
std::ofstream::out | std::ofstream::app);
if (cppOfs.fail())
@@ -394,14 +215,16 @@
cppOfs.close();
// generate R for attributes and write it into the build directory
- std::string rCode = generateR(sourceAttributes,
- contextId_,
- dynlibPath());
std::ofstream rOfs(generatedRSourcePath().c_str(),
std::ofstream::out | std::ofstream::trunc);
- if (cppOfs.fail())
+ if (rOfs.fail())
throw Rcpp::file_io_error(generatedRSourcePath());
- rOfs << rCode;
+ // 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);
rOfs.close();
// discover exported functions, and dependencies
Modified: pkg/Rcpp/src/AttributesGen.cpp
===================================================================
--- pkg/Rcpp/src/AttributesGen.cpp 2012-12-05 04:34:17 UTC (rev 4081)
+++ pkg/Rcpp/src/AttributesGen.cpp 2012-12-05 17:41:52 UTC (rev 4082)
@@ -1,726 +1,843 @@
-// -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; indent-tabs-mode: nil; -*-
-//
-// AttributesGen.cpp: Rcpp R/C++ interface class library -- Rcpp attributes
-//
-// Copyright (C) 2012 JJ Allaire, Dirk Eddelbuettel and Romain Francois
-//
-// This file is part of Rcpp.
-//
-// Rcpp is free software: you can redistribute it and/or modify it
-// under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 2 of the License, or
-// (at your option) any later version.
-//
-// Rcpp is distributed in the hope that it will be useful, but
-// WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with Rcpp. If not, see <http://www.gnu.org/licenses/>.
-
-#include "AttributesGen.h"
-#include "AttributesUtil.h"
-#include "AttributesTypes.h"
-
-#include <fstream>
-
-#include <Rcpp/iostream/Rostream.h>
-
-namespace Rcpp {
-namespace attributes {
-
- namespace {
- const char * const kRcppExportsSuffix = "_RcppExports.h";
-
- // Generate placeholder function declaration (for roxygen)
- void generateRoxygenPlaceholder(std::ostream& ostr,
- const Attribute& attrib) {
-
- ostr << attrib.exportedName() << "<- function(";
- const std::vector<Argument>& args = attrib.function().arguments();
- for (std::size_t i=0; i<args.size(); i++) {
- ostr << args[i].name();
- if (i != (args.size()-1))
- ostr << ", ";
- }
- ostr << ") {}" << std::endl;
- }
-
- // Generate roxygen
- void generateRoxygen(std::ostream& ostr,
- const SourceFileAttributes& attributes) {
-
- for(SourceFileAttributes::const_iterator
- it = attributes.begin(); it != attributes.end(); ++it) {
-
- if (it->isExportedFunction() && !it->roxygen().empty()) {
- ostr << std::endl;
- for (std::size_t i=0; i<it->roxygen().size(); i++)
- ostr << it->roxygen()[i] << std::endl;
- generateRoxygenPlaceholder(ostr, *it);
- ostr << std::endl;
- }
- }
- }
-
- } // anonymous namespace
-
- ExportsGenerator::ExportsGenerator(const std::string& targetFile,
- const std::string& package,
- const std::string& commentPrefix)
- : targetFile_(targetFile),
- package_(package),
- commentPrefix_(commentPrefix) {
-
- // read the existing target file if it exists
- if (FileInfo(targetFile_).exists()) {
- std::ifstream ifs(targetFile_.c_str());
- if (ifs.fail())
- throw Rcpp::file_io_error(targetFile_);
- std::stringstream buffer;
- buffer << ifs.rdbuf();
- existingCode_ = buffer.str();
- }
-
- // see if this is safe to overwite and throw if it isn't
- if (!isSafeToOverwrite())
- throw Rcpp::file_exists(targetFile_);
- }
-
- // Commit the stream -- is a no-op if the existing code is identical
- // to the generated code. Returns true if data was written and false
- // if it wasn't (throws exception on io error)
- bool ExportsGenerator::commit(const std::string& preamble) {
-
- // get the generated code
- std::string code = codeStream_.str();
-
- // if there is no generated code AND the exports file does not
- // currently exist then do nothing
- if (code.empty() && !FileInfo(targetFile_).exists())
- return false;
-
- // write header/preamble
- std::ostringstream headerStream;
- headerStream << commentPrefix_ << " This file was generated by "
- << "Rcpp::compileAttributes" << std::endl;
- headerStream << commentPrefix_ << " Generator token: "
- << generatorToken() << std::endl << std::endl;
- if (!preamble.empty())
- headerStream << preamble;
-
- // get generated code and only write it if there was a change
- std::string generatedCode = headerStream.str() + code;
- if (generatedCode != existingCode_) {
- // open the file
- std::ofstream ofs(targetFile_.c_str(),
- std::ofstream::out | std::ofstream::trunc);
- if (ofs.fail())
- throw Rcpp::file_io_error(targetFile_);
-
- // write generated code and return
- ofs << generatedCode;
- ofs.close();
- return true;
- }
- else {
- return false;
- }
- }
-
- // Remove the generated file entirely
- bool ExportsGenerator::remove() {
- return removeFile(targetFile_);
- }
-
- CppExportsGenerator::CppExportsGenerator(const std::string& packageDir,
- const std::string& package,
- const std::string& fileSep)
- : ExportsGenerator(
- packageDir + fileSep + "src" + fileSep + "RcppExports.cpp",
- package,
- "//")
- {
- }
-
- void CppExportsGenerator::writeBegin() {
- ostr() << "RCPP_MODULE(" << package() << "_RcppExports) {"
- << std::endl;
- }
-
- void CppExportsGenerator::writeFunctions(
- const SourceFileAttributes& attributes,
- bool verbose) {
- // verbose output if requested
- if (verbose) {
- Rcpp::Rcout << "Exports from " << attributes.sourceFile() << ":"
- << std::endl;
- }
-
- // generate functions
- generateCppModuleFunctions(ostr(), attributes, verbose);
-
- // track prototypes/signatures for inclusion in the preamble
- for (std::vector<Attribute>::const_iterator
- it = attributes.begin(); it != attributes.end(); ++it) {
- if (it->isExportedFunction()) {
-
- // prototypes
- std::ostringstream ostr;
- ostr << it->function();
- prototypes_.push_back(ostr.str());
-
- // signatures
- if (!it->function().isHidden()) {
- signatures_.push_back(
- it->function().signature(it->exportedName()));
- }
- }
- }
-
- // verbose if requested
- if (verbose)
- Rcpp::Rcout << std::endl;
- }
-
- void CppExportsGenerator::writeEnd() {
-
- // add our export validation helper
- ostr() << " Rcpp::function(\""
- << exportValidationFunctionRegisteredName() << "\", &"
- << exportValidationFunction() << ");" << std::endl;
-
- ostr() << "}" << std::endl;
- }
-
- bool CppExportsGenerator::commit(const std::vector<std::string>& includes) {
-
- // includes
- std::ostringstream ostr;
- if (!includes.empty()) {
- for (std::size_t i=0;i<includes.size(); i++)
- ostr << includes[i] << std::endl;
- }
- ostr << "#include <string>" << std::endl;
- ostr << "#include <set>" << std::endl;
- ostr << std::endl;
-
- // always bring in Rcpp
- ostr << "using namespace Rcpp;" << std::endl << std::endl;
-
- // prototypes
- if (!prototypes_.empty()) {
- for (std::size_t i=0;i<prototypes_.size(); i++)
- ostr << prototypes_[i] << ";" << std::endl;
- ostr << std::endl;
- }
-
- // generate a function that can be used to validate exported
- // functions and their signatures prior to looking up with
- // GetCppCallable (otherwise inconsistent signatures between
- // client and library would cause a crash)
- ostr << "static bool " << exportValidationFunction()
- << "(const std::string& sig)" << " {" << std::endl;
- ostr << " static std::set<std::string> signatures;"
- << std::endl;
- ostr << " if (signatures.empty()) {" << std::endl;
- for (std::size_t i=0;i<signatures_.size(); i++) {
- ostr << " signatures.insert(\"" << signatures_[i]
- << "\");" << std::endl;
- }
- ostr << " }" << std::endl;
- ostr << " return signatures.find(sig) != signatures.end();"
- << std::endl;
- ostr << "}" << std::endl << std::endl;
-
- // commit with preamble
- return ExportsGenerator::commit(ostr.str());
- }
-
- CppExportsIncludeGenerator::CppExportsIncludeGenerator(
- const std::string& packageDir,
- const std::string& package,
- const std::string& fileSep)
- : ExportsGenerator(
- packageDir + fileSep + "inst" + fileSep + "include" +
- fileSep + package + kRcppExportsSuffix,
- package,
- "//")
- {
- includeDir_ = packageDir + fileSep + "inst" + fileSep + "include";
- hasCppInterface_ = false;
- }
-
- void CppExportsIncludeGenerator::writeBegin() {
-
- ostr() << "namespace " << package() << " {"
- << std::endl << std::endl;
-
- // Import Rcpp into this namespace. This allows declarations to
- // be written without fully qualifying all Rcpp types. The only
- // negative side-effect is that when this package's namespace
- // is imported it will also pull in Rcpp. However since this is
- // opt-in and represents a general desire to do namespace aliasing
- // this seems okay
- ostr() << " using namespace Rcpp;" << std::endl << std::endl;
-
- // Write our export validation helper function. Putting it in
- // an anonymous namespace will hide it from callers and give
- // it per-translation unit linkage
- ostr() << " namespace {" << std::endl;
- ostr() << " void " << exportValidationFunction()
- << "(const std::string& sig) {" << std::endl;
- std::string ptrName = "p_" + exportValidationFunction();
- ostr() << " static bool(" << "*" << ptrName
- << ")(const std::string&) = "
- << getCppCallable(exportValidationFunctionRegisteredName())
- << ";" << std::endl;
- ostr() << " if (!" << ptrName << "(sig))" << std::endl;
- ostr() << " throw Rcpp::function_not_exported(\""
- << "Function '\" + sig + \"' not found in " << package()
- << "\");" << std::endl;
- ostr() << " }" << std::endl;
-
- ostr() << " }" << std::endl << std::endl;
- }
-
- void CppExportsIncludeGenerator::writeFunctions(
- const SourceFileAttributes& attributes,
- bool verbose) {
-
- // don't write anything if there is no C++ interface
- if (!attributes.hasInterface(kInterfaceCpp))
- return;
-
- // there is a C++ interface so set flag indicating so
- hasCppInterface_ = true;
-
- for(std::vector<Attribute>::const_iterator
- it = attributes.begin(); it != attributes.end(); ++it) {
-
- if (it->isExportedFunction()) {
-
- Function function =
- it->function().renamedTo(it->exportedName());
-
- // if it's hidden then don't generate a C++ interface
- if (function.isHidden())
- continue;
-
- ostr() << " inline " << function << " {"
- << std::endl;
-
- std::string ptrName = "p_" + function.name();
- ostr() << " static " << function.signature(ptrName);
- ostr() << " = NULL;" << std::endl;
- ostr() << " if (" << ptrName << " == NULL) {"
- << std::endl;
- ostr() << " " << exportValidationFunction()
- << "(\"" << function.signature() << "\");"
- << std::endl;
- ostr() << " " << ptrName << " = "
- << getCppCallable(function.name()) << ";"
- << std::endl;
- ostr() << " }" << std::endl;
- ostr() << " return " << ptrName << "(";
-
- const std::vector<Argument>& args = function.arguments();
- for (std::size_t i = 0; i<args.size(); i++) {
- ostr() << args[i].name();
- if (i != (args.size()-1))
- ostr() << ",";
- }
-
- ostr() << ");" << std::endl;
- ostr() << " }" << std::endl << std::endl;
- }
- }
- }
-
- void CppExportsIncludeGenerator::writeEnd() {
- ostr() << "}" << std::endl;
- ostr() << std::endl;
- ostr() << "#endif // " << getHeaderGuard() << std::endl;
- }
-
- bool CppExportsIncludeGenerator::commit(
- const std::vector<std::string>& includes) {
-
- if (hasCppInterface_) {
-
- // create the include dir if necessary
- createDirectory(includeDir_);
-
- // generate preamble
- std::ostringstream ostr;
-
- // header guard
- std::string guard = getHeaderGuard();
- ostr << "#ifndef " << guard << std::endl;
- ostr << "#define " << guard << std::endl << std::endl;
-
- // includes
- if (!includes.empty()) {
- for (std::size_t i=0;i<includes.size(); i++)
- ostr << includes[i] << std::endl;
- ostr << std::endl;
- }
-
- // commit with preamble
- return ExportsGenerator::commit(ostr.str());
- }
- else {
- return ExportsGenerator::remove();
- }
- }
-
- std::string CppExportsIncludeGenerator::getCppCallable(
- const std::string& function) const {
- std::ostringstream ostr;
- ostr << "Rcpp::GetCppCallable"
- << "(\"" << package() << "\", "
- << "\"" << package() + "_RcppExports\", "
- << "\"" << function << "\")";
- return ostr.str();
- }
-
- std::string CppExportsIncludeGenerator::getHeaderGuard() const {
- return package() + "__RcppExports_h__";
- }
-
- CppPackageIncludeGenerator::CppPackageIncludeGenerator(
- const std::string& packageDir,
- const std::string& package,
- const std::string& fileSep)
- : ExportsGenerator(
- packageDir + fileSep + "inst" + fileSep + "include" +
- fileSep + package + ".h",
- package,
- "//")
- {
- includeDir_ = packageDir + fileSep + "inst" + fileSep + "include";
- hasCppInterface_ = false;
- }
-
- void CppPackageIncludeGenerator::writeFunctions(
- const SourceFileAttributes& attributes,
- bool verbose) {
- // See if there is a C++ interface exported by any attributes
- if (attributes.hasInterface(kInterfaceCpp))
- hasCppInterface_ = true;
- }
-
- void CppPackageIncludeGenerator::writeEnd() {
- if (hasCppInterface_) {
- // header guard
- std::string guard = getHeaderGuard();
- ostr() << "#ifndef " << guard << std::endl;
- ostr() << "#define " << guard << std::endl << std::endl;
-
- ostr() << "#include \"" << package() << kRcppExportsSuffix
- << "\"" << std::endl;
-
- ostr() << std::endl;
- ostr() << "#endif // " << getHeaderGuard() << std::endl;
- }
- }
-
- bool CppPackageIncludeGenerator::commit(
- const std::vector<std::string>& includes) {
-
- if (hasCppInterface_) {
-
- // create the include dir if necessary
- createDirectory(includeDir_);
-
- // commit
- return ExportsGenerator::commit();
- }
- else {
- return ExportsGenerator::remove();
- }
- }
-
- std::string CppPackageIncludeGenerator::getHeaderGuard() const {
- return "__" + package() + "_h__";
- }
-
- RExportsGenerator::RExportsGenerator(const std::string& packageDir,
- const std::string& package,
- const std::string& fileSep)
- : ExportsGenerator(
- packageDir + fileSep + "R" + fileSep + "RcppExports.R",
- package,
- "#")
- {
- }
-
- void RExportsGenerator::writeFunctions(
- const SourceFileAttributes& attributes,
- bool verbose) {
-
- // add to exported functions if we have an R interface
- if (attributes.hasInterface(kInterfaceR)) {
-
- // track exported functions
- for (std::vector<Attribute>::const_iterator
- it = attributes.begin(); it != attributes.end(); ++it) {
- if (it->isExportedFunction()) {
- rExports_.push_back(it->exportedName());
- }
- }
-
- // generate roxygen
- generateRoxygen(ostr(), attributes);
- }
- }
-
- void RExportsGenerator::writeEnd() {
-
- ostr() << "Rcpp::loadModule(\"" << package() << "_RcppExports\", ";
- if (rExports_.size() > 0) {
- ostr() << std::endl;
- ostr() << " what = c(";
- for (size_t i=0; i<rExports_.size(); i++) {
- if (i != 0)
- ostr() << " ";
- ostr() << "\"" << rExports_[i] << "\"";
- if (i != (rExports_.size()-1))
- ostr() << "," << std::endl;
- }
- ostr() << "))" << std::endl;
- }
- else {
- ostr() << "what = character())";
- }
- }
-
- bool RExportsGenerator::commit(const std::vector<std::string>& includes) {
- return ExportsGenerator::commit();
- }
-
- ExportsGenerators::~ExportsGenerators() {
- try {
- for(Itr it = generators_.begin(); it != generators_.end(); ++it)
- delete *it;
- generators_.clear();
- }
- catch(...) {}
- }
-
- void ExportsGenerators::add(ExportsGenerator* pGenerator) {
- generators_.push_back(pGenerator);
- }
-
- void ExportsGenerators::writeBegin() {
- for(Itr it = generators_.begin(); it != generators_.end(); ++it)
- (*it)->writeBegin();
- }
-
- void ExportsGenerators::writeFunctions(
- const SourceFileAttributes& attributes,
- bool verbose) {
- for(Itr it = generators_.begin(); it != generators_.end(); ++it)
- (*it)->writeFunctions(attributes, verbose);
- }
-
- void ExportsGenerators::writeEnd() {
- for(Itr it = generators_.begin(); it != generators_.end(); ++it)
- (*it)->writeEnd();
- }
-
- // Commit and return a list of the files that were updated
- std::vector<std::string> ExportsGenerators::commit(
- const std::vector<std::string>& includes) {
-
- std::vector<std::string> updated;
-
- for(Itr it = generators_.begin(); it != generators_.end(); ++it) {
- if ((*it)->commit(includes))
- updated.push_back((*it)->targetFile());
- }
-
- return updated;
- }
-
- // Remove and return a list of files that were removed
- std::vector<std::string> ExportsGenerators::remove() {
- std::vector<std::string> removed;
- for(Itr it = generators_.begin(); it != generators_.end(); ++it) {
- if ((*it)->remove())
- removed.push_back((*it)->targetFile());
- }
- return removed;
- }
-
- // Generate function entries for passed attributes
- void generateCppModuleFunctions(std::ostream& ostr,
- const SourceFileAttributes& attributes,
- bool verbose)
- {
- for(std::vector<Attribute>::const_iterator
- it = attributes.begin(); it != attributes.end(); ++it) {
-
- // verify this is an exported function
[TRUNCATED]
To get the complete diff run:
svnlook diff /svnroot/rcpp -r 4082
More information about the Rcpp-commits
mailing list