slint esp32 tokio

源码:https://github.com/xiaguangbo/slint_esp32_tokio
cpu 是 esp32c2,屏幕是 ili9341,触摸是 xpt2046,使用 spi 半双工
不使用DMA(esp-rs还没支持),SPI 40M,240*320全屏刷新为1.5秒,虽然比不了 lvgl,但类lvgl的slint是目前rust跨全平台唯一的选择
这是一个游戏,翻到两个一样的就成功,slint官网有入门示例,就是这个,然后把 .slint 和 控制逻辑拿过来直接用。就是slint平台需要稍微移植下,字体会自动打包
在这里插入图片描述

Cargo.toml

[package]
name = "esp32c2"
version = "0.1.0"
authors = ["xxx"]
edition = "2021"
resolver = "2"
rust-version = "1.71"[profile.release]
opt-level = "s"[profile.dev]
debug = true    # Symbols are nice and they don't increase the size on Flash
opt-level = "z"[features]
default = ["std", "embassy", "esp-idf-svc/native"]pio = ["esp-idf-svc/pio"]
std = ["alloc", "esp-idf-svc/binstart", "esp-idf-svc/std"]
alloc = ["esp-idf-svc/alloc"]
nightly = ["esp-idf-svc/nightly"]
experimental = ["esp-idf-svc/experimental"]
embassy = ["esp-idf-svc/embassy-sync","esp-idf-svc/critical-section","esp-idf-svc/embassy-time-driver",
][dependencies]
log = { version = "*", default-features = false }
esp-idf-svc = { version = "*", default-features = false }tokio = { version = "*", features = ["rt", "time", "sync"] }
num-traits = "*"
chrono = "*"
rand = "*"
slint = { version = "*", default-features = false, features = ["compat-1-2","renderer-software","unsafe-single-threaded",
] }[build-dependencies]
embuild = "*"
slint-build = "*"

appwindow.slint

struct TileData {image: image,image_visible: bool,solved: bool,
}component MemoryTile inherits Rectangle {in property <bool> open_curtain;in property <bool> solved;in property <image> icon;callback clicked;height: 50px;width: 50px;border-radius: self.width / 2;background: solved ? #34CE57 : #3960D5;clip: true;animate background { duration: 800ms; }Image {source: icon;width: parent.width;height: parent.height;}// Left curtainRectangle {background: #193076;x: 0px;width: open_curtain ? 0px : (parent.width / 2);height: parent.height;clip: true;animate width {duration: 250ms;easing: ease-in;}Image {width: root.width - 25px;height: root.height - 25px;x: 13px;y: 13px;source: @image-url("../icons/tile_logo.png");}}// Right curtainRectangle {background: #193076;x: open_curtain ? parent.width : (parent.width / 2);width: open_curtain ? 0px : (parent.width / 2);height: parent.height;clip: true;animate width {duration: 250ms;easing: ease-in;}animate x {duration: 250ms;easing: ease-in;}Image {width: root.width - 25px;height: root.height - 25px;x: parent.width - self.width - 13px;y: 13px;source: @image-url("../icons/tile_logo.png");}}TouchArea {clicked => {// Delegate to the user of this elementroot.clicked();}width: 100%;height: 100%;}
}export component AppWindow inherits Window {width: 240px;height: 320px;callback check_if_pair_solved();// Addedin property <bool> disable_tiles;// Addedin-out property <[TileData]> memory_tiles: [{ image: @image-url("../icons/at.png") },{ image: @image-url("../icons/balance-scale.png") },{ image: @image-url("../icons/bicycle.png") },{ image: @image-url("../icons/bus.png") },{ image: @image-url("../icons/cloud.png") },{ image: @image-url("../icons/cogs.png") },{ image: @image-url("../icons/motorcycle.png") },{ image: @image-url("../icons/video.png") },];for tile[i] in memory_tiles: MemoryTile {x: mod(i, 4) * (root.width / 4);y: floor(i / 4) * (root.width / 4);width: 50px;height: 50px;icon: tile.image;open_curtain: tile.image_visible || tile.solved; // 任何一个满足都打开帘子// propagate the solved status from the model to the tilesolved: tile.solved;clicked => {// old: tile.image_visible = !tile.image_visible;// new:// 可不可以点击if (!root.disable_tiles) {tile.image_visible = !tile.image_visible;root.check_if_pair_solved();}}}
}

