Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
pola-rs
GitHub Repository: pola-rs/polars
Path: blob/main/crates/polars-ffi/src/version_0.rs
6939 views
1
use polars_core::frame::DataFrame;
2
use polars_core::prelude::{Column, CompatLevel};
3
4
use super::*;
5
6
/// An FFI exported `Series`.
7
#[repr(C)]
8
pub struct SeriesExport {
9
field: *mut ArrowSchema,
10
// A double ptr, so we can easily release the buffer
11
// without dropping the arrays.
12
arrays: *mut *mut ArrowArray,
13
len: usize,
14
release: Option<unsafe extern "C" fn(arg1: *mut SeriesExport)>,
15
private_data: *mut std::os::raw::c_void,
16
}
17
18
impl SeriesExport {
19
pub fn empty() -> Self {
20
Self {
21
field: std::ptr::null_mut(),
22
arrays: std::ptr::null_mut(),
23
len: 0,
24
release: None,
25
private_data: std::ptr::null_mut(),
26
}
27
}
28
29
pub fn is_null(&self) -> bool {
30
self.private_data.is_null()
31
}
32
}
33
34
impl Drop for SeriesExport {
35
fn drop(&mut self) {
36
if let Some(release) = self.release {
37
unsafe { release(self) }
38
}
39
}
40
}
41
42
// callback used to drop [SeriesExport] when it is exported.
43
unsafe extern "C" fn c_release_series_export(e: *mut SeriesExport) {
44
if e.is_null() {
45
return;
46
}
47
let e = &mut *e;
48
let private = Box::from_raw(e.private_data as *mut PrivateData);
49
for ptr in private.arrays.iter() {
50
// drop the box, not the array
51
let _ = Box::from_raw(*ptr as *mut ManuallyDrop<ArrowArray>);
52
}
53
54
e.release = None;
55
}
56
57
pub fn export_column(c: &Column) -> SeriesExport {
58
export_series(c.as_materialized_series())
59
}
60
61
pub fn export_series(s: &Series) -> SeriesExport {
62
let field = s
63
.dtype()
64
.to_arrow_field(s.name().clone(), CompatLevel::newest());
65
let schema = Box::new(ffi::export_field_to_c(&field));
66
67
let mut arrays = (0..s.chunks().len())
68
.map(|i| {
69
// Make sure we export the logical type.
70
let arr = s.to_arrow(i, CompatLevel::newest());
71
Box::into_raw(Box::new(ffi::export_array_to_c(arr.clone())))
72
})
73
.collect::<Box<_>>();
74
75
let len = arrays.len();
76
let ptr = arrays.as_mut_ptr();
77
SeriesExport {
78
field: schema.as_ref() as *const ArrowSchema as *mut ArrowSchema,
79
arrays: ptr,
80
len,
81
release: Some(c_release_series_export),
82
private_data: Box::into_raw(Box::new(PrivateData { arrays, schema }))
83
as *mut std::os::raw::c_void,
84
}
85
}
86
87
/// # Safety
88
/// `SeriesExport` must be valid
89
pub unsafe fn import_series(e: SeriesExport) -> PolarsResult<Series> {
90
let field = ffi::import_field_from_c(&(*e.field))?;
91
92
let pointers = std::slice::from_raw_parts_mut(e.arrays, e.len);
93
let chunks = pointers
94
.iter()
95
.map(|ptr| {
96
let arr = std::ptr::read(*ptr);
97
import_array(arr, &(*e.field))
98
})
99
.collect::<PolarsResult<Vec<_>>>()?;
100
101
Series::_try_from_arrow_unchecked_with_md(
102
field.name.clone(),
103
chunks,
104
field.dtype(),
105
field.metadata.as_deref(),
106
)
107
}
108
109
/// # Safety
110
/// `SeriesExport` must be valid
111
pub unsafe fn import_series_buffer(e: *mut SeriesExport, len: usize) -> PolarsResult<Vec<Series>> {
112
let mut out = Vec::with_capacity(len);
113
for i in 0..len {
114
let e = std::ptr::read(e.add(i));
115
out.push(import_series(e)?)
116
}
117
Ok(out)
118
}
119
120
/// # Safety
121
/// `SeriesExport` must be valid
122
pub unsafe fn import_df(e: *mut SeriesExport, len: usize) -> PolarsResult<DataFrame> {
123
let mut out = Vec::with_capacity(len);
124
for i in 0..len {
125
let e = std::ptr::read(e.add(i));
126
let s = import_series(e)?;
127
out.push(s.into())
128
}
129
Ok(DataFrame::new_no_checks_height_from_first(out))
130
}
131
132
/// Passed to an expression.
133
/// This contains information for the implementer of the expression on what it is allowed to do.
134
#[derive(Copy, Clone, Debug, Default)]
135
#[repr(C)]
136
pub struct CallerContext {
137
// bit
138
// 1: PARALLEL
139
bitflags: u64,
140
}
141
142
impl CallerContext {
143
const fn kth_bit_set(&self, k: u64) -> bool {
144
(self.bitflags & (1 << k)) > 0
145
}
146
147
fn set_kth_bit(&mut self, k: u64) {
148
self.bitflags |= 1 << k
149
}
150
151
/// Parallelism is done by polars' main engine, the plugin should not run its own parallelism.
152
/// If this is `false`, the plugin could use parallelism without (much) contention with polars
153
/// parallelism strategies.
154
pub fn parallel(&self) -> bool {
155
self.kth_bit_set(0)
156
}
157
158
pub fn _set_parallel(&mut self) {
159
self.set_kth_bit(0)
160
}
161
}
162
163
#[cfg(test)]
164
mod test {
165
use polars_core::prelude::*;
166
167
use super::*;
168
169
#[test]
170
fn test_ffi() {
171
let s = Series::new("a".into(), [1, 2]);
172
let e = export_series(&s);
173
174
unsafe {
175
assert_eq!(import_series(e).unwrap(), s);
176
};
177
}
178
}
179
180