15个不稳定版本
0.9.0 | 2023年12月6日 |
---|---|
0.8.0 | 2023年1月27日 |
0.7.1 | 2022年12月5日 |
0.7.0 | 2022年11月15日 |
#555 in Rust模式
每月32次下载
13KB
hs-bindgen
为Haskell生成Rust的C-FFI绑定的便捷宏。
此库旨在与通过 cargo-cabal
配置的项目最佳配合。
注意。 MSRV是 1.64.0,因为它使用 core_ffi_c
功能。
示例
一个最小示例是将函数注释如下
use hs_bindgen::*;
/// Haskell type signatures are auto-magically inferred from Rust function
/// types! This feature could slow down compilation, and be enabled with:
/// `hs-bindgen = { ..., features = [ "full" ] }`
#[hs_bindgen]
fn greetings(name: &str) {
println!("Hello, {name}!");
}
这将被扩展为(您可以用 cargo expand
尝试自己)
use hs_bindgen::*;
fn greetings(name: &str) {
println!("Hello, {name}!");
}
#[no_mangle] // Mangling makes symbol names more difficult to predict.
// We disable it to ensure that the resulting symbol is really `__c_greetings`.
extern "C" fn __c_greetings(__0: *const core::ffi::c_char) -> () {
// `traits` module is `hs-bindgen::hs-bindgen-traits`
// n.b. do not forget to import it, e.g., with `use hs-bindgen::*`
traits::FromReprC::from(greetings(traits::FromReprRust::from(__0),))
}
一个更完整的示例,当我们现在尝试将自定义类型传递到我们的接口时
use hs_bindgen::{traits::FromReprRust, *};
use std::marker::PhantomData;
/// A custom Rust data-type, `#[repr(transparent)]` is not useful here
/// since `FromReprRust` trait will offers the constructor we need to construct
/// our type out of a C-FFI safe primitive data-structure.
struct User<T: Kind> {
name: String,
kind: PhantomData<T>,
}
/** Overly engineered traits definitions just for the sake of demonstrating
limitations of this example, this isn't at all needed by default */
struct Super;
trait Kind {
fn greet(name: &str) -> String;
}
impl Kind for Super {
fn greet(name: &str) -> String {
format!("Hello, {}!", name)
}
}
/// Declare targeted Haskell signature, return types should be wrapped in
/// an IO Monad (a behavior enforced by safety concerns)
#[hs_bindgen(hello :: CString -> IO CString)]
fn hello(user: User<Super>) -> String {
Super::greet(&user.name)
}
/** n.b. functions wrapped by `#[hs_bindgen]` macro couldn't be
parametrized by generics (because monomorphisation occurs after macro
expansion during compilation, and how rustc assign unmangled symbols to
monomorphised methods are AFAIK not a publicly specified behavior), but
this limitation didn’t apply to `hs-bindgen-traits` implementations! */
impl<T: Kind> FromReprRust<*const i8> for User<T> {
fn from(ptr: *const i8) -> Self {
User::<T> {
name: <String as FromReprRust<*const i8>>::from(ptr),
kind: PhantomData::<T>
}
}
}
设计
首先,我要感谢 Michael Gattozzi,他实现了 一个不再维护的绑定生成实现,并且 他的写作 和指导真正帮助我快速启动这个项目。
我尝试用以下核心设计原则来构建 hs-bindgen
-
简单性: 遵循KISS UNIX哲学的简约主义,意味着在这里我试图从不重新实现Rust编程语言已经处理的功能(解析代码、推断类型等),而是依赖于宏和特质的系统功能。例如,这个代码中唯一剩下的解析部分是Haskell函数签名(鉴于授权的C-FFI安全类型的特性集,这是微不足道的);
-
模块化: 此库旨在适用于更广泛的用途,因此此库应该可以在
#[no_std]
设置下工作,并且大多数功能可以禁用。例如,由antlion
库提供的类型推断是可选的; -
稳定性:该库在稳定C ABI(具有良好定义的内存布局约定)范围内不实现任何技巧,并确保在不违反此安全规则的前提下提供易用性。任何
rustc
或GHC更新都无法打破任何魔法!
致谢
⚠️ 这仍然是一个工作实验,尚未准备好投入生产。
hs-bindgen
受到了其他互操作性项目的很大启发,如wasm-bindgen
和PyO3
。
该项目是作为IOG承包商的工作任务的一部分。
许可证
根据您的选择,该许可证受Apache许可证版本2.0或MIT许可证的约束。
除非您明确声明,否则根据Apache-2.0许可证定义的,您有意提交给本项目的内容,将按上述方式双重许可,没有任何额外的条款或条件。
依赖关系
~0.6–1.2MB
~27K SLoC