osnosn

  博客园 :: 首页 :: 博问 :: 闪存 :: :: 联系 :: 订阅 订阅 :: 管理 ::

rust语言_学习笔记

转载注明来源: 本文链接 来自osnosn的博客,写于 2023-12-10.

安装 rust

cargo 的 config 设置

  • 更换 ustc 源,使用代理。设置缺省registry。见【rust cargo 配置】。

crate库

  • 搜索

  • cli 命令行参数解析 【clap
    应该还有更简单小巧的库。【Collected benchmarks for arg parsing crates written in Rust
    • getopt, 基本符合POSIX参数解析规则。似乎仅支持短参数
    • getopt3, 符合GNU参数解析规则。似乎仅支持短参数
    • clap_lex,用两个循环去match。短参数支持合并写法 "-ab"。
    • lexopt可用,和libc中的getopt很像。短参数支持合并写法 "-ab"。
      还可以通过 bin_name() 获取当前的程序名。执行文件自身的名称。
    • xflags,用声明宏。 "-a -b"不支持合并写法 "-ab"。
    • argh,用自定义宏(#derive). "-a -b"不支持合并写法 "-ab"。
    • gumdrop,挺高级的。
    • pico-args,似乎不好用。
  • 异步,多线程
  • json解析
  • bincode 二进制序列化/反序列化
    二进制自压缩序列化bincode模块
    或者,rust标准库的 u32::from_le_bytes(),123_u32.to_le_bytes(),f32::from_le_bytes(),12.3_f32.to_le_bytes(),
  • image库
  • sqlite3
    • rusqulite可用。需要安装 apt install libsqlite3-dev
      如果要静态编译,或编译window程序,Cargo.toml 中要加入 features = ["bundled"]
      (gnu 相关的交叉编译都OK。musl 相关的交叉编译,都会失败,没找到解决办法)
      多线程中使用,每个线程单独建立一个连接(Connection::open())就行,要求sqlite-3.7.0以上。【1】【2】【3
      会碰到,编译器无法确定泛型的具体类型,需要用 turbofish语法,在调用函数时指定类型。
      • 用到的函数,
        Connection::open(),execute(),query_row(),prepare(),close(),
        Statement::execute(),insert(),query(),query_map(),exists(),query_row(),finalize(),
        Row::get(),
        Rows::next(),map(),get(),...
    • sqlite3
  • 读取 ini文件
    • light_ini, ini_core, tini,
    • ini_lib】 简单,可用
  • gui
    • iced
    • fltk
      • 需要 cmake-3.15.0 以上。
      • 交叉编译x86_64-pc-windows-gun, i686-pc-windows-gnu 成功。
        在 main.rs第一行,加入 #![windows_subsystem = "windows"],运行时不会出现console窗口。
      • 其他的target编译失败。可能是缺少 libx...的包。
      • 在aarch64的UOS中编译,cmake版本太低,编译失败。
  • 把文件/目录打包到执行文件中
  • 获取Utc,Local时间,
    *用 use chrono::{Local, Utc};
    • 在openwrt中,Local时间的获取, 依赖 /etc/localtime 文件。
      如果localtime文件不存在,则获取的是Utc时间。
      这个表现,和golang获取Local时间是一样的。
    • time v0.2.27
  • base64 编码解码, base64_light
  • 正则, regex::Regex
  • 文件/路径/目录 操作, std::path:Path
  • 文件读取, std::fs
  • memmap2 文件的内存映射。
  • bzip2 压缩
  • 时间计算, std:time::Duration
  • hdf5
  • mlua
    • features: lua54 需要 apt install lua5.4 liblua5.4-dev
      Cargo.toml 中加入 features= ["lua54","vendored"],在debian x86_64 rustc-1.74中,交叉编译,全部成功。(2024-03测)
      RUSTFLAGS='-C target-feature=+crt-static' cargo build --release --target x86_64-unknown-linux-gnu
      RUSTFLAGS='-C target-feature=+crt-static' cargo build --release --target x86_64-unknown-linux-musl
      TARGET_CC=i686-w64-mingw32-gcc RUSTFLAGS='-C target-feature=+crt-static' cargo build --release --target i686-pc-windows-gnu
      TARGET_CC=x86_64-w64-mingw32-gcc RUSTFLAGS='-C target-feature=+crt-static' cargo build --release --target x86_64-pc-windows-gnu
      TARGET_CC=aarch64-linux-gnu-gcc RUSTFLAGS='-C linker=aarch64-linux-gnu-gcc -C target-feature=+crt-static' cargo build --release --target aarch64-unknown-linux-gnu
      #使用openwrtSDK,交叉编译mipsel-musl #成功#
      
    • features: luajit 或 luajit52 需要 apt install luajit2 libluajit2-5.1-dev
      Cargo.toml 中加入 features= ["luajit52","vendored"],在debian x86_64 rustc-1.74中,交叉编译,部分失败。(2024-03测)
      RUSTFLAGS='-C target-feature=+crt-static' cargo build --release --target x86_64-unknown-linux-gnu
      #失败#RUSTFLAGS='-C target-feature=+crt-static' cargo build --release --target x86_64-unknown-linux-musl
      #失败#TARGET_CC=i686-w64-mingw32-gcc RUSTFLAGS='-C target-feature=+crt-static' cargo build --release --target i686-pc-windows-gnu
      TARGET_CC=x86_64-w64-mingw32-gcc RUSTFLAGS='-C target-feature=+crt-static' cargo build --release --target x86_64-pc-windows-gnu
      TARGET_CC=aarch64-linux-gnu-gcc RUSTFLAGS='-C linker=aarch64-linux-gnu-gcc -C target-feature=+crt-static' cargo build --release --target aarch64-unknown-linux-gnu
      #使用openwrtSDK,交叉编译mipsel-musl #失败#
      
    • features: luau 好像不需要额外安装。
    • userdata 参考【userdata.rs】,【mlua-userdata-json】,【How to store functions in UserData

Rust中文文档

  • 看其中的【Rust 程序设计语言】,好难。
    • rust语言 本身似乎不复杂,"所有权"也不难理解。
    • "泛型",也好理解。"生命周期",也好理解。
    • "Trait",比较复杂,没看明白做啥用的。
    • "宏"好复杂。又是一种独立的语法。
      包含,用macro_rules!的声明宏,和三种过程宏 (自定义宏 #[derive],类属性宏,类函数宏)。

笔记

创建项目

  • 修改~/.cargo/config。更换 ustc 源,使用代理。设置缺省registry。见【rust cargo 配置】。
  • 选择一个目录,cargo new lexopt-test 创建一个项目。看【cargo-new(1)
  • 搜索 crate,cargo search lexopt,看【cargo-search(1)
  • 添加 crate "lexopt"
    • 方法1:执行 cargo add lexopt,看【cargo-add(1)
      会自动获取最新的版本,并写入 Cargo.toml
      • 删除create,执行 cargo remove lexopt
      • 查看本项目使用的crate,cargo tree
    • 方法2:在 docs.rs 中搜索 lexopt,找到它的版本号。
      手工修改 Cargo.toml,在 [dependencies] 下面,插入一行,
      lexopt = "0.3.0"
      然后执行 cargo update,把这个crate 拉取下来。
      • 删除crate,编辑 Cargo.toml 删除lexot那行。执行cargo update即可。
  • 编写 src/main.rs 使用这个 crate。
    从 【lexopt】 抄它的 example。
  • cargo clean 清理缓存。
  • cargo check 检查。
  • cargo fmt 格式化源码文件。
  • cargo build 编译。
  • cargo vendor pkg 把当前项目依赖的所有包,下载到当前目录的pkg目录中。
    不要下载到 ./ 当前目录,会把当前目录中的所有文件清空

rust 中引入其他rs文件

编程中的问题记录

  • 出现 note: #[warn(non_snake_case)] on by default 警告。
    你的项目名称不是蛇形命名。即不是 "单词+下划线+单词" 的命名方式。
    在 src/main.rs 的第一行加入 #![allow(non_snake_case)] 允许非蛇形命名,即可。

  • 查找标准库的functions或methods, 去 【doc.rust-lang.org/std】搜索

    搜 Some 或 Option,就能找到很多教程中没有介绍的methods。如 ok_or(), map_or(), unwrap_or()
    见,【Enum std::option::Option】,str【Primitive Type str】,【Struct std::string::String】,

  • turbofish-涡轮鱼,语法
    编译时报错,编译器无法确定泛型的具体类型。那么,需要用 turbofish语法,在调用函数时指定类型。
    比如 sqlite的连接 conn,调用conn.query_row("select ...",[],|row| row.get(0));
    会报错 cannot infer type of the type parameter T declared on the method get, 编译器建议使用 row.get::<usize, T>(0)
    如果返回的是String,就改为 row.get::<usize, String>(0)

  • 要把字符串变量传入 子线程,不能用 &str,编译会报错"life time"不够。应该用 String 或 Arc<String> 就没问题了。

  • 调试变量,除了用println!(), 还可以用 dbg!()。 dbg!(用&引用变量)。

  • 发布配置 Profile】,【Cargo Book/Profiles】,
    优化 Rust 程序编译体积】,【rust 性能优化】,【Cargo使用指南|发布配置 Profile】,【最小化 Rust 二进制文件大小】,

    # 可以考虑这几项
    [profile.release]
    strip = true
    opt-level = "s"
    lto = true
    panic = "abort"
    #codegen-units = 1
    
    # 如果用了 regex的简单匹配,可以限定 features,只启用"std" features,可以减少体积。
    [dependencies]
    regex = { version = "1.10.2", default-features = false, features = ["std"] }
    
  • 一个项目中,教程说,可以包含多个二进制crate。
    cargo new 创建的项目(package),默认有src/main.rs
    如果手工创建 src/bin/test1.rssrc/bin/test1.rs,就能编译出 3个二进制程序。
    如果 src/bin/test1.rs 中要使用 module(模块),考虑以下方法。

  • rust course/工作空间Workspace】,【Cargo Book/Workspaces】,【知乎/workspace详解
    手动创建 Cargo.tmol

    [workspace]
    resolver="2"  #Edition2021 默认为 2
    members = ["pkg2", "pkg3"] #写入包含的多个项目
    

    如果子项目中有 [profile.release],整个copy到 workspace目录的 Cargo.toml中。注释掉子项目中 Cargo.toml的[profile.release]

  • 条件编译 Features
    在代码块前加一行 #[cfg(feature = "myfeature")]#[cfg(not(feature = "myfeature"))]
    编译时指定了myfeature才会被选择编译。
    然后在 Cargo.toml中加入:

    [features]
    myfeature = []          #如果没有相关依赖
    myfeature = ["xxx1"]   #如果有别的依赖
    default = []            #默认不开启这个feature
    default = ["myfeature"] #默认开启这个feature
    
  • rust条件编译】,【条件编译

    #[cfg(target_os = "windows")]
    { //...win代码
    }
    #[cfg(target_os = "linux")]
    { //...Linux代码
    }
    if cfg!(target_os = "windows") {
      // windows系统要执行的代码段
    } else if cfg!(target_os = "linux") {
      // linux系统要执行的代码段
    }
    #[cfg(not(target_os = "linux"))]
    { // 非Linux 的代码
    }
    #[cfg(all(unix, target_pointer_width = "32"))]
    { // 32位 unix
    }
    
  • Cargo 为 crates 设置的环境变量
    程序中用这种方式获取 let version = env!("CARGO_PKG_VERSION");
    Cargo手册.环境变量】,【The Cargo Book.Environment Variables

  • Rust中 #[derive()]是什么?怎么理解】,【Rust 参考手册/派生 derive — 自动部署 trait实现】,【Rust 版本指南/自定义 Derive】,
    Rust 常见20类常见Trait,你熟悉多少?】,【Rust 常见内置 Traits 详解】,【[译] Rust 的内置 Traits, 使用场景, 方式, 和原因

其他

----end----


转载注明来源: 本文链接 https://www.cnblogs.com/osnosn/p/17913222.html
来自 osnosn的博客 https://www.cnblogs.com/osnosn/ .


posted on 2023-12-19 11:14  osnosn  阅读(195)  评论(0编辑  收藏  举报