[Rcpp-commits] r219 - in pkg: R inst inst/examples/RcppInline src

noreply at r-forge.r-project.org noreply at r-forge.r-project.org
Mon Dec 28 12:23:31 CET 2009


Author: romain
Date: 2009-12-28 12:23:31 +0100 (Mon, 28 Dec 2009)
New Revision: 219

Added:
   pkg/src/exception_handling.cpp
Modified:
   pkg/R/exceptions.R
   pkg/inst/ChangeLog
   pkg/inst/examples/RcppInline/UncaughtExceptions.r
   pkg/src/RcppCommon.cpp
Log:
improved exception handling

Modified: pkg/R/exceptions.R
===================================================================
--- pkg/R/exceptions.R	2009-12-27 22:11:52 UTC (rev 218)
+++ pkg/R/exceptions.R	2009-12-28 11:23:31 UTC (rev 219)
@@ -15,11 +15,11 @@
 # You should have received a copy of the GNU General Public License
 # along with Rcpp.  If not, see <http://www.gnu.org/licenses/>.
 
-uncaught_cpp_exception <- function( message = "uncaught C++ exception" ){
+cpp_exception <- function( message = "C++ exception", class = NULL ){
 	callstack <- sys.calls()
 	ncalls <- length(callstack)
 	call <- if( ncalls > 1L) callstack[[ ncalls - 1L ]] else match.call()
-	classes <- c( "C++Error", "error", "condition" )
+	classes <- c( class, "C++Error", "error", "condition" )
 	condition <- structure( 
 		list( message = message, call = call ), 
 		class = classes )

Modified: pkg/inst/ChangeLog
===================================================================
--- pkg/inst/ChangeLog	2009-12-27 22:11:52 UTC (rev 218)
+++ pkg/inst/ChangeLog	2009-12-28 11:23:31 UTC (rev 219)
@@ -1,3 +1,15 @@
+2009-12-28  Romain Francois <francoisromain at free.fr>
+
+	* R/exceptions.R: s/uncaught_cpp_exception/cpp_exception/ and added a
+	'class' argument to hold the class name of the C++ exception
+	(range_error, etc ...)
+
+	* inst/examples/RcppInline/UncaughtExceptions.r: extend examples to
+	show how to grab details of the C++ exception
+
+	* src/exception_handling.cpp: factored out from RcppCommon.cpp, now
+	able to grab the class name of the exception and its message. 
+
 2009-12-27  Dirk Eddelbuettel  <edd at debian.org>
 
 	* R/RcppInline.R: Removed as we now use cfunction() from inline (>= 0.3.4)

Modified: pkg/inst/examples/RcppInline/UncaughtExceptions.r
===================================================================
--- pkg/inst/examples/RcppInline/UncaughtExceptions.r	2009-12-27 22:11:52 UTC (rev 218)
+++ pkg/inst/examples/RcppInline/UncaughtExceptions.r	2009-12-28 11:23:31 UTC (rev 219)
@@ -24,8 +24,13 @@
 return R_NilValue ;
 ', Rcpp=TRUE, verbose=FALSE)
 tryCatch(  funx(), "C++Error" = function(e){
-	print( "gotcha" )
+	cat( sprintf( "C++ exception of class '%s' : %s\n", class(e)[1L], e$message  ) )
 } )
+# or using a direct handler 
+tryCatch(  funx(), "std::range_error" = function(e){
+        cat( sprintf( "C++ exception of class '%s' : %s\n", class(e)[1L], e$message  ) )
+} )
+# just to check things carry on
 print( rnorm(10) )
 
 

Modified: pkg/src/RcppCommon.cpp
===================================================================
--- pkg/src/RcppCommon.cpp	2009-12-27 22:11:52 UTC (rev 218)
+++ pkg/src/RcppCommon.cpp	2009-12-28 11:23:31 UTC (rev 219)
@@ -40,18 +40,3 @@
     Rprintf("%s:%d %s\n", file, line, expression);
 }
 
-void forward_uncaught_exceptions_to_r(){
-	/* we don't bother unprotecting */
-	SEXP m = PROTECT( Rf_mkString( "uncaught C++ exception" ) ) ;
-	SEXP call = PROTECT( Rf_lang2( Rf_install("uncaught_cpp_exception"), m ) ) ;
-	Rf_eval( call, R_FindNamespace(Rf_mkString("Rcpp")) ) ; 
-	
-	/* but this is never actually called since the call eventually calls stop */
-	UNPROTECT(1);
-}
-SEXP initUncaughtExceptionHandler(){
-	void (*old_terminate)() = std::set_terminate(forward_uncaught_exceptions_to_r);
-	return R_NilValue ;
-}
-
-

Added: pkg/src/exception_handling.cpp
===================================================================
--- pkg/src/exception_handling.cpp	                        (rev 0)
+++ pkg/src/exception_handling.cpp	2009-12-28 11:23:31 UTC (rev 219)
@@ -0,0 +1,77 @@
+// -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; tab-width: 8 -*-
+//
+// RcppCommon.cpp: R/C++ interface class library -- common functions
+//
+// Copyright (C) 2009 - 2010 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 <Rcpp.h>
+#include <typeinfo>
+#include <exception>
+#include <exception_defines.h>
+#include <cxxabi.h>
+
+/* much inspired from the __verbose_terminate_handler of the GCC */
+void forward_uncaught_exceptions_to_r(){
+	
+	std::string exception_class ;
+	bool has_exception_class = false;
+	std::string exception_what ; 
+	
+	// Make sure there was an exception; terminate is also called for an
+    // attempt to rethrow when there is no suitable exception.
+    std::type_info *t = abi::__cxa_current_exception_type();
+    if (t){
+    	has_exception_class = true ;
+    	const char *name = t->name() ;
+    	// now we need to demangle "name"
+    	
+    	{
+    	  int status = -1;
+    	  char *dem = 0;
+    	  dem = abi::__cxa_demangle(name, 0, 0, &status);
+    	  if( status == 0){
+    	  	 exception_class = dem ; /* great we can use the demangled name */
+    	  	 free(dem);
+    	  } else{
+    	  	 exception_class = name ; /* just using the mangled name */
+    	  }
+    	}
+	}
+	
+	// If the exception is derived from std::exception, we can give more
+    // information.
+    try { 
+    	__throw_exception_again;
+#ifdef __EXCEPTIONS    	
+    } catch (std::exception &exc) { 
+    	exception_what = exc.what() ;
+#endif
+    } catch (...) { 
+    	exception_what = "unrecognized exception" ;
+    }
+    
+	Rf_eval( 
+		Rf_lang3( Rf_install("cpp_exception"), Rf_mkString(exception_what.c_str()), has_exception_class ? Rf_mkString(exception_class.c_str()) : R_NilValue ), 
+		R_FindNamespace(Rf_mkString("Rcpp"))
+	) ; 
+}
+SEXP initUncaughtExceptionHandler(){
+	void (*old_terminate)() = std::set_terminate(forward_uncaught_exceptions_to_r);
+	return R_NilValue ;
+}
+



More information about the Rcpp-commits mailing list