Skip to content

Commit

Permalink
test: what happens with non-ref arguments?
Browse files Browse the repository at this point in the history
  • Loading branch information
CGMossa committed Apr 6, 2024
1 parent d537352 commit fd30622
Show file tree
Hide file tree
Showing 5 changed files with 144 additions and 1 deletion.
2 changes: 2 additions & 0 deletions tests/extendrtests/R/extendr-wrappers.R
Expand Up @@ -212,6 +212,8 @@ MySubmoduleClass$me_explicit_mut <- function() .Call(wrap__MySubmoduleClass__me_

MySubmoduleClass$max_ref <- function(other) .Call(wrap__MySubmoduleClass__max_ref, self, other)

MySubmoduleClass$max_ref_offset <- function(other, `_offset`) .Call(wrap__MySubmoduleClass__max_ref_offset, self, other, `_offset`)

#' @rdname MySubmoduleClass
#' @usage NULL
#' @export
Expand Down
2 changes: 1 addition & 1 deletion tests/extendrtests/man/MySubmoduleClass.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions tests/extendrtests/src/rust/src/submodule.rs
Expand Up @@ -78,6 +78,14 @@ impl MySubmoduleClass {
other
}
}

fn max_ref_offset(&self, other: &'static MySubmoduleClass, _offset: i32) -> &Self {
if self.a > other.a {
self
} else {
other
}
}
}

// Macro to generate exports
Expand Down
128 changes: 128 additions & 0 deletions tests/extendrtests/tests/testthat/_snaps/macro-snapshot.md
Expand Up @@ -2600,6 +2600,13 @@
fn max_ref(&self, other: &'static MySubmoduleClass) -> &Self {
if self.a > other.a { self } else { other }
}
fn max_ref_offset(
&self,
other: &'static MySubmoduleClass,
_offset: i32,
) -> &Self {
if self.a > other.a { self } else { other }
}
}
#[no_mangle]
#[allow(non_snake_case, clippy::not_unsafe_ptr_arg_deref)]
Expand Down Expand Up @@ -3397,6 +3404,126 @@
hidden: false,
})
}
#[no_mangle]
#[allow(non_snake_case, clippy::not_unsafe_ptr_arg_deref)]
pub extern "C" fn wrap__MySubmoduleClass__max_ref_offset(
_self: extendr_api::SEXP,
other: extendr_api::SEXP,
_offset: extendr_api::SEXP,
) -> extendr_api::SEXP {
use extendr_api::robj::*;
let wrap_result_state: std::result::Result<
std::result::Result<Robj, extendr_api::Error>,
Box<dyn std::any::Any + Send>,
> = unsafe {
let mut _self_robj = extendr_api::robj::Robj::from_sexp(_self);
let _other_robj = extendr_api::robj::Robj::from_sexp(other);
let __offset_robj = extendr_api::robj::Robj::from_sexp(_offset);
std::panic::catch_unwind(|| -> std::result::Result<Robj, extendr_api::Error> {
let return_ref_to_self = extendr_api::unwrap_or_throw(
<&MySubmoduleClass>::from_robj(&_self_robj),
)
.max_ref_offset(
<&'static MySubmoduleClass>::from_robj(&_other_robj)?,
<i32>::from_robj(&__offset_robj)?,
);
if std::ptr::addr_eq(
libR_sys::R_ExternalPtrAddr(_self),
std::ptr::from_ref(return_ref_to_self),
) {
return Ok(extendr_api::Robj::from_sexp(_self));
}
if std::ptr::addr_eq(
libR_sys::R_ExternalPtrAddr(other),
std::ptr::from_ref(return_ref_to_self),
) {
return Ok(extendr_api::Robj::from_sexp(other));
}
if std::ptr::addr_eq(
libR_sys::R_ExternalPtrAddr(_offset),
std::ptr::from_ref(return_ref_to_self),
) {
return Ok(extendr_api::Robj::from_sexp(_offset));
}
Err(Error::ExpectedExternalPtrReference)
})
};
match wrap_result_state {
Ok(Ok(zz)) => {
return unsafe { zz.get() };
}
Ok(Err(conversion_err)) => {
let err_string = conversion_err.to_string();
drop(conversion_err);
extendr_api::throw_r_error(&err_string);
}
Err(unwind_err) => {
drop(unwind_err);
let err_string = {
let res = ::alloc::fmt::format(
format_args!("user function panicked: {0}", "max_ref_offset"),
);
res
};
extendr_api::handle_panic(
err_string.as_str(),
|| {
#[cold]
#[track_caller]
#[inline(never)]
const fn panic_cold_explicit() -> ! {
::core::panicking::panic_explicit()
}
panic_cold_explicit();
},
);
}
}
{
::core::panicking::panic_fmt(
format_args!(
"internal error: entered unreachable code: {0}",
format_args!("internal extendr error, this should never happen."),
),
);
}
}
#[allow(non_snake_case)]
fn meta__MySubmoduleClass__max_ref_offset(
metadata: &mut Vec<extendr_api::metadata::Func>,
) {
let mut args = <[_]>::into_vec(
#[rustc_box]
::alloc::boxed::Box::new([
extendr_api::metadata::Arg {
name: "self",
arg_type: "MySubmoduleClass",
default: None,
},
extendr_api::metadata::Arg {
name: "other",
arg_type: "MySubmoduleClass",
default: None,
},
extendr_api::metadata::Arg {
name: "_offset",
arg_type: "i32",
default: None,
},
]),
);
metadata
.push(extendr_api::metadata::Func {
doc: "",
rust_name: "max_ref_offset",
r_name: "max_ref_offset",
mod_name: "max_ref_offset",
args: args,
return_type: "Self",
func_ptr: wrap__MySubmoduleClass__max_ref_offset as *const u8,
hidden: false,
})
}
impl<'a> extendr_api::FromRobj<'a> for &MySubmoduleClass {
fn from_robj(robj: &'a Robj) -> std::result::Result<Self, &'static str> {
if robj.check_external_ptr_type::<MySubmoduleClass>() {
Expand Down Expand Up @@ -3453,6 +3580,7 @@
meta__MySubmoduleClass__me_explicit_ref(&mut methods);
meta__MySubmoduleClass__me_explicit_mut(&mut methods);
meta__MySubmoduleClass__max_ref(&mut methods);
meta__MySubmoduleClass__max_ref_offset(&mut methods);
impls
.push(extendr_api::metadata::Impl {
doc: " Class for testing (exported)\n @examples\n x <- MySubmoduleClass$new()\n x$a()\n x$set_a(10)\n x$a()\n @export",
Expand Down
5 changes: 5 additions & 0 deletions tests/extendrtests/tests/testthat/test-test-submodules.R
Expand Up @@ -32,4 +32,9 @@ test_that("Return the right externalptr", {
max_class <- x$max_ref(y)
expect_identical(max_class, y)
expect_false(isTRUE(identical(x, max_class)))

# check if you can have regular arguments as well
x <- MySubmoduleClass$new()
x$set_a(22)
x$max_ref_offset(y, 30)
})

0 comments on commit fd30622

Please sign in to comment.