mod args;
mod engine;
mod logical;
mod rmacros;
mod robj;
mod wrapper;
pub use args::*;
pub use engine::*;
pub use rmacros::*;
pub use robj::*;
pub use wrapper::*;
pub use extendr_macros::*;
pub use libR_sys::DllInfo;
pub use libR_sys::R_CallMethodDef;
pub use libR_sys::R_forceSymbols;
pub use libR_sys::R_registerRoutines;
pub use libR_sys::R_useDynamicSymbols;
pub use libR_sys::SEXP;
pub type AnyError = Box<dyn std::error::Error + Send + Sync>;
pub struct CallMethod {
pub call_symbol: std::ffi::CString,
pub func_ptr: *const u8,
pub num_args: i32,
}
pub unsafe fn register_call_methods(info: *mut libR_sys::DllInfo, methods: &[CallMethod]) {
let mut rmethods: Vec<_> = methods
.iter()
.map(|m| libR_sys::R_CallMethodDef {
name: m.call_symbol.as_ptr(),
fun: Some(std::mem::transmute(m.func_ptr)),
numArgs: m.num_args,
})
.collect();
rmethods.push(libR_sys::R_CallMethodDef {
name: std::ptr::null(),
fun: None,
numArgs: 0,
});
libR_sys::R_registerRoutines(
info,
std::ptr::null(),
rmethods.as_ptr(),
std::ptr::null(),
std::ptr::null(),
);
}
#[cfg(test)]
mod tests {
use super::*;
use crate as extendr_api;
use extendr_macros::extendr;
use extendr_macros::extendr_module;
#[extendr]
pub fn inttypes(a: i8, b: u8, c: i16, d: u16, e: i32, f: u32, g: i64, h: u64) {
assert_eq!(a, 1);
assert_eq!(b, 2);
assert_eq!(c, 3);
assert_eq!(d, 4);
assert_eq!(e, 5);
assert_eq!(f, 6);
assert_eq!(g, 7);
assert_eq!(h, 8);
}
#[extendr]
pub fn floattypes(a: f32, b: f64) {
assert_eq!(a, 1.);
assert_eq!(b, 2.);
}
#[extendr]
pub fn strtypes(a: &str, b: String) {
assert_eq!(a, "abc");
assert_eq!(b, "def");
}
#[extendr]
pub fn vectortypes(a: Vec<i32>, b: Vec<f64>) {
assert_eq!(a, [1, 2, 3]);
assert_eq!(b, [4., 5., 6.]);
}
#[extendr]
pub fn robjtype(a: Robj) {
assert_eq!(a, Robj::from(1))
}
#[extendr]
pub fn return_u8() -> u8 {
123
}
#[extendr]
pub fn return_u16() -> u16 {
123
}
#[extendr]
pub fn return_u32() -> u32 {
123
}
#[extendr]
pub fn return_u64() -> u64 {
123
}
#[extendr]
pub fn return_i8() -> i8 {
123
}
#[extendr]
pub fn return_i16() -> i16 {
123
}
#[extendr]
pub fn return_i32() -> i32 {
123
}
#[extendr]
pub fn return_i64() -> i64 {
123
}
#[extendr]
pub fn return_f32() -> f32 {
123.
}
#[extendr]
pub fn return_f64() -> f64 {
123.
}
struct Person {
pub name: String,
}
#[extendr]
impl Person {
fn new() -> Self {
Self {
name: "".to_string(),
}
}
fn set_name(&mut self, name: &str) {
self.name = name.to_string();
}
fn name(&self) -> &str {
self.name.as_str()
}
}
#[extendr]
fn aux_func(_person: &Person) {}
extendr_module! {
mod my_module;
fn aux_func;
impl Person;
}
#[test]
fn export_test() {
use super::*;
unsafe {
wrap__inttypes(
Robj::from(1).get(),
Robj::from(2).get(),
Robj::from(3).get(),
Robj::from(4).get(),
Robj::from(5).get(),
Robj::from(6).get(),
Robj::from(7).get(),
Robj::from(8).get(),
);
wrap__inttypes(
Robj::from(1.).get(),
Robj::from(2.).get(),
Robj::from(3.).get(),
Robj::from(4.).get(),
Robj::from(5.).get(),
Robj::from(6.).get(),
Robj::from(7.).get(),
Robj::from(8.).get(),
);
wrap__floattypes(Robj::from(1.).get(), Robj::from(2.).get());
wrap__floattypes(Robj::from(1).get(), Robj::from(2).get());
wrap__strtypes(Robj::from("abc").get(), Robj::from("def").get());
wrap__vectortypes(
Robj::from(&[1, 2, 3] as &[i32]).get(),
Robj::from(&[4., 5., 6.] as &[f64]).get(),
);
wrap__robjtype(Robj::from(1).get());
assert_eq!(new_borrowed(wrap__return_u8()), Robj::from(123));
assert_eq!(new_borrowed(wrap__return_u16()), Robj::from(123));
assert_eq!(new_borrowed(wrap__return_u32()), Robj::from(123));
assert_eq!(new_borrowed(wrap__return_u64()), Robj::from(123));
assert_eq!(new_borrowed(wrap__return_i8()), Robj::from(123));
assert_eq!(new_borrowed(wrap__return_i16()), Robj::from(123));
assert_eq!(new_borrowed(wrap__return_i32()), Robj::from(123));
assert_eq!(new_borrowed(wrap__return_i64()), Robj::from(123));
assert_eq!(new_borrowed(wrap__return_f32()), Robj::from(123.));
assert_eq!(new_borrowed(wrap__return_f64()), Robj::from(123.));
}
}
}