[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