在树莓派上玩转 Rust :交叉编译

本文面向于对 Rust 和 Linux 有一定基础的读者。

在开始之前,请先确保你已经拥有了一个树莓派,和一台装有 Linux 的物理机或者虚拟机,装好 Rust,并且已经为树莓派刷好了系统(推荐官方系统),能够在你电脑上用 ssh 连接至树莓派。期间你可能会遇到问题,请尝试从文末给出的连接找到答案。

通常,要得到可在树莓派上运行的二进制文件有两种方式。一种是在树莓派上安装 Rust,编译源码并运行。由于树莓派硬件资源的限制,在树莓派上编译 Rust 极其缓慢,尤其是在 zero w 这类型号上,并且编写源码也是件麻烦的事。另一种是在你的电脑上编写源码,交叉编译,并通过 scp 命令发送至树莓派。在开发时,你也可以利用 rsync 工具,将编译好的二进制文件同步至树莓派。

继续阅读

Rust 实战 – 使用套接字联网API 2

图片来自pexels.com

上一节,我们已经实现了一个最小可运行版本。之所以使用Rust而不是C,是因为Rust具备了必要的抽象能力,还能获得跟C差不多的性能。这一节,我们对上一节的代码做必要的封装,顺便还能把unsafe的代码包装成safe的API。

我将上一节的源码放到了这里,你可以去查看。

还记得上一节,我们把使用到的libc中的函数socketbindconnect和结构体sockaddrsockaddr_inin_addr等,在Rust这边定义了出来。实际上,几乎libc中的函数,libc这个crate都帮我们定义好了。你可以去这里查看。编译器和标准库本身也使用了这个crate,我们也使用这个。

首先在Cargo.toml文件的[dependencies]下面加入libc = "0.2":

[dependencies]
libc = "0.2"

接着在main.rs文件上方加入use libc;,也可以use libc as c;。或者你直接简单粗暴use libc::*,并不推荐这样,除非你明确知道你使用的函数来自哪里。并将我们定义的与libc中对用的常量、函数、结构体删除。再添加libc::c::到我们使用那些常量、结构体、函数的地方。如果你是直接use libc::*,除了直接删除那部分代码外,几乎什么都不用做。目前的代码:

继续阅读

Rust 实战 – 使用套接字联网API 1

图片来自pexels.com

虽然标准库已经封装好了 TcpListenerTcpStream 等基础api,但作为Rust 的爱好者,我们可以去一探究竟。本文假设你已经对 Rust 和 Linux 操作系统有了一定了解。

在 Linux 上 Rust 默认会链接的系统的 libc 以及一些其他的库,这就意味着,你可以直接使用libc中的函数。比如,你可以使用 gethostname 获取你电脑的 “hostname”:

use std::os::raw::c_char;
use std::ffi::CStr;

extern {
    pub fn gethostname(name: *mut c_char, len: usize) -> i32;
}

fn main() {
    let len = 255;
    let mut buf = Vec::<u8>::with_capacity(len);
    let ptr = buf.as_mut_ptr() as *mut c_char;

    unsafe {
        gethostname(ptr, len);
        println!("{:?}", CStr::from_ptr(ptr));
    }
}

解释一下上面的代码。

extren 表示“外部块(External blocks)”,用来申明外部非 Rust 库中的符号。我们需要使用 Rust 以外的函数,比如 libc ,就需要在 extren 中将需要用到的函数定义出来,然后就可以像使用本地函数一样使用外部函数,编译器会负责帮我们转换,是不是很方便呢。但是,调用一个外部函数是unsafe的,编译器不能提供足够的保证,所以要放到unsafe块中。

继续阅读