Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Raising exceptions in Rcpp

Tags:

c++

r

rcpp

I am trying to report errors from my rcpp code. I am using the constructor exception (const char *message_, const char *file, int line) from http://dirk.eddelbuettel.com/code/rcpp/html/classRcpp_1_1exception.html. To isolate the problem, I wrote the following bar.cpp:

#include <Rcpp.h>

RcppExport SEXP bar( SEXP x){
        throw(Rcpp::exception("My Error Message","bar.cpp",4));
        return x ;
}

When I run it in R, this is what I get:

> dyn.load("bar.so")
> is.loaded("bar")
[1] TRUE
> .Call("bar",12)
Error: SET_VECTOR_ELT() can only be applied to a 'list', not a 'NULL'
> 
like image 395
highBandWidth Avatar asked Dec 08 '11 22:12

highBandWidth


People also ask

Which exceptions are raised?

An exception is a runtime error or warning condition, which can be predefined or user-defined. Predefined exceptions are raised implicitly (automatically) by the runtime system. User-defined exceptions must be raised explicitly by RAISE statements.

How do I raise exceptions in CPP?

An exception in C++ is thrown by using the throw keyword from inside the try block. The throw keyword allows the programmer to define custom exceptions. Exception handlers in C++ are declared with the catch keyword, which is placed immediately after the try block.


1 Answers

You can either

  • use the inline package which puts a try/catch block into the function it generates for you (by using two simple macros)

  • or do it manually yourself as shown in a bunch of examples on my blog, or in the examples/ section of the Rcpp package,

but doing what you (ie: throwing outside of a try/catch block) can never work.

As an added bonus, here is a complete example (which essentially already existed in the unit tests):

R> library(inline)
R> f <- cxxfunction(signature(), plugin="Rcpp", body='
+    throw std::range_error("boom");
+    return R_NilValue;
+ ')
R> f()
Error in f() : boom
R>

Again, cxxfunction() puts a try/catch() block in here for you as you can see if you turn verbose on:

R> f <- cxxfunction(signature(), plugin="Rcpp", body='
+    throw std::range_error("boom");
+    return R_NilValue;
+ ', verbose=TRUE)
 >> setting environment variables:
PKG_LIBS =  -L/usr/local/lib/R/site-library/Rcpp/lib \
            -lRcpp -Wl,-rpath,/usr/local/lib/R/site-library/Rcpp/lib

 >> LinkingTo : Rcpp
CLINK_CPPFLAGS =  -I"/usr/local/lib/R/site-library/Rcpp/include"

 >> Program source :

   1 :
   2 : // includes from the plugin
   3 :
   4 : #include <Rcpp.h>
   5 :
   6 :
   7 : #ifndef BEGIN_RCPP
   8 : #define BEGIN_RCPP
   9 : #endif
  10 :
  11 : #ifndef END_RCPP
  12 : #define END_RCPP
  13 : #endif
  14 :
  15 : using namespace Rcpp;
  16 :
  17 :
  18 :
  19 : // user includes
  20 :
  21 :
  22 : // declarations
  23 : extern "C" {
  24 : SEXP file4cc53282( ) ;
  25 : }
  26 :
  27 : // definition
  28 :
  29 : SEXP file4cc53282(  ){
  30 : BEGIN_RCPP
  31 :
  32 :    throw std::range_error("boom");
  33 :    return R_NilValue;
  34 :
  35 : END_RCPP
  36 : }
  37 :
  38 :
Compilation argument:
 /usr/lib/R/bin/R CMD SHLIB file4cc53282.cpp 2> file4cc53282.cpp.err.txt
ccache g++-4.6 -I/usr/share/R/include   \
   -I"/usr/local/lib/R/site-library/Rcpp/include"   \
   -fpic  -g0 -O3 -Wall -pipe -Wno-unused -pedantic -c file4cc53282.cpp \
   -o file4cc53282.o
g++ -shared -o file4cc53282.so file4cc53282.o \
   -L/usr/local/lib/R/site-library/Rcpp/lib \
   -lRcpp -Wl,-rpath,/usr/local/lib/R/site-library/Rcpp/lib \
   -L/usr/lib/R/lib -lR
R>

The BEGIN_RCPP and END_CPP add the magic you need here.

Please do move your questions to rcpp-devel.

like image 136
Dirk Eddelbuettel Avatar answered Sep 28 '22 00:09

Dirk Eddelbuettel