[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