分类目录归档:未分类

为什么rust编译出的可执行文件体积那么大

因为Rust用静态链接(static linking)来编译可执行文件。

也就是说,所有依赖的库,都会编译进去。当然也包含了Rus runtime

可以添加

-C prefer-dynamic

命令行参数, 来让rust编译器是用动态链接。

如果用cargo,这个选项也要传给rustc

cargo rustc --debug  -- -C prefer-dynamic
或者
cargo rustc --release -- -C prefer-dynamic

进一步,在Cargo.toml中配置,也可以减少一些体积

[profile.release]
opt-level = 'z'     # Optimize for size.
lto = true          # Enable Link Time Optimization
codegen-units = 1   # Reduce number of codegen units to increase optimizations.
panic = 'abort'     # Abort on panic
strip = true        # Strip symbols from binary*

https://lifthrasiir.github.io/rustlog/why-is-a-rust-executable-large.html
https://stackoverflow.com/questions/29008127/why-are-rust-executables-so-huge

F2 Status

返回当前目录或者当前应用的相关信息

按照应用规范,这个命令可能用来指出 在UICC的应用的初始化过程已经成功执行,或者终止过程即将执行。

注意:这个之事,也可能用来同步终端和UICC上的应用。

P1 = 0 没有额外的指示,仅仅想知道卡还在不在

P1 = 1 当前应用 已经在终端被初始化(也就是准备好让这张卡入网)

P1= 2 终端准备 关闭uicc上的应用

p2=0 Response parameters and data are identical to the response parameters and data of the SELECT command

p2 =1 The DF name TLV-object of the currently selected application is returned

p2 =c 不要返回额外的数据,我就是看看卡还在不在

6FAD

此EF包含有关操作模式(按照usim类型而不同的模式)的信息。

正常模式(用户登录3GPP网络)

型号批准(在型号批准过程中,允许ME的特定的使用)

基站小区测试(在某个小区在商用之前,进行测试)

制造商特定的用途(允许ME制造商执行专有的自动测试,例如维护阶段)

此文件的内容至少为4个字节,其中前4个字节的含义

1字节 UE operation mode
00 = 正常模式
80 = 类型批准操作
01 = 正常模式+特定设施
81 = 型号批准操作 + 特定
02 = 维护(离线)
04 = 小区测试操作

2-3字节 Additional information
UE操作模式的额外信息
4字节 length of MNC in the IMSI

如果 service n°130 is “available”, 那么这个字节为0
否则,应该为 2 或者 3 表示 MNC的长度为2 或者 3

130号服务是 Support for SUPI of type NSI or GLI or GCI

如130号服务可用,那么 EF_IMSI (6F07)就不应该存在

proactive UICC command通用元素

1命令编号

命令编号是为了满足未来可能出现的多个正在进行的命令(UICC在收到对正在进行的命令的响应之前,发出进一步的命令)。在toolkit规范的这个阶段,还没有对这种多个命令的含义进行详细说明。

在卡会话期间,有主动UICC发出的每个命令都应该有自己的命令编号。编号可以为在01-FE之间的任何十六进制值。命令编号保存在 “命令详细信息”数据对象中.

UICC负责分配命令编号。终端应该记录每条命令的状态和命令编号,直到终端使用TERMINAL RESPONSE向UICC发出命令的结果。

此后,终端可能会擦除有关此命令的所有内部记录。此命令编号可以由UICC分配给新的命令。

UICC Maximum Power Consumption

跟EF_DIR, EF_ICCID, EF_PL, EF_ARR一样, EF_UMPC也是一个应用无关的文件

放在MF(3F00)下

很多卡上实际没有这个文件

虽然规范是要求这个文件 必须存在

电信卡有这个文件

FCP: 62198205422100093283022F088A01058B032F0605800201C28800

62 19

82 05 42(工作EF,线性固定,共享) 21 00 09(记录长度) 32 (记录个数)

83 02 2F08

8A 01 05 (生命周期:激活)

8B 03 2F0605

80 02 01 C2 (文件大小)

88 00 (无SFI)

3F00 2FE2 0000000001

3F00 7F20 6F20 000000

3F00 7F25 6F31 000001

3F00 7FF1 6F31 000001

3F00 7FF1 6F46 000001

看来这个文件被挪做他用了

rust拼接切片(concatenate two slices /join two slices as a new slice)

如果都是vector,可以用vector自带的append方法 或者 Extend trait 或者slice的concat方法

