【发布时间】:2022-08-17 04:43:32
【问题描述】:
我正在构建一个 raku 模块来使用 Rust Polars - 通过 Rust ffi。
通常它通过来回传递不透明的容器(SeriesC、ExprC 等)来工作。
我第一次通过 Expr .apply 函数看起来像这样(摘录):
use libc::c_char;
use libc::size_t;
use std::slice;
use std::ptr;
use std::ffi::*; //{CStr, CString,}
use polars::prelude::*;//{CsvReader, DataType, DataFrame, Series};
use polars::prelude::{Result as PolarResult};
use polars::lazy::dsl;
use polars::lazy::dsl::Expr;
pub struct SeriesC {
se: Series,
}
impl SeriesC {
fn new<T>(name: String, data: Vec::<T>) -> SeriesC
where Series: NamedFrom<Vec<T>, [T]>
{
SeriesC {
se: Series::new(&name, data),
}
}
// ...
}
type AppMap = extern fn(appmap: *mut SeriesC) -> SeriesC;
pub struct ExprC {
pub inner: dsl::Expr,
}
impl ExprC {
fn sum(&self) -> ExprC {
self.clone().inner.clone().sum().into()
}
// ... some more Exprs
fn apply(&self, appmap: AMWrap) -> ExprC {
let o = GetOutput::from_type(DataType::UInt32);
self.clone().inner.clone().apply(appmap, o).into()
}
}
// ffi helper functions
#[no_mangle]
pub extern \"C\" fn ex_sum(ptr: *mut ExprC) -> *mut ExprC {
let ex_c = unsafe {
assert!(!ptr.is_null());
&mut *ptr
};
Box::into_raw(Box::new(ex_c.sum()))
}
type AppMap = fn(*mut SeriesC) -> SeriesC;
type AMWrap = fn(Series) -> Result<Series>;
#[no_mangle]
pub extern \"C\" fn ex_apply(ptr: *mut ExprC, appmap: AppMap) -> *mut ExprC {
let ex_c = check_ptr(ptr);
fn c2s(se_c: SeriesC) -> Result<Series> {
Ok(se_c.se.into_series())
}
fn s2c(series: Series) -> *mut SeriesC {
let mut se_c = SeriesC::new::<u32>(\"dummy\".to_owned(), [].to_vec());
se_c.se = series;
Box::into_raw(Box::new(se_c))
}
fn compose<A, B, C, F, G>(f: F, g: G) -> impl Fn(A) -> C
where
F: Fn(B) -> C,
G: Fn(A) -> B,
{
move |x| f(g(x))
}
let am_wrap_a = compose(appmap, s2c);
let am_wrap_b = compose(c2s, am_wrap_a);
Box::into_raw(Box::new(ex_c.apply(am_wrap_b)))
}
这种技术适用于 Expr\'s,例如 .sum()
对于.apply(),如您所见,我从 raku 端(未显示)得到一个回调,其类型为 AppMap 接受并返回 SeriesC 容器,我将其组合成 AMWrap 类型,该类型根据函数指针的要求接受并返回 Series传递给 Expr.apply 方法。
我已经设法将 Rust 错误减少到一个:
root@83471ed9aab4:~/raku-Dan-Polars/dan# cargo build
Compiling dan v0.1.0 (/root/raku-Dan-Polars/dan)
error[E0308]: mismatched types
--> src/lib.rs:881:39
|
871 | fn compose<A, B, C, F, G>(f: F, g: G) -> impl Fn(A) -> C
| --------------- the found opaque type
...
881 | Box::into_raw(Box::new(ex_c.apply(am_wrap_b)))
| ^^^^^^^^^ expected fn pointer, found opaque type
|
= note: expected fn pointer `fn(polars::prelude::Series) -> std::result::Result<polars::prelude::Series, PolarsError>`
found opaque type `impl Fn(polars::prelude::Series)-> std::result::Result<polars::prelude::Series, PolarsError>`
For more information about this error, try `rustc --explain E0308`.
error: could not compile `dan` due to previous error
但是我无法理解如何将 compose 的返回类型连接到 AMWrap 类型。请问你能帮我吗?
这是 Cargo.toml 的完整性:
1 [package]
2 name = \"dan\"
3 version = \"0.1.0\"
4 edition = \"2021\"
5
6 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7
8 [dependencies]
9 libc = \"0.2.126\"
10 polars = {version = \"0.22.1\", features = [\"lazy\"]}
11 ffi-convert = \"0.5.0\"
12
13 [lib]
14 name = \"dan\"
15 path = \"src/lib.rs\"
16 crate-type = [\"cdylib\"]
标签: rust rust-polars