开发者生态
morning
显示 HN:Hsrs – Rust 的类型安全 Haskell 绑定生成器
2026-05-19
1 阅读
suis_siva
hsrs 使用类型安全、自动生成的 FFI 绑定从 Haskell 调用 Rust。注释您的 Rust 类型和函数,运行代码生成器,并获得惯用的 Haskell 来为您处理内存管理、序列化和类型转换。快速开始 1. 注释您的 Rust 代码 # [ hsrs :: module ] mod canvas { # [ hsrs :: value_type ] pub struct Point { pub x : i32 , pub y : i32 , } # [ hsrs :: data_type ] pub struct Canvas { points : Vec < Point > , } impl Canvas { # [ hsrs :: function ] pub fn new ( ) ->自我{自我{点:vec! [ ] } } # [ hsrs :: function ] pub fn add_point ( & mut self , p : Point ) { self .点。推(p); } # [ hsrs :: function ] pub fn count ( & self ) -> u64 { self .点。 len ( ) as u64 } } } 2. 生成 Haskell 绑定 Cargo install hsrs-codegen hsrs-codegen src/lib.rs -o Bindings.hs 3. 使用 from Haskell import Bindings main :: IO () main = do c <- new addPoint c ( Point 10 20 ) n <- count c print n -- 1 就是这样。内存通过ForeignPtr自动管理,像Point这样的复杂类型通过Borsh跨越边界进行序列化。设置 Rust 端 — 将 hsrs 添加到您的 crate: [ lib ] crate-type = [ " lib " , " staticlib " ] [ dependency ] hsrs = " 0.1 " Haskell 端 — 添加 hsrs 运行时包: build-depends : hsrs >= 0.1 && < 0.2 这会自动引入 Borsh 序列化 — 不需要额外的依赖项。您可以注释的内容 注释 作用 Haskell 结果 #[hsrs::data_type] 通过指针传递的不透明结构具有自动清理功能的foreignPtr newtype #[hsrs::enumeration] C 兼容枚举 ( repr(u8) ) 具有模式同义词的 Word8 newtype #[hsrs::value_type] 通过 Borsh 导出的 Borsh 数据记录按值传递的结构 #[hsrs::function] 导出的方法over FFI 类型安全 Haskell 包装器 #[hsrs::module] 将数据类型与其方法分组生成类型的所有 FFI 粘合 Result 变为 Either E T ,Option 变为 Maybe T ,Vec 变为 [T] ,并且 String 变为 Text — 所有这些都通过 Borsh 透明地序列化。支持的类型 Rust Haskell Transfer i8 , i16 , i32 , i64 Int8 , Int16 , Int32 , Int64 Direct (C FFI) u8 , u16 , u32 , u64 Word8 , Word16 , Word32 , Word64 Direct (C FFI) bool CBool Direct (C FFI) usize / isize Word64 / Int64 Direct (C FFI) #[hsrs::enumeration] enum Word8 newtype + Patterns Direct (C FFI) #[hsrs::value_type] struct data record Borsh String Text Borsh Vec [T] Borsh Option Maybe T Borsh Result E T Borsh Platform 注释 usize 和 isize 分别映射到 Word64 和 Int64。这与 64 位平台(x86_64、aarch64)匹配。如果您的目标是 32 位平台,请注意值可能会被截断。完整示例 具有枚举、值类型、结果和选项 Rust 的小型 VM # [ hsrs :: module ] mod quecto_vm { # [derive ( Debug , PartialEq , Eq ) ] # [ hsrs :: enumeration ] pub enum Register { Reg0 , Reg1 , Count } # [derive ( Debug , PartialEq , Eq ) ] # [ hsrs :: value_type ] pub struct Point { pub x : i32 , pub y : i32 } # [derive ( Debug , PartialEq , Eq ) ] # [ hsrs :: value_type ] pub struct VmError { pub code : u32 } # [ hsrs :: data_type ] pub struct QuectoVm { 寄存器 : [ i64 ; } Register :: Count as usize ] , Clock : usize , } impl QuectoVm { # [ hsrs :: function ] pub fn new ( ) -> Self { /* ... */ } # [ hsrs :: function ] pub fn store ( & mut self , r : Register , v : i64 ) { /* ... */ } # [ hsrs :: function ] pub fn snapshot ( & self ) -> Point { /* ... */ } # [ hsrs :: function ] pub fn safe_div ( & mut self , a : Register , b : Register ) -> Result < i64 , VmError > { /* ... */ } # [ hsrs :: function ] pub fn nonzero ( & self , r : Register ) -> Option < i64 > { /* ... */ } } }生成的 Haskell newtype Register = Register Word8 deriving ( Eq , Show , Storable ) 通过 Word8 模式 Reg0 :: Regist