fn main() {
    let mut a = vec![1, 2, 3];
    let mut b = vec![4, 5, 6];

    a.append(&mut b);

    assert_eq!(a, [1, 2, 3, 4, 5, 6]);
    assert_eq!(b, []);
}
或者
fn main() {
    let mut a = vec![1, 2, 3];
    let b = vec![4, 5, 6];

    a.extend(b);
    assert_eq!(a, [1, 2, 3, 4, 5, 6]);
}
或者

fn main() {
    let mut a = vec![1, 2, 3];
    let b = vec![4, 5, 6];

    [a, b].concat()
    assert_eq!(a, [1, 2, 3, 4, 5, 6]);
}

用extend_from_slice

fn cat<T: Clone>(a: &[T], b: &[T]) -> Vec<T> {
let mut v = Vec::with_capacity(a.len() + b.len());
v.extend_from_slice(a);
v.extend_from_slice(b);
v
} 或者
fn join<T: Clone>(a: &[T], b: &[T]) -> Vec<T> { a.iter().cloned().chain(b.iter().cloned()).collect() }
或者 fn join<T: Clone>(a: &[T], b: &[T]) -> Vec<T> { let mut v = a.to_vec(); v.extend_from_slice(b); v }

rust得到变量的类型和占用空间的大小

两种写法
1. 直接打印

fn print_type_of<T>(_: &T) {
    println!( "{}", std::any::type_name::<T>()   );
}

或者
fn print_type_of<T>(_: T) {
    println!("{}", std::any::type_name::<T>());
}
上面那种,传 引用,  
下面这种,直接传值, 会转移所有权

2. 返回字符串

fn type_of<T>(_: T) -> &'static str {
std::any::type_name::<T>()
} 或者 fn type_of<T>(_: &T) -> &'static str { std::any::type_name::<T>() } 也是 转移所有权的区别 调用示范: println!("{}", type_of(&x));

3.其他方法 (新功能https://github.com/rust-lang/rust/issues/66359)

use std::any::type_name_of_val;
let x = 1;
println!("{}", type_name_of_val(&x));

4.基本类型:
1)整数:
u8, i8, u16, i16, u32, i32, u64, i64, u128, i128

2)浮点数:
f32, f64

3)逻辑数(布尔类型)
true, false

4)字符 (char)

let alphabet:char = 'A';
let emoji:char = '😁';

5)数组 array

6) 元组 tuple

5. 完整代码

fn type_of(_: &T) -> &'static str {
    std::any::type_name::()
}


fn main() {
    let buff = [0x21 as u8, 0x22, 0x23, 0x24];

    println!("{}", type_of(&buff));
}

运行结果:
[u8; 4]

6. 得到占用空间的大小

fn main() {
    fn size_of_val<T>(_: &T) -> usize {
        std::mem::size_of::<T>()
    }
    
    let arr = [0u8; 4];
    println!("size_of arr: {}", size_of_val(&arr));
}

7. 图示

Rust Container cheat sheet

rust的数组array向量vector切片slice字符串str

1. 数组 array
Rust 中的数组是固定长度的:一旦声明,它们的长度不能增长或缩小。

let a = [1, 2, 3, 4, 5];
let a: [i32; 5] = [1, 2, 3, 4, 5];
let a = [3; 5];
let a = [3, 3, 3, 3, 3];

当你想要在栈(stack)而不是在堆(heap)上为数据分配空间,或者是想要确保总是有固定数量的元素时,数组非常有用。
正是因为array存储在stack上,所以必须固定大小。

2.切片 slice
slice是没有所有权的,它引用集合中一段连续的元素序列,而不用引用整个集合。

let a = [1, 2, 3, 4, 5];
let slice = &a[1..3];

3.基础类型字符串 str

str 本质也是表示一段 u8 序列,只是附带了额外的要求:这些 u8 序列必须是合法的 utf-8 编码

str 类型,也称为字符串切片(string slice),是最基本的字符串类型。它通常以借用的形式出现, 它们是一些储存在别处的 UTF-8 编码字符串数据的引用。它也是字符串字面值(string literals)的类型,  也就是 &'static str

字符串字面值:


let s = "Hello, world!";

这里 s 的类型是 &str:它是一个指向二进制程序(binary executes)特定位置的 slice。这也就是为什么字符串字面值是不可变的;&str 是一个不可变引用。

