1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
//! # rmin - A minimal Rust lib for writting R extensions
//!
//! This is a very early version, only support vector type, and thus its overhead is minimized.
//!
//! Compare to the well-knowned `rextendr`, This crate although with some limitations but could provide a faster implementation, a smaller code size, and a faster compile time
//! ( could generate a release build in 0.45s with `#![no_std], but may cause memory leak).
//!
//! Since it is small enough, you could vendor this crate easily into your CRAN package.
//!
//! # Usage
//!
//! Version 0.1.0 provides a fastest (but ugly) way to achieve about 2x speedup on with functions. They are discarded in 0.2.* since they are really unsafe and may cause memory leak.
//!
//! I cannot ensure whether the api will change again in the future, but currently v0.2.0 seems usable.
//!
//! ## 0.2.0, rewrite to prevent memory leak
//!
//! Several changes have been made since v0.1.0:
//!
//! 1. Add a panic_handler with default `std` feature, it is because currently, Rust cannot call all drop function before a longjmp is executed, which will cause memory leak, thus `catch_unwind` must be used and thus `std` crate is needed. I have not check whether `#![no_std]` works now, but it is better not to use it.
//! 2. Move `SEXP` to `libR::SEXP`, and exporting `SEXP<T>`, `Owned<T>` (and `Protected<T>` generated by `Owned<T>::protect` which cannot be used directly, since return `Protected<T>` to R will break the protect balance)
//! 3. Currently, you could directly indexing a sexp object, but convert them firstly into slices is more preferred.
//!
//! ### grammar
//! ```rust
//! use rmin::prelude::*;
//! /// Return a+b to R.
//! #[no_mangle]
//! pub extern "C-unwind" fn add_protect(a:SEXP<f64>,b:SEXP<f64>) -> Owned<f64> {
//! handle_panic(||{
//! let mut c=Owned::new(1).protect();
//! c[0]=a[0]+b[0];
//! c.into()
//! })
//! }
//! #[no_mangle]
//! pub extern "C-unwind" fn add_noprotect(a:SEXP<f64>,b:SEXP<f64>) -> Owned<f64> {
//! handle_panic(||{
//! let mut c=Owned::new(1);
//! c[0]=a[0]+b[0];
//! c
//! })
//! }
//!
//! /// raise panic.
//! #[no_mangle]
//! pub extern "C-unwind" fn panic() -> Owned<f64> {
//! handle_panic(||{
//! panic!("error occurs")
//! })
//! }
//! ```
//!
//! The program above could be tested with test command
//! ```bash
//! export LOAD="dyn.load('target/release/examples/libcompare_rmin.so');addnp=getNativeSymbolInfo('add_noprotect');addp=getNativeSymbolInfo('add_protect');panic=getNativeSymbolInfo('panic')" ; LC_ALL=C r -e "$LOAD;system.time(sapply(1:100000,function(x)tryCatch(.Call(wrap__panic),error=I)))" 2>/dev/null ; LC_ALL=C r -e "$LOAD;system.time(sapply(1:1000000,function(x).Call(addnp,1.,2.)));system.time(sapply(1:1000000,function(x).Call(addnp,1.,2.)))"
//! ```
pub type String = crateString;
pub use crateVec;
pub use crate::;
/// It makes no difference to choose either write `use rmin::prelude::*` or `use rmin::*`.
///
/// Choose your favorite one:)
///
/// # Example
/// ## 1. use prelude
/// ```
/// use rmin::prelude::*;
/// ```
/// ## 2. use a shorter version
/// ```
/// use rmin::*;
/// ```