extendr: robj::try_into() fails for Result> where MyStruct derived with #[extendr]
Dear extendries
I get an error which comes from this check
test tests::it_works ... FAILED
failures:
---- tests::it_works stdout ----
[src/lib.rs:38] &robj = ExternalPtr.set_class(["MyStruct"]
thread 'tests::it_works' panicked at 'called `Result::unwrap()` on an `Err` value: ExpectedExternalPtrType(ExternalPtr.set_class(["MyStruct"], "helloextendr::MyStruct")', src/lib.rs:16:21
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
I try to convert Robj to MyStruct but it seems to fail because ptr tag is ‘MyStruct’ and typename is “helloextendr::MyStruct” robj::try_into() fails for Result<ExternalPtr<MyStruct>>.
the unit test only covers a trivial type not a user-defined #[extendr]-exported struct
all the best
use extendr_api::prelude::*;
#[derive(Debug, Clone)]
#[extendr]
struct MyStruct(String); //could be any type
#[extendr]
impl MyStruct {
pub fn new() -> Self {
MyStruct("applepie".into())
}
//restore_from_robj must take Robj, not MyStruct as input
pub fn restore_from_robj(robj: Robj) -> Self {
let res: Result<ExternalPtr<MyStruct>> = robj.try_into(); // this fails
let x = res.unwrap().0.clone();
MyStruct(x)
}
}
// Macro to generate exports.
extendr_module! {
mod helloextendr;
impl MyStruct;
}
#[cfg(test)]
mod tests {
use super::*;
use extendr_api::prelude::extendr_engine::{end_r, start_r};
#[test]
//build and install package to access it from rust side
fn it_works() {
start_r();
let robj = R!("helloextendr:::MyStruct$new()").unwrap();
dbg!(&robj);
let mystruct = MyStruct::restore_from_robj(robj);
assert_eq!(mystruct.0, "applpie".to_string());
end_r();
}
}
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Comments: 22 (22 by maintainers)
Commits related to this issue
- Create test for #431 — committed to Ilia-Kosenkov/extendr by Ilia-Kosenkov 2 years ago
- Unify external ptr tag names (#433) * Create test for #431 * Update externalptr usage * Update docs & wrappers in test project — committed to extendr/extendr by Ilia-Kosenkov 2 years ago
cargo tests were alright, just needed to build package fully and not use rextendr::document().
@Ilia-Kosenkov
Tags now are created with the correct type name. It is strange as I ran your test project against my branch and it worked. I also added a test to re-create your scenario. Can you check the PR?
I see your point. The problem here is that we are providing an API to others and thus we have to be very precise about type conversion. We might consider two things here:
indeed provide an unsafe function that will behave as, basically,
reinterpret_cast<>()
or something similar – take the pointer and cast it to whatever you belive is correct, no guarantees;update current implementation to provide partial safety – we can notify the user whether we were able to match the type
Err()
case in the current implementationimprove tag generation by embedding more metadata – perhaps information about the type shape & size. That way we can allow reinterpreting the pointer to any type of the same shape and size
I do not have a lot of free time right now, but this thing is top-1 priority for me. Let me do some more research and I’ll get back to you.