Rust 调用 C/Rust 生成的动态库

在始终是 C/C++ 有着更优越性能的情况下,因而之前介绍过多种 其他不同的语言如何加载使用 C/C++ 写的动态库,有 Go, Python, Java 和 C#。在学习 Rust 之时也有类似的需求。本文的做法是要用到第三方库 libloading,这里将参考官方的例子。

先来创建一个动态库,使用和 Go 调用 C 写的动态库完整例子(Linux版) 一文中相同的例子,add.c 代码内容如下

在 Linux 中使用如下命令编译出 libadd.so 动态库文件 阅读全文 >>

Rust 语言学习笔记(五)

终于来到了 Rust 的精髓所在了,那就是使之不依赖于垃圾回收又能保障内存安全且高效运行的所有权系统(Ownership System)。想要用 Rust 做一个稍显规模项目必定绕不过它,所有权系统包括所有权(Ownership), 借用(Borrowing), 生命周期(Lifetimes)。

以下概念的复述基本是从 《Rust编程: 入门, 实战与进阶》一书中而来,那里面有些内容是来自于官方的 The Rust Programming Languge - Understanding Ownership

所有权系统的基本概念

Rust 的编程语法很快就能上手,让学习 Rust 曲线陡然大增的也就是这个所有权系统。所有权检测在编译期完成,Rust 能编译出来的代码就是安全高效的。要理解 Rust 的所有权系统必须首先明白以下两组概念:

  1. 栈内存(Stack),值语义(Value Semantic),按位复制(浅复制)(Shallow Copy),复制语义(Copy Semantic)
  2. 堆内存(Heap), 引用语义(Reference Semantic), 深复制(Deep Copy),移动语义(Move Semantic), 借助(Borrowing)

和其他语言一样,大小固定的所有基本类型都可以存储在栈上,栈上存取数据总是在栈顶操作,很快,而访问堆内存需要搜索内存地址。所有权系统的主要任务是用来跟踪堆上的数据,即引用语义的数据。 阅读全文 >>

从 Rust 官方文档理解 Ownership

Rust 的 Ownership 感觉仍然很复杂,但 Rust 官方文档 The Rust Programming Language - Understanding Ownership 所费篇幅似乎并不多。下面就阅读该文档并记录下来对 Rust Ownership 的理解,相信官方的文档会表述的比准确而清晰。

本文中对 Ownership, Move, Reference, Dereference, Mutable, Immutable, Borrow, Owner, Stack, Heap, Scope 等词不进行翻译,以免走样。同时在阅读过程中不进行过度的联想,不与 C/C++ 的引用, 指针, 指针的指针进行关联,力求做一个完全不会 C/C++ 的 Rust 初学者。

Ownership 是 Rust 独一无二的特性。内存管理一般是两种,显式分配与释放和 GC, 这两种的弊端无需多说。Rust 另辟溪径,用 Owership 的一系列的规则来指导怎么管理内存,编译期保证程序运行期的内存安全性,不影响运行时性能。学习 Rust 的过程中需要很长时间去适应 Ownership, 从 Rust 开发者(Rustacean) 的经验来说是:随着对 Ownership 的掌握,越来轻松自然的写出安全高效的代码(希望如此)。 阅读全文 >>

Rust 语言学习笔记(四)

试手了一下 Rust, 发现止今所学知识尚浅,不少情况处理起来很是茫然,比如经常得到的值是 Result 或 Option, 有时候要 .unwrap(), 有时得后面加个问号,或 .await。还有从自定义函数里返回一个引用都不容易,到处是 move, borrow, owner, lifetime 之类的错误信息。所以说,快充五分钟还真不敢上路,继续学习 Rust 的 Result, 说起它又必须与 Rust 的错误处理联系起来。

编程语言在处理错误无外乎就两种哲学

  1. 得到正确的结果或触发异常,异常不就地处理则向外传播
  2. 总是能得到一个结果,于结果中获知是否有异常,如 Option<T>, Result<T, E>

其实本人更钟爱前一种方式,因为正常逻辑可以更流畅的表达,不至于被众多的 if 语句所打断; 而异常的话可以就地解决,或者延迟到某处去集中处理。Java 多是用第一种方式,所以某些框架尽量使用 Unchecked 异常,不强制插入 try/catch 块。

第二种方式,在 shell 或 C++ 很常见,比如 shell 下每调用一个命令都有返回数值, 即 $?, 0 为正常,非 0 为有错误; C++ 的 GetLastError() 也是一样的意思。

现在所学的 Rust 在处理结果和错误时,采用了第二种方式,不过使用上 Rust 的模式匹配处理起 Option<T>, Result<T, E> 倒也不难,而且 Option<T> 和 Result<T, E> 这样的返回结果还用来向上传播异常,出错时还能追踪到异常栈。 阅读全文 >>

Rust 语言学习笔记(三)

引用与解除引用

觉得还是有必要继续深入学习一下 Rust 再练手,毕竟仍然看到 & 和 * 符号还有些恍惚,大概就是 C/C++ 里的取地址和取值操作吧,实际上也确实类似。只是叫法略有不同, 还有就是在 C/C++ 多用了指针的概念。

在 C/C++ 中, &:称作 Address-of Operator, 在 Rust 中称作 Reference Operator, 而 * 在 C/C++ 和 Rust 中都叫做 Dereference Operator。以前学 C/C++ 经常被一系列的 &, * 打晕了头,如今参考了它们的英文名称立刻变得清晰了起来。

就像当初看汇编各种寻址方式弄得头都大了,其实也就是依照约定。 阅读全文 >>

Rust 语言学习笔记(二)

再继续快速学习一下 Rust 的以下几个知识点,就可以开始着手做点小工具了

  1. 基本数据类型
  2. 复合数据类型
  3. 基本的流程控制

Rust 设计为有效使用内存考虑的,它提供了非常细力度的数据类型,如整数分为有无符号,宽度从 8 位到 128 位,分别表示为 i8, u8, u128 等。浮点数有 f32 和 f64,以及 bool 和 range 类型。

元组

元组和 Python 的元组用法类似,Immutable, 可混合类型

数组

数组类型中的元素类型相同,表示为  [T; n], T 为类型,n 为元素个数 阅读全文 >>

Rust 语言学习笔记(一)

学了不少编程语言,多数是离不开垃圾回收的,要么像 C++ 仍然是过于复杂,对于通用,编译型编程语言 Rust 是个不错的选择, Rust 不需要垃圾回收器。Rust 是由 Mozilla 主导开发的,设计准则为 "安全,并发,实用", 支持函数式,并发式,过程式以及面向对象的编程风格。Rust 能达到与 C++ 接近的性能,它又是编译型语言,编译出来二进制文件执行时不再依赖于运行时。Rust 有自带的 Cargo 作为依赖管理与构建工具,免除了关键工具的选择综合症。AWS 在今年也推出了 Rust 的 AWS SDK, 所以学习 Rust 的过程中也打算使用它来操作 AWS 的资源。

Rust 的 Hello World

在 macOS 下的安装

$ brew install rust

$ curl https://sh.rustup.rs | sh    # 安装
$ rustc --version                              # 查看版本
$ rustup update                               # 更新
$ rustup self uninstall                     # 卸载

当前 Rust 版本为 1.74.0, 安装后有 rustc, rustdoc, rust-gdb, rust-lldb, cargo 等相关命令

创建一个并运行 hello

cargo new 生成的项目有一个标准布局,不像 C++ 的项目那么自由混乱。自然的,Cargo.toml 中可配置项目的信息及管理依赖。 阅读全文 >>