R to Rust type mapping
extendr is allows us to create a bridge between R and Rust. When writing a function in Rust that is intended to be called from R, it is important that the input types be R types. There are many types of objects in R (almost) all of which are available in extendr via a wrapper struct.
The below lists the extendr structs that wrap R object types. These types can be used as function arguments or return values.
Scalar types
R has no concept of scalar values whereas Rust does. Rust does not have the concept of an NA. As such, we have types to represent scalar values in R. The below is how they are mapped.
| R type | extendr type | Rust type |
|---|---|---|
integer(1) |
Rint |
i32 |
double(1) |
Rfloat |
f64 |
logical(1) |
Rbool |
bool |
complex(1) |
Rcplx |
Complex<f64> |
character(1) |
Rstr |
String |
Vector types
Everything in R is a vector. In Rust, we have to point to R’s owned vector types rather than use Rust’s native Vec collection. These are mapped accordingly:
| R type | extendr type | extendr scalar type | C API Type |
|---|---|---|---|
integer() |
Integers |
Rint |
INTSXP |
double() |
Doubles |
Rfloat |
REALSXP |
logical() |
Logicals |
Rbool |
LGLSXP |
complex() |
Complexes |
Rcplx |
CPLXSXP |
character() |
Strings |
Rstr |
STRSXP |
raw() |
Raw |
&[u8] |
RAWSXP |
list() |
List |
Robj |
VECSXP |
Using Rust library types vs R-native types
Whenever possible use the extendr wrapper type. Accepting or returning a Vec<T> requires additional allocations. This will always incur memory usage overhead. In some cases, the overhead will be minimal and tolerable. However, if you can use the Rust type instead, always do.
Other types
Environment(ENVSXP)Expressions(EXPRSXP)ExternalPtr(EXTPTRSXP)Function(CLOSSXP)Language(LANGSXP)RArrayPairlist(LISTSXP)Promise(PROMSXP)S4(S4SXP)