[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