ui

use std::{borrow::Borrow, cell::RefCell, rc::Rc};use slint::platform::{software_renderer::*, PointerEventButton, WindowAdapter, WindowEvent};
use slint::Model;
use tokio::time;use esp_idf_svc::hal::{gpio::*, peripheral::*, spi::*};use crate::component::{ili9341, xpt2046};slint::include_modules!();pub async fn work<SPI, CS, CS2, DC>(spi1: SPI, spi2: SPI, cs1: CS, cs2: CS2, dc: DC)
whereSPI: Borrow<SpiDriver<'static>> + 'static,CS: Peripheral<P = CS> + OutputPin,CS2: Peripheral<P = CS2> + OutputPin,DC: Peripheral<P = DC> + OutputPin,
{let mut ili9341 = ili9341::ILI9341::new(spi1, cs1, dc);let xpt2046 = xpt2046::XPT2046::new(spi2, cs2);ili9341.open();let buffer_provider = DrawBuffer {display: ili9341,buffer: vec![Rgb565Pixel::default(); ili9341::ILI9341_WIDTH as usize].leak(),};slint::platform::set_platform(Box::new(SlintBackend {window: Default::default(),now: std::time::Instant::now().into(),buffer_provider: buffer_provider.into(),touch: xpt2046.into(),last_touch: None.into(),})).unwrap();let main_window = AppWindow::new().unwrap();// Fetch the tiles from the modellet mut tiles: Vec<TileData> = main_window.get_memory_tiles().iter().collect();// Duplicate them to ensure that we have pairstiles.extend(tiles.clone());// Randomly mix the tilesuse rand::seq::SliceRandom;let mut rng = rand::thread_rng();tiles.shuffle(&mut rng);// Assign the shuffled Vec to the model propertylet tiles_model = std::rc::Rc::new(slint::VecModel::from(tiles));main_window.set_memory_tiles(tiles_model.clone().into());let main_window_weak = main_window.as_weak();// 点击的回调函数main_window.on_check_if_pair_solved(move || {// 如果元素的(image_visible && !solved)为真,则得到他// 就是被打开看的且没有被标记的对象let mut flipped_tiles = tiles_model.iter().enumerate().filter(|(_, tile)| tile.image_visible && !tile.solved);// 当检查出有两个这样的元素就进入判断if let (Some((t1_idx, mut t1)), Some((t2_idx, mut t2))) =(flipped_tiles.next(), flipped_tiles.next()){let is_pair_solved = t1 == t2; // 比较两个元素的值是不是一样的,包括图片的 rgba 和元素属性,也就是 TileData 的所有成员// 一样if is_pair_solved {t1.solved = true; // 彻底打开帘子tiles_model.set_row_data(t1_idx, t1);t2.solved = true;tiles_model.set_row_data(t2_idx, t2);}// 不一样else {let main_window = main_window_weak.unwrap();main_window.set_disable_tiles(true); // 防止继续点击let tiles_model = tiles_model.clone();// 延时 1sslint::Timer::single_shot(std::time::Duration::from_secs(1), move || {main_window.set_disable_tiles(false); // 可继续点击t1.image_visible = false; // 关闭帘子tiles_model.set_row_data(t1_idx, t1);t2.image_visible = false;tiles_model.set_row_data(t2_idx, t2);});}}});loop {slint::run_event_loop().unwrap();time::sleep(time::Duration::from_millis(20)).await;}
}pub struct SlintBackend<'a, SPI, DC>
whereSPI: Borrow<SpiDriver<'a>> + 'a,DC: Peripheral<P = DC> + OutputPin,
{window: RefCell<Option<Rc<MinimalSoftwareWindow>>>,now: RefCell<std::time::Instant>,buffer_provider: RefCell<DrawBuffer<'a, SPI, DC>>,touch: RefCell<xpt2046::XPT2046<'a, SPI>>,last_touch: RefCell<Option<slint::LogicalPosition>>,
}impl<'a, SPI, DC> slint::platform::Platform for SlintBackend<'a, SPI, DC>
whereSPI: Borrow<SpiDriver<'a>> + 'a,DC: Peripheral<P = DC> + OutputPin,
{fn create_window_adapter(&self) -> Result<Rc<dyn WindowAdapter>, slint::PlatformError> {let window = MinimalSoftwareWindow::new(RepaintBufferType::ReusedBuffer);self.window.replace(Some(window.clone()));self.window.borrow().as_ref().unwrap().set_size(slint::PhysicalSize::new(ili9341::ILI9341_WIDTH as u32,ili9341::ILI9341_HEIGHT as u32,));Ok(window)}fn duration_since_start(&self) -> std::time::Duration {self.now.borrow().elapsed()}fn run_event_loop(&self) -> Result<(), slint::PlatformError> {let while_now = std::time::Instant::now();let mut touch_now = std::time::Instant::now();let mut touch_ed = false;// 连续绘制达到 100ms 就跳过while while_now.elapsed().as_millis() < 100 {slint::platform::update_timers_and_animations();if let Some(window) = self.window.borrow().clone() {if !touch_ed {touch_ed = !touch_ed;touch_now = std::time::Instant::now();if let Some(event) = match self.touch.borrow_mut().read() {Some(v) => {let position = slint::PhysicalPosition::new((v.x * ili9341::ILI9341_WIDTH as f32) as i32,(v.y * ili9341::ILI9341_HEIGHT as f32) as i32,).to_logical(window.scale_factor());Some(match self.last_touch.borrow_mut().replace(position) {Some(_) => WindowEvent::PointerMoved { position },_ => WindowEvent::PointerPressed {position,button: PointerEventButton::Left,},})}_ => self.last_touch.borrow_mut().take().map(|position| {WindowEvent::PointerReleased {position,button: PointerEventButton::Left,}}),} {let is_pointer_release_event =matches!(event, WindowEvent::PointerReleased { .. });window.dispatch_event(event);if is_pointer_release_event {window.dispatch_event(WindowEvent::PointerExited);}}} else {if touch_now.elapsed().as_millis() >= 20 {// 每隔一段时间才能再次读取触摸,避免频繁处理touch_ed = !touch_ed;}}window.draw_if_needed(|renderer| {renderer.render_by_line(&mut *self.buffer_provider.borrow_mut());});if !window.has_active_animations() {// 如果没有需要绘制的东西就跳出,否则就继续绘制break;}}}Ok(())}
}struct DrawBuffer<'a, SPI, DC>
whereSPI: Borrow<SpiDriver<'a>> + 'a,DC: Peripheral<P = DC> + OutputPin,
{display: ili9341::ILI9341<'a, SPI, DC>,buffer: &'a mut [Rgb565Pixel],
}impl<'a, SPI, DC> LineBufferProvider for &mut DrawBuffer<'a, SPI, DC>
whereSPI: Borrow<SpiDriver<'a>> + 'a,DC: Peripheral<P = DC> + OutputPin,
{type TargetPixel = Rgb565Pixel;fn process_line(&mut self,line: usize,range: std::ops::Range<usize>,render_fn: impl FnOnce(&mut [Rgb565Pixel]),) {let buffer = &mut self.buffer[range.clone()];render_fn(buffer);self.display.write_pixel_slint(range.start as u16,line as u16,range.end as u16,line as u16,&buffer,);}
}

work

use std::{rc, thread};use tokio::{runtime, task, time};use esp_idf_svc::hal::{gpio, peripherals, spi};use crate::module::*;pub fn work() {thread::Builder::new().stack_size(8 * 1024).spawn(|| {task::LocalSet::new().block_on(&runtime::Builder::new_current_thread().enable_all().build().unwrap(),async {let peripherals = peripherals::Peripherals::take().unwrap();let spi = spi::SpiDriver::new::<spi::SPI2>(peripherals.spi2,peripherals.pins.gpio0,peripherals.pins.gpio1,Option::<gpio::AnyIOPin>::None,&spi::SpiDriverConfig::new(),).unwrap();let spi = rc::Rc::new(spi);let spi_1 = spi.clone();let spi_2 = spi.clone();task::spawn_local(async move {ui::work(spi_1,spi_2,peripherals.pins.gpio3,peripherals.pins.gpio4,peripherals.pins.gpio2,).await;});loop {time::sleep(time::Duration::MAX).await;}},);}).unwrap();
}

build

fn main() {embuild::espidf::sysenv::output();slint_build::compile_with_config("ui/appwindow.slint",slint_build::CompilerConfiguration::new().embed_resources(slint_build::EmbedResourcesKind::EmbedForSoftwareRenderer),).unwrap();
}

ili9341

use std::borrow::*;use esp_idf_svc::hal::{delay::Delay, gpio::*, peripheral::*, prelude::*, spi::*};use slint::platform::software_renderer::Rgb565Pixel;pub const ILI9341_WIDTH: u16 = 240;
pub const ILI9341_HEIGHT: u16 = 320;/*
# 初始化
第一个字节是命令
等待5ms36, 48 左上右下竖屏、c8 右下左上竖屏、e8 左下右上横屏、28右上左下横屏
3a, 55 像素格式 565
11     退出睡眠
29     开显示、28 关显示。不会更改内存内容# 设置区域
可设置一点、一行或一个方块,方块区域会自动换行2a x坐标
16bit xs
16bit xe2b y坐标
16bit ys
16bit ye2c
16bit 565 颜色数据
*/pub struct ILI9341<'a, SPI, DC>
whereSPI: Borrow<SpiDriver<'a>> + 'a,DC: Peripheral<P = DC> + OutputPin,
{spi: SpiDeviceDriver<'a, SPI>,dc: PinDriver<'a, DC, Output>,line_buf: Vec<u8>,
}impl<'a, SPI, DC> ILI9341<'a, SPI, DC>
whereSPI: Borrow<SpiDriver<'a>> + 'a,DC: Peripheral<P = DC> + OutputPin,
{pub fn new<CS>(spi: SPI, cs: CS, dc: DC) -> SelfwhereCS: Peripheral<P = CS> + OutputPin,{let config = config::Config::default().baudrate(40.MHz().into()).duplex(config::Duplex::Half3Wire);Self {spi: SpiDeviceDriver::new(spi, Some(cs), &config).unwrap(),dc: PinDriver::output(dc).unwrap(),line_buf: vec![0u8; (ILI9341_WIDTH * 2) as usize],}}pub fn open(&mut self) {let delay = Delay::new_default();for _ in 0..2 {delay.delay_ms(20);self.write_cmd_data_u8(0x36, Some(&[0x48]));self.write_cmd_data_u8(0x3a, Some(&[0x55]));self.write_cmd_data_u8(0x11, None);self.write_cmd_data_u8(0x29, None);}}pub fn write_pixel_slint(&mut self,x: u16,y: u16,x_end: u16,y_end: u16,pixel: &[Rgb565Pixel],) {self.write_draw_range(x, y, x_end, y_end);self.write_cmd_data_slint(0x2c, pixel);}fn write_cmd_data_u8(&mut self, cmd: u8, data: Option<&[u8]>) {self.dc.set_low().unwrap();self.spi.write(&[cmd]).unwrap();if let Some(v) = data {self.dc.set_high().unwrap();self.spi.write(v).unwrap();}}fn write_draw_range(&mut self, x: u16, y: u16, x_end: u16, y_end: u16) {let mut x_buf = [0u8; 4];let mut y_buf = [0u8; 4];x_buf[0..=1].copy_from_slice(&x.to_be_bytes());x_buf[2..=3].copy_from_slice(&x_end.to_be_bytes());y_buf[0..=1].copy_from_slice(&y.to_be_bytes());y_buf[2..=3].copy_from_slice(&y_end.to_be_bytes());self.write_cmd_data_u8(0x2a, Some(&x_buf));self.write_cmd_data_u8(0x2b, Some(&y_buf));}fn write_cmd_data_slint(&mut self, cmd: u8, data: &[Rgb565Pixel]) {let mut i = 0;data.iter().for_each(|v| {self.line_buf[i..=i + 1].copy_from_slice(v.0.to_be_bytes().as_ref());i += 2;});self.dc.set_low().unwrap();self.spi.write(&[cmd]).unwrap();self.dc.set_high().unwrap();self.spi.write(self.line_buf[0..i].as_ref()).unwrap();}
}

xpt2046

use std::borrow::*;use esp_idf_svc::hal::{gpio::*, peripheral::*, prelude::*, spi::*};/*
d0 读 x 轴
90 读 y 轴
*/pub struct XPT2046Touch {pub x: f32,pub y: f32,
}pub struct XPT2046<'a, SPI>
whereSPI: Borrow<SpiDriver<'a>> + 'a,
{spi: SpiDeviceDriver<'a, SPI>,
}impl<'a, SPI> XPT2046<'a, SPI>
whereSPI: Borrow<SpiDriver<'a>> + 'a,
{pub fn new<CS>(spi: SPI, cs: CS) -> SelfwhereCS: Peripheral<P = CS> + OutputPin,{let config = config::Config::default().baudrate(2.MHz().into()).duplex(config::Duplex::Half3Wire);Self {spi: SpiDeviceDriver::new(spi, Some(cs), &config).unwrap(),}}pub fn read(&mut self) -> Option<XPT2046Touch> {let mut x_u16 = [0u16; 3];let mut y_u16 = [0u16; 3];for i in 0..x_u16.len() {let mut x = [0u8; 2];let mut y = [0u8; 2];self.spi.transaction(&mut [Operation::Write(&[0xd0]), Operation::Read(&mut x)]).unwrap();self.spi.transaction(&mut [Operation::Write(&[0x90]), Operation::Read(&mut y)]).unwrap();x_u16[i] = u16::from_be_bytes(x) << 1 >> 4;y_u16[i] = u16::from_be_bytes(y) << 1 >> 4;}x_u16.sort();y_u16.sort();// 实测最大最小值let x = x_u16[1].max(336).min(3847);let y = y_u16[1].max(184).min(3584);let x = (x - 336) as f32 / (3847 - 336) as f32;let y = (y - 184) as f32 / (3584 - 184) as f32;// 判断有没有触摸if x == 0 as f32 && y == 1 as f32 {None} else {Some(XPT2046Touch { x, y })}}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/16198.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

四. TensorRT模型部署优化-模型部署的基础知识

目录 前言0. 简介1. FLOPS2. TOPS3. HPC的排行&#xff0c;CPU/GPU比较4. FLOPs5. FLOPS是如何计算的6. CUDA Core vs Tensor Core总结参考 前言 自动驾驶之心推出的 《CUDA与TensorRT部署实战课程》&#xff0c;链接。记录下个人学习笔记&#xff0c;仅供自己参考 本次课程我们…

最小二乘法-超详细推导(转换为矩阵乘法推导,矩阵求导推导)

最小二乘法就是让均方误差最小。 下面是损失函数转换为矩阵方式的详解 如何让其最小&#xff0c;在导数为0的地方取极小值。 问&#xff1a;导数为0的地方可能去极大值&#xff0c;也可能是极小值&#xff0c;凭什么说导数为0就是极小值&#xff1f; 答&#xff1a;因为使用…

酷黑简洁大气体育直播自适应模板赛事直播门户网站源码

源码名称&#xff1a;酷黑简洁大气体育直播自适应模板赛事直播门户网站源码 开发环境&#xff1a;帝国cms 7.5 安装环境&#xff1a;phpmysql 支持PC与手机端同步生成html&#xff08;多端同步生成插件&#xff09; 带软件采集&#xff0c;可以挂着自动采集发布&#xff0c;无…

某某某加固系统分析

某某某加固系统内核so dump和修复&#xff1a; 某某某加固系统采取了内外两层native代码模式&#xff0c;外层主要为了保护内层核心代码&#xff0c;从分析来看外层模块主要用来反调试&#xff0c;释放内层模块&#xff0c;维护内存模块的某些运行环境达到防止分离内外模块&am…

网上比较受认可的赚钱软件有哪些?众多兼职选择中总有一个适合你

在这个互联网高速发展的时代&#xff0c;网上赚钱似乎成了一种潮流。但是&#xff0c;你是否还在靠运气寻找赚钱的机会&#xff1f;是否还在为找不到靠谱的兼职平台而苦恼&#xff1f; 今天&#xff0c;就为你揭秘那些真正靠谱的网上赚钱平台&#xff0c;让你的赚钱之路不再迷…

Python--List列表

list列表⭐⭐ 1高级数据类型 Python中的数据类型可以分为&#xff1a;数字型&#xff08;基本数据类型&#xff09;和非数字型&#xff08;高级数据类型&#xff09; ●数字型包含&#xff1a;整型int、浮点型float、布尔型bool、复数型complex ●非数字型包含&#xff1a;字符…

整合SSM框架笔记

整合SSM框架笔记 Spring5 Spring MVC MyBatis Druid MySQL Thymeleaf 感谢尚硅谷课程&#xff1a;B站课程 前言 单Spring框架时&#xff0c;是Java工程。 Spring与Spring MVC可以共用一个配置文件&#xff0c;也可以不共用一个&#xff0c;推荐不共用一个。 Spring与Sp…

Quartus 联合 ModelSim 仿真 IP 核(RAM)

文章目录 ModelSim 路径设置创建 RAM进行仿真 本文主要介绍如何在包含 IP 核的 Quartus 项目中使用 Modelsim 进行仿真&#xff0c;本文基于 IP 核 RAM: 2-PORT&#xff0c;其他 IP 核类似。 ModelSim 路径设置 点击 Tools->Options 点击 EDA Tool Options&#xff0c;设置…

string OJ题

下面分享一下string做题心得 1. 明白字符串中存储的数字为0 8 9与0 8 9 完全不同&#xff0c;字符0其实在串中存储的是48&#xff0c;要有意识的转化。字符串中如果存数字8&#xff0c;意味着存了BS&#xff08;退格&#xff09; 例如1&#xff1a; 算出结果为5&#xff0c;存…

Selenium 自动化测试工具<2>(Selenium 常用API的使用方法)

文章目录 浏览器操作浏览器最大化设置浏览器的大小浏览器的前进和后退操作浏览器滚动条 键盘事件单个按键用法键盘组合键用法 鼠标事件不同窗口搜索定位一组元素定位多层框架下拉框定位alert、confirm、prompt 的处理上传文件操作自动截屏 继上一篇文章对 Selenium API 的使用&…

RT-DRET在实时目标检测上超越YOLO8

导读 目标检测作为计算机视觉的核心任务之一&#xff0c;其研究已经从基于CNN的架构发展到基于Transformer的架构&#xff0c;如DETR&#xff0c;后者通过简化流程实现端到端检测&#xff0c;消除了手工设计的组件。尽管如此&#xff0c;DETR的高计算成本限制了其在实时目标检测…

搭建属于自己的 Git 仓库:GitLab

搭建属于自己的 Git 仓库&#xff1a;使用 GitLab 文章目录 搭建属于自己的 Git 仓库&#xff1a;使用 GitLab什么是 GitLab&#xff1f;准备工作安装 Docker使用Docker Compose 快速构建GitLab1、从docker compose快速搭建GitLab2、部署到服务器并访问3、浏览器访问 在现代软件…

【数据结构】------C语言实现二叉树

作者主页&#xff1a;作者主页 数据结构专栏&#xff1a;数据结构 创作时间 &#xff1a;2024年5月20日 一、二叉树的定义 二叉树(Binary Tree) 是由n个结点构成的有限集(n≥0)&#xff0c;n0时为空树&#xff0c;n>0时为非空树。 对于非空树&#xff1a; 有且仅有一个根…

腾讯Java社招面试题真题,最新面试题

Java中synchronized和ReentrantLock有什么区别&#xff1f; 1、锁的实现方式不同&#xff1a; synchronized是JVM层面的锁&#xff0c;主要依赖于监视器对象&#xff08;monitor&#xff09;实现。ReentrantLock是JDK层面的锁&#xff0c;通过Java代码实现&#xff0c;提供了更…

语雀——云知识库/笔记

对于日常进行学习/创作或是记录学习、工作内容与心得的群体来说&#xff0c;能够及时同步的云笔记应用有着广泛的应用场景。近期&#xff0c;我也探索了许多款不同的软件应用&#xff0c;今天来分享一款很有特点的应用——语雀。 语雀&#xff0c;为每一个人提供优秀的文档和知…

1.6 什么是程序-编译与调试

目录 1 程序的作用 2 新建项目及编译运行 2.1 新建项目 2.2 HelloWorld 程序说明 2.3 printf 打印输出 2.4 注释 3 程序的编译过程及项目位置 4 断点及调试窗口设置 5 学习C语言后的境界 1 程序的作用 如下图所示&#xff0c;我们编写了一个可以做加法的程序&#xf…

vue3 vite项目配置了proxy代理情况下查看真实的接口调用地址

vite配置了proxy代理情况下如何查看真实的接口调用地址? 使用vite进行代理 在vite.config.ts配置了代理 在浏览器查看请求头和响应头发现只有代理前的url&#xff0c;没有显示代理后的路径 然后发现一个bypass函数&#xff0c;但是此函数只能修改res响应头的数据&#xff0…

Dockerfile文件详细介绍

前言 Dockerfile是一个文本文件&#xff0c;包含了用于构建Docker镜像的所有命令和说明。它定义了容器的运行环境、依赖以及启动方式&#xff0c;是创建Docker镜像的核心部分。 由于制作镜像的过程中&#xff0c;需要逐层处理和打包&#xff0c;比较复杂&#xff0c;所以Docke…

实战复盘:内网环境渗透ms-SQL数据库

渗透环境&#xff1a;如下图所示&#xff0c;web服务器、ms-SQL服务器、PC客户端在同一个网络中&#xff0c;彼此之间&#xff0c;没有路由器或防火墙的隔离&#xff0c;这是一种危险的网络结构&#xff0c;入侵ms-SQL服务器&#xff0c;非常容易。&#xff08;实战中&#xff…

整理了10个靠谱且热门的赚钱软件,适合普通人长期做的赚钱副业

作为一名普通的上班族&#xff0c;我们每天都在辛勤工作&#xff0c;但工资的增长速度却如同蜗牛般缓慢。不过&#xff0c;别担心&#xff0c;信息时代总是带给我们无尽的惊喜&#xff01;今天&#xff0c;我将为大家推荐一些赚钱的宝藏软件&#xff0c;让你在闲暇之余轻松实现…