Skip to content

Commit acf8324

Browse files
committed
convert c++ exceptions to r errors in module .External entry points (#1496)
1 parent 7ce2f82 commit acf8324

3 files changed

Lines changed: 22 additions & 1 deletion

File tree

ChangeLog

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
2026-08-03 Kevin Ushey <kevinushey@gmail.com>
22

3+
* src/module.cpp (class__newInstance, CppMethod__invoke,
4+
CppMethod__invoke_void, CppMethod__invoke_notvoid): Convert C++
5+
exceptions to R errors at these .External entry points, so that
6+
e.g. calling a method on an uninitialized module object raises
7+
the intended R error rather than terminating the R session
8+
(#1495)
9+
* inst/tinytest/test_module.R: Add regression test
310
* inst/include/Rcpp/module/class.h (invoke): Protect freshly
411
computed method results while wrapping them in the result list
512
(#1493)

inst/tinytest/test_module.R

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,12 @@ x10 <- runif(10, 10.0, 20.0)
102102
set.seed(123)
103103
expect_equal(r$get(10), x10)
104104

105+
## calling a method on an uninitialized module object (created via the
106+
## dummy-object path for classes without a default constructor) should
107+
## raise an R error rather than terminating the R session (#1495)
108+
r <- new( ModuleRandomizer )
109+
expect_error( r$get(10L), "not initialized" )
110+
105111
# test.Module.flexible.semantics <- function( ){
106112
expect_equal( test_reference( seq(0,10) ), 11L )
107113
expect_equal( test_const_reference( seq(0,10) ), 11L )

src/module.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,12 +135,14 @@ END_RCPP
135135
} // #nocov end
136136

137137
SEXP class__newInstance(SEXP args) {
138+
BEGIN_RCPP
138139
SEXP p = CDR(args);
139140

140141
XP_Module module(CAR(p)); p = CDR(p);
141142
XP_Class clazz(CAR(p)); p = CDR(p);
142143
UNPACK_EXTERNAL_ARGS(cargs,p)
143144
return clazz->newInstance(cargs, nargs);
145+
END_RCPP
144146
}
145147

146148
// relies on being set in .onLoad()
@@ -164,6 +166,7 @@ SEXP class__dummyInstance(SEXP args) {
164166
}
165167

166168
SEXP CppMethod__invoke(SEXP args) { // #nocov start
169+
BEGIN_RCPP
167170
SEXP p = CDR(args);
168171

169172
// the external pointer to the class
@@ -180,9 +183,11 @@ SEXP CppMethod__invoke(SEXP args) { // #nocov start
180183
UNPACK_EXTERNAL_ARGS(cargs,p)
181184

182185
return clazz->invoke(met, obj, cargs, nargs);
183-
} // #nocov end
186+
END_RCPP
187+
} // #nocov end
184188

185189
SEXP CppMethod__invoke_void(SEXP args) {
190+
BEGIN_RCPP
186191
SEXP p = CDR(args);
187192

188193
// the external pointer to the class
@@ -199,9 +204,11 @@ SEXP CppMethod__invoke_void(SEXP args) {
199204
UNPACK_EXTERNAL_ARGS(cargs,p)
200205
clazz->invoke_void(met, obj, cargs, nargs);
201206
return R_NilValue;
207+
END_RCPP
202208
}
203209

204210
SEXP CppMethod__invoke_notvoid(SEXP args) {
211+
BEGIN_RCPP
205212
SEXP p = CDR(args);
206213

207214
// the external pointer to the class
@@ -218,6 +225,7 @@ SEXP CppMethod__invoke_notvoid(SEXP args) {
218225
UNPACK_EXTERNAL_ARGS(cargs,p)
219226

220227
return clazz->invoke_notvoid(met, obj, cargs, nargs);
228+
END_RCPP
221229
}
222230

223231
namespace Rcpp{

0 commit comments

Comments
 (0)