[Rcpp-devel] Problem with exceptions from standalone functions (Windows only)
QRD
qrd at sig.com
Thu Jun 13 10:17:38 CEST 2013
Hi,
I've just had some trouble, on Windows with Rtools-3.0, throwing
exceptions from within a standalone function belonging to a module:
- - - - 8< - - - - crash.cpp
#include <stdexcept>
#include <Rcpp.h>
int calculate(int x)
{
throw std::invalid_argument("x is invalid");
}
RCPP_MODULE(Crash)
{
Rcpp::function("calculate", &calculate);
}
- - - - 8< - - - - crash.R
require(methods)
require(Rcpp)
dll.info <- dyn.load("crash")
mod <- Module("Crash", dll.info, mustStart = TRUE)
mod$calculate(42)
- - - - 8< - - - - shell prompt
R CMD SHLIB crash.cpp && Rscript crash.R
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
terminate called after throwing an instance of 'std::invalid_argument'
what(): x is invalid
- - - - 8< - - - -
This is strange as there is a BEGIN_RCPP / END_RCPP pair in the relevant
function in Module.cpp:
extern "C" SEXP InternalFunction_invoke( SEXP args ){
BEGIN_RCPP
SEXP p = CDR(args) ;
XP_Function fun( CAR(p) ) ; p = CDR(p) ;
UNPACK_EXTERNAL_ARGS(cargs,p)
return fun->operator()( cargs ) ;
END_RCPP
}
What seems to be going on is:
Under MinGW, you can only throw/catch exceptions across a DLL boundary
when linking to the 'DLL runtime'. I'm basing this on quite an old
post (from Jan 2011):
http://mingw-users.1079350.n2.nabble.com/dlls-and-exceptions-using-a-cross-compiler-td5967925.html
This is my situation, because I throw the exception from crash.dll, but
it's the above code from Module.cpp in Rcpp.dll which tries to catch it.
The R scripts use a link invocation which includes '-static-libgcc':
R CMD SHLIB # ...
g++ -m64 -shared -s -static-libgcc -o crash.dll # [... etc. ...]
and also Rtools's 'g++ -v' reports that it was configured with
'--disabled-shared':
Target: i686-w64-mingw32
Configured with: [...] --disable-shared --enable-static [...]
Thread model: win32
gcc version 4.6.3 20111208 (prerelease) (GCC)
This problem doesn't show up with throwing exceptions from class member
functions, because in that case, all the work gets done in a template, so
the try/catch is compiled into my module's DLL.
For an only-mildly-ugly workaround, I put a BEGIN_RCPP / END_RCPP pair
around the call in the CppFunction1<OUT, U0> template class (c. line 104
in Module_generated_CppFunction.h):
SEXP operator()(SEXP* args) {
BEGIN_RCPP // <<-- ADD THIS
return Rcpp::module_wrap<OUT>( ptr_fun( /* ... */ ) );
END_RCPP // <<-- AND THIS
}
This is a template, so it gets compiled into my DLL, the exception never
leaves my DLL, and all is well.
Because of the '_generated_' in the filename, I haven't created a patch.
If the above is right, do you think adding BEGIN_RCPP / END_RCPP pairs
in all of the CppFunction-derived classes would be acceptable to work
round this feature of the current build set-up under MinGW?
Thanks,
Ben.
More information about the Rcpp-devel
mailing list