&str 占用 16 个字节,除了 8 个字节代表其指向的第一个字节的地址之外,还有 8 个字节代表其所涵盖的字节长度(所以 &str 又被称为胖指针

4. 向量 vector

Vec 本质是一个指针,所以 Vec 变量是定长的,可以在Stack上存储;它指向Heap的一段具有相同类型的数据序列

5. String

String本质是Vec<u8>,  同str一样, 要求Heap中的u8序列是合法的utf编码

用代码查看类型

fn type_of<T>(_: T) -> &'static str {
     std::any::type_name::<T>()
}

fn main() {
    let x = 21;
    let y = 2.5;
    let strz = "abcd";
    let str_slice = &strz[1..3];
    
    let array_ref =  b"abcd";
    let array_slice = &array_ref[1..3];
    
    let arr = [0x61 as u8, 0x62, 0x63, 0x64];
    let arr_slice = &arr[1..3]; 

    println!("{}", type_of(&y));
    println!("{}", type_of(x));
    println!("str= {}", type_of(strz));
    println!("str slice= {}", type_of(str_slice));
    println!("array ref ={}", type_of(array_ref));
    println!("array slice= {}", type_of(array_slice)); 
    println!("String={}", type_of(String::from(strz)));
    println!("array={}", type_of(arr)); 
    println!("arr slice={}", type_of(arr_slice)); 
    println!("vec={}", type_of(vec![0x61 as u8, 0x62, 0x63, 0x64]));
    println!("{}", type_of(main));
    println!("{}", type_of(type_of::<u8>));

}


运行结果
&f64
i32
str= &str
str slice= &str
array ref =&[u8; 4]
array slice= &[u8]
String=alloc::string::String
array=[u8; 4]
arr slice=&[u8]
vec=alloc::vec::Vec<u8>
vexample::main
vexample::type_of<u8>

从Rust中调用C代码

unsafe关键字

0. 新建一个InvokeC的工程

cargo new  InvokeC

1.编辑 src/main.c

extern "C" {
    fn doubler(x: i32) -> i32;
}

fn main() {
    println!("[rust] start");
    unsafe { 
        println!("{}", doubler(6));
    }
}

2. 编辑 src/hello.c

#include stdio.h

int doubler(int x) {
    return x * 2;
}

3.编译C代码

$ cc -c src/hello.c
$ cc -shared hello.o -o libnum.so

4.用rustc 编译代码,并动态链接到 libnum

rustc -l num -L . src/main.rs

5. 运行

LD_LIBRARY_PATH=.  ./main

如果不设置 LD_LIBRARY_PATH 变量, 将会找不到 libnu.so 动态库

6. 也考虑生成静态库

$  ar rcs libnum.a   hello.o

7.链接到静态库

rustc -l static=num -L. src/main.rs  

8.直接运行

./main

9. 如何不用rustc编译, 而是用cargo build或者cargo run
在项目的根目录下,建立一个 build.rs 文件

fn main() {
    println!("cargo:rustc-link-search=.");
    println!("cargo:rustc-link-lib=static=num");
}

就可以了
如果是动态库

    println!("cargo:rustc-link-search=all=src");      //  类似"rustc -L src ..." 
    println!("cargo:rustc-link-lib=dylib=num"); // 类似"rustc -l num"

或者在源代码中 指定链接选项
main.c中

#[link(name = "num", kind = "static")]
extern "C" {
    fn doubler(x: i32) -> i32;
}
...

就可以把 build.rs中

println!("cargo:rustc-link-lib=static=num");

这一行去掉

最后,如果连编译C代码都不想手动去做,可以用一个 cc的库, 在Cargo.toml中添加

[build-dependencies]
cc = "1.0"

注意:是 build-dependencies 而不是 dependencies

然后,将 build.rs改为

fn main() {
    cc::Build::new()
        .file("src/hello.c")
        .compile("libnum.a");
}

或者

fn main() {
    cc::Build::new()
        .file("src/hello.c")
        .compile("anything");
}

adb push照片并用广播更新相册媒体库

上传到 /sdcard/Pictures/up 目录

adb push   front.jpg   /sdcard/Pictures/up

广播通知

adb shell am broadcast -a android.intent.action.MEDIA_SCANNER_SCAN_FILE   -d file:///storage/emulated/0/Pictures/up/front.jpg
或者
adb shell am broadcast -a android.intent.action.MEDIA_MOUNTED             -d file:///storage/emulated/0/Pictures/up