13 个不稳定版本 (3 个破坏性更新)

0.3.8 2024 年 6 月 29 日
0.3.7 2024 年 6 月 28 日
0.3.6 2024 年 3 月 14 日
0.3.4 2023 年 12 月 27 日
0.0.2 2023 年 12 月 10 日

#350 in FFI

Download history 18/week @ 2024-05-26 11/week @ 2024-06-02 6/week @ 2024-06-09 39/week @ 2024-06-16 284/week @ 2024-06-23 67/week @ 2024-06-30 36/week @ 2024-07-07 160/week @ 2024-07-28

每月 198 次下载
rust2go 中使用

MIT/Apache

78KB
1.5K SLoC

Rust2Go

Crates.io

Rust2Go 是一个项目,为用户提供了一种简单高效的方法来从 Rust 调用 Golang,并支持原生的异步。

功能

  • 从 Rust 到 Golang 的同步和异步调用
  • 高效的数据交换:无需序列化或套接字通信,只需 FFI
  • 简单的接口设计:除了本地的 Rust 之外,没有新的 IDL

使用方法

  1. 在受限制的 Rust 语法中定义结构体和调用接口,并将生成的代码包含在同一文件中。
  2. 使用以下命令生成 golang 代码:rust2go-cli --src src/user.rs --dst go/gen.go
  3. 为您项目编写一个 build.rs
  4. 然后您可以在 Rust 项目中使用生成的实现来调用 golang!

有关详细示例,请参阅 示例项目

关键设计

详细设计细节可在此文章中找到: Rust-Go FFI 框架的设计与实现

为什么这么快?

为了实现最佳性能,本项目不是基于通信,而是基于 FFI 通过特殊编码的数据进行传递。为了将内存操作减少到最小,满足特定内存布局的数据直接通过引用传递,而不是复制。

例如,Vec<u8>String 被表示为一个指针和长度。然而,像 Vec<String>Vec<Vec<u8>> 这样的结构体需要中间表示。为了将内存分配的数量减少到一次,我使用一个预计算的尺寸缓冲区来存储这些中间结构。

内存安全

在 Golang 一侧,它接收的数据是从 Rust 引用的。Rust 一侧将尽力确保在调用期间数据的有效性。因此,Golang 一侧可以任意实现处理器,但在函数生命周期外泄漏数据时需要手动深度复制。

在 Rust 一侧,需要确保在 future 释放时,回调 ffi 操作的槽指针和用户参数有效。这是通过实现原子槽结构和提供一个 [drop_safe] 属性来实现的,该属性要求用户以所有权的形式传递参数。

工具链要求

  • Golang: >=1.18
    • 对于 >=1.18 && < 1.20:使用 --go118 生成 golang 代码
    • 对于 >=1.20:正常生成 golang 代码
  • Rust: 如果要使用异步,需要 >=1.75

里程碑

初始版本

  • IDL(在 Rust 中)解析
  • Go 代码生成
  • 构建脚本助手
  • 基本数据类型和转换生成
  • Rust 实现
  • 使用 Future 和基本同步原语

基本能力增强

  • 支持更复杂的数据类型
  • 支持用户传递引用
  • 更优雅的代码生成实现
  • 更好的构建缓存控制
  • 支持 Golang 接口(将用户代码与生成代码分开)
  • 支持动态链接
  • Golang 辅助库

性能优化

  • 基于共享内存的实现

扩展功能

  • 支持从 Golang 调用 Rust

致谢

本项目受到 fcplug 的启发。

依赖项

~5–14MB
~191K SLoC