Skip to content

Commit b1d8ecd

Browse files
committed
implement #312
1 parent aeb1895 commit b1d8ecd

File tree

5 files changed

+49
-3
lines changed

5 files changed

+49
-3
lines changed

cpp11test/R/cpp11.R

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,14 @@ rcpp_push_and_truncate_ <- function(size_sxp) {
236236
.Call(`_cpp11test_rcpp_push_and_truncate_`, size_sxp)
237237
}
238238

239+
nullable_extptr_1 <- function() {
240+
.Call(`_cpp11test_nullable_extptr_1`)
241+
}
242+
243+
nullable_extptr_2 <- function() {
244+
.Call(`_cpp11test_nullable_extptr_2`)
245+
}
246+
239247
test_destruction_inner <- function() {
240248
invisible(.Call(`_cpp11test_test_destruction_inner`))
241249
}

cpp11test/src/cpp11.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,20 @@ extern "C" SEXP _cpp11test_rcpp_push_and_truncate_(SEXP size_sxp) {
443443
return cpp11::as_sexp(rcpp_push_and_truncate_(cpp11::as_cpp<cpp11::decay_t<SEXP>>(size_sxp)));
444444
END_CPP11
445445
}
446+
// test-external_pointer.cpp
447+
cpp11::external_pointer<int> nullable_extptr_1();
448+
extern "C" SEXP _cpp11test_nullable_extptr_1() {
449+
BEGIN_CPP11
450+
return cpp11::as_sexp(nullable_extptr_1());
451+
END_CPP11
452+
}
453+
// test-external_pointer.cpp
454+
cpp11::external_pointer<int> nullable_extptr_2();
455+
extern "C" SEXP _cpp11test_nullable_extptr_2() {
456+
BEGIN_CPP11
457+
return cpp11::as_sexp(nullable_extptr_2());
458+
END_CPP11
459+
}
446460
// test-protect-nested.cpp
447461
void test_destruction_inner();
448462
extern "C" SEXP _cpp11test_test_destruction_inner() {
@@ -500,6 +514,8 @@ static const R_CallMethodDef CallEntries[] = {
500514
{"_cpp11test_my_warning_n1", (DL_FUNC) &_cpp11test_my_warning_n1, 1},
501515
{"_cpp11test_my_warning_n1fmt", (DL_FUNC) &_cpp11test_my_warning_n1fmt, 1},
502516
{"_cpp11test_my_warning_n2fmt", (DL_FUNC) &_cpp11test_my_warning_n2fmt, 2},
517+
{"_cpp11test_nullable_extptr_1", (DL_FUNC) &_cpp11test_nullable_extptr_1, 0},
518+
{"_cpp11test_nullable_extptr_2", (DL_FUNC) &_cpp11test_nullable_extptr_2, 0},
503519
{"_cpp11test_protect_many_", (DL_FUNC) &_cpp11test_protect_many_, 1},
504520
{"_cpp11test_protect_many_cpp11_", (DL_FUNC) &_cpp11test_protect_many_cpp11_, 1},
505521
{"_cpp11test_protect_many_preserve_", (DL_FUNC) &_cpp11test_protect_many_preserve_, 1},

cpp11test/src/test-external_pointer.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,15 @@ void deleter(int* ptr) {
1010
delete ptr;
1111
}
1212

13+
// Pacha: Test nullable external_pointer (#312)
14+
[[cpp11::register]] cpp11::external_pointer<int> nullable_extptr_1() {
15+
return cpp11::external_pointer<int>(nullptr);
16+
}
17+
18+
[[cpp11::register]] cpp11::external_pointer<int> nullable_extptr_2() {
19+
return cpp11::external_pointer<int>(R_NilValue);
20+
}
21+
1322
context("external_pointer-C++") {
1423
test_that("external_pointer works") {
1524
std::vector<int>* v = new std::vector<int>;
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Pacha: test that nullable external pointer is consistent (#312)
2+
test_that("nullable external pointer is consistent", {
3+
4+
len <- 1e5
5+
set.seed(42)
6+
x <- rnorm(len)
7+
sum_base <- sum(x)
8+
9+
expect_equal(nullable_extptr_1(), NULL)
10+
expect_equal(nullable_extptr_2(), NULL)
11+
})

inst/include/cpp11/external_pointer.hpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,9 @@ class external_pointer {
2323
sexp data_ = R_NilValue;
2424

2525
static SEXP valid_type(SEXP data) {
26-
if (data == nullptr) {
27-
throw type_error(EXTPTRSXP, NILSXP);
26+
// Pacha: Allow nullable external_pointer (#312)
27+
if (data == R_NilValue) {
28+
return data;
2829
}
2930
if (detail::r_typeof(data) != EXTPTRSXP) {
3031
throw type_error(EXTPTRSXP, detail::r_typeof(data));
@@ -120,7 +121,8 @@ class external_pointer {
120121
data_ = tmp;
121122
}
122123

123-
operator bool() noexcept { return data_ != nullptr; }
124+
// Pacha: Support nullable external_pointer (#312)
125+
operator bool() const noexcept { return data_ != R_NilValue; }
124126
};
125127

126128
template <class T, void Deleter(T*)>

0 commit comments

Comments
 (0)