Linux驱动(中断、异步通知):红外对射,并在Qt StatusBus使用指示灯进行显示
本文工作:
1、Linux驱动与应用程序编写:使用了设备树、中断、异步通知知识点,实现了红外对射状态的异步信息提醒。
2、QT程序编写:自定义了一个“文本指示灯”类,并放置在QMainWidget的StatusBus中。
3、C与C++混合编程与调试:将Linux C下的面向过程转化为QT C++的面向对象。但是Linux C下signal函数需要使用static函数作为传入参数,但是C++中static的用法与C语言不一样,因此在C++中对抽象出的类进行了适配与修改。
参考资料
1、《正点原子:I.MX6U嵌入式Linux驱动开发指南V1.6》
2、C/C++ static关键字详解(最全解析,static是什么,static如何使用,static的常考面试题)-CSDN博客
3、【创龙AM4379 Cortex-A9试用体验】之I/O中断异步通知驱动程序+QT捕获Linux系统信号+测试信号通知 - ARM技术论坛 - 电子技术论坛 - 广受欢迎的专业电子论坛! (elecfans.com)
4、Qt 封装一个简单的LED(指示灯)控件_qt 指示灯-CSDN博客
本文不对基础知识进行讲解,因此阅读本文需要一定的驱动/QT基础。
开发板:IMX6ULL
内核版本:4.1.15
QT版本:5.12
一、项目需求与效果
1、项目需求:
项目中的一个简单传感器:使用红外对射,检查物品是否放入了盒子中,并在QT界面的statusBus中,使用指示灯的形式进行显示与说明。
2、代码效果
红外对射-Linux驱动-QT
代码效果:屏幕左下角文本指示灯的变化
二、Linux驱动与应用程序编写
1、使用引脚说明
本次所使用的引脚为GPIO2_2,查看了I.MX6ULL核心板对GPIO的描述,该引脚可复用到GPIO1_IO02引脚上,因此我们需要先修改下设备树的文件。
2、修改设备树文件
在根节点目录下先添加节点:
gpio_infrared {compatible = "csx-gpio-infrared";pinctrl-names = "default";pinctrl-0 = <&pinctrl_infrared>;infrared-gpio = <&gpio1 2 GPIO_ACTIVE_LOW>;interrupts = < IRQ_TYPE_EDGE_BOTH>;status = "okay";};
项目中,我们需要极度关注是否有物体存入,进拿进取出都需要通知用户,因此需要中断类型使用IRQ_TYPE_EDGE_BOTH。
其中的pinctrl_infrared为:
pinctrl_infrared: infraredgrp {fsl,pins = <MX6UL_PAD_GPIO1_IO02__GPIO1_IO02 0x10B0>;};
修改完之后,执行make dtbs,更换开发板的设备树之后,我们使用 ls /proc/device-tree查看是否有我们增加的设备树节点。
如上图,设备树修改成功,接下来就是编写驱动文件。
3、驱动文件编写
(1)结构体编写
/* 设备中断结构体 */
struct irq_gpio_infrared{int gpio; /* gpio */int irqnum; /* 中断号 */unsigned char value; /* 读取的值 */char name[10]; /* 名字 */irqreturn_t (*handler)(int,void *); /* 中断服务函数 */};/* gpioinfrared设备结构体 */
struct gpio_infrared_dev{dev_t devid; /* 设备号 */struct cdev cdev; /* cdev */struct class *class; /* 类 */struct device *device; /* 设备 */int major; /* 主设备号 */int minor; /* 次设备号 */struct device_node *nd; /* 设备节点 */struct irq_gpio_infrared irqgpioinfrared; /* 中断结构体 */struct fasync_struct *async_queue; /* 异步相关结构体 */
};struct gpio_infrared_dev gpioinfrared; /* infrared设备 */
代码中我们需要注意的是,使用了中断结构体,用于红外对射,检测到物体时通知用户,在各种通知方法中,使用异步通知是最可行的,其他方法需要占据大量的cpu资源,不适合本次的应用场景,因此,中断服务其实就是使用异步通知对用户进行通知,因此,我们还需要使用异步通知的结构体。
(2)获取设备树节点的信息【设备树API、GPIO子系统API】
/* 1、获取设备节点:gpioinfrared */gpioinfrared.nd = of_find_node_by_path("/gpio_infrared");if(gpioinfrared.nd == NULL) {printk("gpioinfrared node not find!\r\n");return -EINVAL;} else {printk("gpioinfrared node find!\r\n");}/* 2、 获取设备树中的gpio属性,得到GPIO所使用的编号 */gpioinfrared.irqgpioinfrared.gpio = of_get_named_gpio(gpioinfrared.nd, "infrared-gpio", 0);if(gpioinfrared.irqgpioinfrared.gpio < 0) {printk("can't get infrared-gpio");return -EINVAL;}else{printk("infrared-gpio num = %d\r\n", gpioinfrared.irqgpioinfrared.gpio);}/* 3、初始化使用的gpio */memset(gpioinfrared.irqgpioinfrared.name,0,sizeof(gpioinfrared.irqgpioinfrared.name));sprintf(gpioinfrared.irqgpioinfrared.name,"gpioinfrared%d",i);ret = gpio_direction_input(gpioinfrared.irqgpioinfrared.gpio);if(ret < 0) {printk("can't set gpio!\r\n");}
(3)中断申请
/* 4、设置中断模式,返回中断号 */gpioinfrared.irqgpioinfrared.irqnum = gpio_to_irq(gpioinfrared.irqgpioinfrared.gpio);printk("gpio:%d,irq:%d",gpioinfrared.irqgpioinfrared.gpio,gpioinfrared.irqgpioinfrared.irqnum);/* 申请中断 */gpioinfrared.irqgpioinfrared.handler = goio_infrared_handler;ret = request_irq(gpioinfrared.irqgpioinfrared.irqnum, gpioinfrared.irqgpioinfrared.handler, IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING,gpioinfrared.irqgpioinfrared.name, &gpioinfrared);if(ret < 0){printk("irq %d request fail infrared!\r\n", gpioinfrared.irqgpioinfrared.irqnum);printk("irq_name: %s\r\n",gpioinfrared.irqgpioinfrared.name);return -EFAULT;}if (ret==-EBUSY){printk("irq already apply\r\n");}
(4)编写红外对射的中断函数
/*GPIO红外中断服务函数,用于发送异步信息
*/
static irqreturn_t goio_infrared_handler(int irq,void *dev_id)
{struct gpio_infrared_dev *dev = (struct gpio_infrared_dev *)dev_id;printk("irq happend!\r\n");kill_fasync(&dev->async_queue, SIGIO, POLL_IN);return IRQ_RETVAL(IRQ_HANDLED);
}
如上述所说,就是用于发送异步通信的!在这里还使用内核进行打印输出,方便检测。
(5)编写异步通信函数
static int imx6uirq_fasync(int fd, struct file *filp, int on)
{struct gpio_infrared_dev *dev = (struct gpio_infrared_dev *)filp->private_data;return fasync_helper(fd, filp, on, &dev->async_queue);
}static int imx6uirq_release(struct inode *inode, struct file *filp)
{return imx6uirq_fasync(-1, filp, 0);
}
(6)编写用户层数据接口
/** @description : 从设备读取数据 * @param - filp : 要打开的设备文件(文件描述符)* @param - buf : 返回给用户空间的数据缓冲区* @param - cnt : 要读取的数据长度* @param - offt : 相对于文件首地址的偏移* @return : 读取的字节数,如果为负值,表示读取失败*/
static ssize_t infrared_read(struct file *filp, char __user *buf, size_t cnt, loff_t *offt)
{int ret = 0;unsigned char value=-1;struct gpio_infrared_dev *dev = (struct gpio_infrared_dev *)filp->private_data;value = gpio_get_value(dev->irqgpioinfrared.gpio);printk("gpioinfrared read:%d!\r\n",value);ret = copy_to_user(buf, &value, sizeof(value));return ret;
}
重点的内容都介绍完了,接下来就是检查下是否正确驱动编写是否正确了!make生成.ko文件后,传到开发板,使用insmod命令,会有如下输入:
此时,我们将红外进行对射后,就会有如下输出:
即驱动编写正确。接下来,我们先编写应用程序的代码,接收异步通知的提醒。
4、Linux C应用程序代码编写
应用程序接收异步通知需要以下三个步骤:
(1)使用signal函数设置(驱动程序所使用的)信号处理函数;
(2)将当前应用程序的内核号告知内核
(3)开启异步通知
signal(SIGIO, sigio_signal_func); /* 设置信号SIGIO的处理函数 */
fcntl(fd, F_SETOWN, getpid()); /* 设置当前进程接收SIGIO信号 */
flags = fcntl(fd, F_GETFL); /* 获取当前的进程状态 */
fcntl(fd, F_SETFL, flags | FASYNC); /* 设置进程启用异步通知功能 */
/** SIGIO信号处理函数* @param - signum : 信号值* @return : 无*/
static void sigio_signal_func(int signum)
{int err = 0;unsigned int infrared_value = 0;err = read(fd, &infrared_value, sizeof(infrared_value));if(err < 0) {/* 读取错误 */printf("read error!\r\n");} else {printf("sigio signal:%d!\r\n",infrared_value);}}
接下来,我们在进行交叉编译之后
arm-linux-gnueabihf-gcc infrared_asy.c -o infrared_asy
进行测试一下。
上图所示,测试成功!
三、C++ Qt程序编写
1、自定义LedWithText
先根据自己的需要,对参考资料第四点对自封装的LED控件进行了简化,类名为QSimpleLed
QSimpleLed.cpp文件
#include "qsimpleled.h"#include <QGradient>
#include <QPainter>
#include <QDebug>
#include <QColor>QSimpleLed::QSimpleLed(QWidget *parent, QColor color,int radius): QLabel(parent), mColor(color)
{setMinimumSize(radius, radius);setMaximumSize(radius,radius);
}void QSimpleLed::setStates(QSimpleLed::LEDSTATES states)
{switch (states) {case ON:resetStatus();mStates = ON;break;case OFF:resetStatus();break;case BLINK:resetStatus();if (!mBlinkTimer) {mBlinkTimer = new QTimer(this);connect(mBlinkTimer, &QTimer::timeout, this, &QSimpleLed::onBlinkTimerTimeout);}mBlinkTimer->setInterval(mInterval);mBlinkTimer->start();mStates = BLINK;break;default:qDebug() << "LED - unknown states!!!";}update();
}void QSimpleLed::setColor(QColor color)
{mColor = color;
}void QSimpleLed::paintEvent(QPaintEvent *event)
{Q_UNUSED(event);qreal realSize = qMin(width(), height());QPainter painter(this);painter.setRenderHint(QPainter::Antialiasing); // 反锯齿painter.translate(width()/2, height()/2); // 绘点移到控件中心处if(blinkState)painter.setBrush(QBrush(QColor(111,111,111)));elsepainter.setBrush(QBrush(mColor));painter.drawEllipse(QPointF(0, 0), realSize/2, realSize/2);}void QSimpleLed::resizeEvent(QResizeEvent *event)
{Q_UNUSED(event);update();
}void QSimpleLed::onBlinkTimerTimeout()
{blinkState = !blinkState;update();
}void QSimpleLed::resetStatus()
{if (mBlinkTimer && mBlinkTimer->isActive()) {mBlinkTimer->stop();}mStates = OFF;
}
QSimpleLed.h文件
#ifndef QSIMPLELED_H
#define QSIMPLELED_H#include <QLabel>
#include <QTimer>
#include <QColor>class QSimpleLed : public QLabel
{Q_OBJECTpublic:enum LEDSTATES {ON = 0,OFF = 1,BLINK = 2,};QSimpleLed(QWidget *parent = nullptr, QColor color = Qt::green,int radius=16);void setStates(LEDSTATES states);void setInterval(int msec) { mInterval = msec; }void setColor(QColor color);protected:virtual void paintEvent(QPaintEvent *event) override;virtual void resizeEvent(QResizeEvent *event) override;private slots:void onBlinkTimerTimeout();private:void resetStatus();LEDSTATES mStates = OFF;QColor mColor;QTimer *mBlinkTimer = nullptr;int mInterval = 500;bool blinkState = false;};#endif // QSIMPLELED_H
再根据自己的需求,自定义一个widget,用于存放led(左)与text(右),我们在外部只需要传入led的状态、颜色、文本的内容即可,该类的名称为LedWithText。
LedWithText.cpp
#include "ledwithtext.h"
#include <QFont>
#include <QDebug>ledWithText::ledWithText(QWidget *parent, QColor color, const QString &text):QWidget(parent)
{ledLabel = new QSimpleLed(this);ledLabel->setColor(color);
// ledLabel->setStyleSheet("border-width: 1px;border-style: solid;border-color: rgb(255, 170, 0);");textLabel = new QLabel(text,this);textLabel->adjustSize();textLabel->setAlignment(Qt::AlignVCenter);textLabel->setMinimumHeight(ledLabel->height()+5);textLabel->setVisible(!text.isEmpty());QFont ft;ft.setPointSize(14);textLabel->setFont(ft);layout = new QHBoxLayout(this);layout->addWidget(ledLabel);layout->addWidget(textLabel);layout->setSpacing(5);setLayout(layout);int adjustWith = ledLabel->width()+textLabel->width()+25;int adjustHeight = textLabel->height()+10;
// qDebug()<<adjustHeight<<adjustWith;setGeometry(0,0,adjustWith,adjustHeight);
}ledWithText::~ledWithText()
{delete ledLabel;delete textLabel;
}void ledWithText::setLedColor(QColor color)
{ledLabel->setColor(color);
}void ledWithText::setLedState(QSimpleLed::LEDSTATES states)
{ledLabel->setStates(states);
}void ledWithText::setText(const QString &text)
{textLabel->setText(text);textLabel->adjustSize();textLabel->setVisible(!text.isEmpty());int adjustWith = ledLabel->width()+textLabel->width()+25;int adjustHeight = textLabel->height()+10;setGeometry(0,0,adjustWith,adjustHeight);
}void ledWithText::setTextFontSize(int size)
{QFont ft;ft.setPointSize(size);textLabel->setFont(ft);textLabel->adjustSize();int adjustWith = ledLabel->width()+textLabel->width()+25;int adjustHeight = textLabel->height()+10;setGeometry(0,0,adjustWith,adjustHeight);
}
LedWithText.h
#ifndef LEDWITHTEXT_H
#define LEDWITHTEXT_H
#include <QLabel>
#include <ui_optimize/qsimpleled.h>
#include <QWidget>
#include <QHBoxLayout>class ledWithText:public QWidget
{Q_OBJECT
public:ledWithText(QWidget *parent = nullptr, QColor color = Qt::green, const QString &text = "");~ledWithText();void setLedColor(QColor color);void setLedState(QSimpleLed::LEDSTATES states);void setText(const QString &text);void setTextFontSize(int size);private:QSimpleLed *ledLabel;QLabel *textLabel;QHBoxLayout *layout;
};#endif // LEDWITHTEXT_H
2、使用MainWidget的StatusBus存放文本指示灯
我们要把这些控件放置在状态栏中,不管切换到什么界面都可以看到,就不需要一直重复写代码了,因此,我们需要使用MainWidget的StatusBus,Widget类没有StatusBus!不要用错。
void MainWindow::state_bus_init()
{device_connect_label = new ledWithText(this,Qt::green,"设备正在连接");device_connect_label->setLedColor(Qt::blue);device_connect_label->setLedState(QSimpleLed::BLINK);device_connect_label->setTextFontSize(10);ui->statusbar->addWidget(device_connect_label);device_place_label = new ledWithText(this,Qt::green,"设备未放置");device_place_label->setTextFontSize(10);ui->statusbar->addWidget(device_place_label);
}
就可以看到如下效果了。我们自定义的LedWithText类的效果就显示在左下角了。
3、Qt接受异步通知,并根据结果改变文本指示灯
按道理,最简单的做法,这一步只需要将应用层的代码搬过来就可以,但是在上文我们提到,在Linux C的应用程序中,signal函数需要传入static修饰的函数,但是Qt使用C++语言,想要将其转化为类(而不是面向过程),就需要解决static在C语言和C++的差异。
#include "infrareddev.h"InfraredDev::InfraredDev(QObject *parent) : QObject(parent)
{fd = open(DEVNAME, O_RDWR);if (fd < 0) {qDebug()<<"Can't open file :"<<DEVNAME;}else{register_infrared_asy();qDebug()<<"infrared:init succeed!";}}InfraredDev::~InfraredDev()
{if(fd){close(fd);}
}void InfraredDev::set_dev_name(char *name)
{dev_name = name;
}char *InfraredDev::get_dev_name()
{return dev_name;
}void InfraredDev::setLedWithText(ledWithText *obj)
{infrared_ledWithText = obj;
}void InfraredDev::sigio_signal_func(int signum)
{int err = 0;unsigned int infrared_value = 0;err = read(fd, &infrared_value, sizeof(infrared_value));if(err < 0) {
// InfraredDev instance; // 创建对象实例
// emit instance.infraredSignal(infrared_value);/* 读取错误 */infrared_ledWithText->setLedColor(Qt::red);infrared_ledWithText->setLedState(QSimpleLed::BLINK);infrared_ledWithText->setText("获取设备失败");qDebug()<<"infrared:read error!";} else {if(infrared_value==0){infrared_ledWithText->setLedColor(Qt::green);infrared_ledWithText->setText("设备已放置");}else if(infrared_value==1){infrared_ledWithText->setLedColor(Qt::red);infrared_ledWithText->setLedState(QSimpleLed::BLINK);infrared_ledWithText->setText("设备未放置");}qDebug()<<"infrared:sigio signal!"<<infrared_value;}}void InfraredDev::register_infrared_asy()
{int flags = 0;/* 设置信号SIGIO的处理函数 */signal(SIGIO, &InfraredDev::sigio_signal_func);fcntl(fd, F_SETOWN, getpid()); /* 设置当前进程接收SIGIO信号 */flags = fcntl(fd, F_GETFL); /* 获取当前的进程状态 */fcntl(fd, F_SETFL, flags | FASYNC); /* 设置进程启用异步通知功能 */
}int InfraredDev::fd = -1; // 初始化为无效的文件描述符
ledWithText *InfraredDev::infrared_ledWithText = nullptr;
#ifndef INFRAREDDEV_H
#define INFRAREDDEV_H#include "stdio.h"
#include "unistd.h"
#include "sys/types.h"
#include "sys/stat.h"
#include "fcntl.h"
#include "stdlib.h"
#include "string.h"
#include "poll.h"
#include "sys/select.h"
#include "sys/time.h"
#include "linux/ioctl.h"
#include "signal.h"#include <QObject>
#include <QDebug>
#include <QFile>
#include <QTextStream>
#include <QString>#include "ui_optimize/ledwithtext.h"#define DEVNAME "/dev/gpio_infrared"class InfraredDev : public QObject
{Q_OBJECT
public:explicit InfraredDev(QObject *parent = nullptr);~InfraredDev();void set_dev_name(char *name);char * get_dev_name();static ledWithText *infrared_ledWithText;static void setLedWithText(ledWithText *obj);private:static int fd; /* 文件描述符 */static QFile file;char *dev_name;static void sigio_signal_func(int signum);void register_infrared_asy(void);};#endif // INFRAREDDEV_H
因为static修饰的成员变量、成员函数并没有this指针,因此无法读取其他非static成员只允许读取static变量,因此我们需要将fd也需要使用static函数进行修饰,并且函数内不能包含其他no-static的变量。
因此在signal函数,我们就需要根据C++访问静态函数的规则,对参数进行传入了修改,使用通过(类名::静态成员)的方式来访问。
signal(SIGIO, &InfraredDev::sigio_signal_func);
然后,我们需要让QMainwindow类知道,接收到异步通信了,需要刷新UI了。
(1)信号机制方法
我一开始是照常使用信号机制,定义了信号函数,使用emit函数进行发送,但是因为异步通知处理函数是static类的,无法直接调用其他non-static的成员,无法发送信号,因此我想是实例化一个类,发送类的实例,进而发送信号:
InfraredDev instance; // 创建对象实例
emit instance.infraredSignal(infrared_value);
代码没报错,但是执行过程出错了,在开发板上只能读取第一次的数值,发送后,就无法进行读取,由于是在开发板上进行运行的,无法进行debug,不知道是什么原因,如果有大神知道,还请不吝赐教!
(2)指针传入做法
之后,我看到了参考资料的3的做法,就想直接传入界面的指针,在异步通知里面,直接读取指针,进行界面的修改。因此我就根据,non-static成员函数可以访问static成员变量的特性,对该做法进行了改进。定义了一个设置控件的函数,外部传入一个控件指针,函数内部设置为static类型,因此完美解决了该问题。
void InfraredDev::setLedWithText(ledWithText *obj)
{infrared_ledWithText = obj;
}// 在static函数就可以使用这个static指针进行设置了
void InfraredDev::sigio_signal_func(int signum){......infrared_ledWithText->setLedColor(Qt::red);infrared_ledWithText->setLedState(QSimpleLed::BLINK);infrared_ledWithText->setText("设备未放置");}
在infrared_dev.h中,存在该声明,为static成员变量
static ledWithText *infrared_ledWithText;
那么,我们在外部只需要传入该控件的指针即可
device_connect_label = new ledWithText(this,Qt::green,"设备正在连接");......
infrared_dev = new InfraredDev();
infrared_dev->setLedWithText(device_place_label);
相关文章:

Linux驱动(中断、异步通知):红外对射,并在Qt StatusBus使用指示灯进行显示
本文工作: 1、Linux驱动与应用程序编写:使用了设备树、中断、异步通知知识点,实现了红外对射状态的异步信息提醒。 2、QT程序编写:自定义了一个“文本指示灯”类,并放置在QMainWidget的StatusBus中。 3、C与C混合编程与…...

echarts地图的常见用法:基本使用、区域颜色分级、水波动画、区域轮播、给地图添加背景图片和图标、3d地图、飞线图
前言 最近几天用echarts做中国地图,就把以前写的demo:在vue中实现中国地图 拿来用,结果到项目里直接报错了,后来发现是因为版本的问题,没办法只能从头进行踩坑了。以下内容基于vue3 和 echarts 5.32 基本使用 获取地…...
进程间通讯-管道
介绍 管道(Pipe)是操作系统提供的一种进程间通信(IPC,Inter-Process Communication)机制,它允许一个进程的输出直接作为另一个进程的输入。管道主要分为以下两种类型: 无名管道(Unn…...

项目总结-自主HTTP实现
终于是写完了,花费了2周时间,一点一点看,还没有扩展,但是基本功能是已经实现了。利用的是Tcp为网络链接,在其上面又写了http的壳。没有使用epoll,多路转接难度比较高,以后有机会再写,…...
Java语言+二维数组+非递归实现五子棋游戏
以前做过一个C语言版五子棋:C语言+二维数组+非递归实现五子棋游戏 现在做一个Java语言版五子棋,规则如下: 1、白子为O; 2、黑子为; 3、白子先手;…...

WordCloud—— 词云
【说明】文章内容来自《机器学习入门——基于sklearn》,用于学习记录。若有争议联系删除。 wordcloud 是python的第三方库,称为词云,也成文字云,可以根据文本中的词频以直观和艺术化的形式展示文本中词语的重要性。 依赖于pillow …...
linux网络----UDP编程
一、函数接口: 1.socket:创建一个用来网络通信的终端节点; 参数: type:套接字类型 SOCK_STREAM 流式套接字 TCP SOCK_DGRAM 数据报套接字 UDP SOCK_RAM 原始套接字 domain: 协议族 AF_INET protocal: 默认为0 2.s…...

[AI工具推荐]AiRestful智能API代码生成
智能API代码示例生成工具AiRestful 一、产品介绍二、如何使用1、第一步(必须):2、第二步(可选):3、第三步(智能生成): 三、如何集成到您的网站(应用)1、开始接入2、接入案例 四、注意点 一、产品介绍 AiRestful是一款基于智能AI的,帮助小白快速生成任意编程语言的API接口调用示…...
Elasticsearch 8.10.0同义词API用法详解,支持同义词热更新
Elasticsearch 的同义词功能非常强大,如果使用得当,可以显着提高搜索引擎的效果。使用同义词功能时的一个常见问题是更新同义词集。 同义词在搜索引擎领域用途 同义词在搜索引擎领域的用途可概括如下: 增强搜索的准确性——当用户输入一个关键词时,可能与他们实际意图相关…...
深度学习之模型权重
在深度学习中,模型的权重(weights)是指神经网络中的参数,这些参数用于调整和学习模型的行为,以便能够对输入数据进行有效的映射和提取有用的特征。深度学习模型通常由许多神经元和连接组成,而权重就是连接这…...

纯前端使用XLSX导出excel表格
1 单个sheet page.js(页面中的导出方法) import { exportExcel } from ../../../utils/exportExcel.js; leadOut() {const arr [{ id: 1, name: 张三, age: 14, sex: 男 },{ id: 2, name: 李四, age: 15, sex: 女 },{ id: 3, name: 王五, age: 16, sex: 男 },];const allR…...

将mjpg格式数转化成opencv Mat格式
该博客可以解决如下两个问题: 1、将mjpg格式数据转化成opencv Mat格式 2、v4l2_buffer 格式获取的mjpg格式数据转换成Mat格式。 要将 MJPEG 格式的数据转换为 OpenCV 的 Mat 格式,您可以使用 imdecode 函数。imdecode 函数可以将图像数据解码为 Mat 对象…...

【golang/g3n】3D游戏引擎G3N的windows安装与测试
目录 说在前面安装测试 说在前面 操作系统:win 11go version:go1.21.5 windows/amd64g3n版本:github.com/g3n/engine v0.2.0其他:找了下golang 3d相关的库,目前好像就这个比较活跃 安装 按照官方教程所说,…...

sap table 获取 valuation class MBEW 查表获取
参考 https://www.tcodesearch.com/sap-tables/search?qvaluationclass...
介绍一些操作系统—— Ubuntu 系统
介绍一些操作系统—— Ubuntu 系统 Ubuntu 系统 Ubuntu 是一个以桌面应用为主的 Linux 发行版操作系统,其名称来自非洲南部祖鲁语或豪萨语的“ubuntu"一词,意思是“人性”“我的存在是因为大家的存在",是非洲传统的一种价值观。U…...
React中props 和 state异同初探
在 React 中,props 和 state 是两个非常重要的概念,它们决定了组件的行为和渲染方式。 Props props(属性)是父组件传递给子组件的数据。它们类似于函数的参数,可以在组件内部被访问和使用,但不能被修改。…...

spring-kakfa依赖管理之org/springframework/kafka/listener/CommonErrorHandler错误
问题: 整个项目使用spring-boot2.6.8版本,使用gradle构建,在common模块指定了implementation org.springframework.kafka:spring-kafka:2.6.8’这个工程也都能运行(这正常发送kafka消息和接收消息),但是执行…...

基于go语言开发的海量用户及时通讯系统
文章目录 二十三、海量用户即时通讯系统1、项目开发前技术准备2.实现功能-显示客户端登录菜单3.实现功能-完成用户登录-1.完成客户端可以该长度值发送消息长度,服务器端可以正常接收到-2.完成客户端可以发送消息,服务器端可以接收到消息并根据客户端发送…...
19.Oracle 中count(1) 、count(*) 和count(列名) 函数的区别
count(1) and count(字段) 两者的主要区别是 count(1) 会统计表中的所有的记录数,包含字段为null 的记录。count(字段) 会统计该字段在表中出现的次数,忽略字段为null 的情况。 即不统计字段为null 的记录。 count(*) 和 count(1)和count(列名)区别 …...
C 库函数 - time()
描述 C 库函数 time_t time(time_t *seconds) 返回自纪元 Epoch(1970-01-01 00:00:00 UTC)起经过的时间,以秒为单位。如果 seconds 不为空,则返回值也存储在变量 seconds 中。 声明 下面是 time() 函数的声明。 time_t time(t…...
挑战杯推荐项目
“人工智能”创意赛 - 智能艺术创作助手:借助大模型技术,开发能根据用户输入的主题、风格等要求,生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用,帮助艺术家和创意爱好者激发创意、提高创作效率。 - 个性化梦境…...
Golang dig框架与GraphQL的完美结合
将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用,可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器,能够帮助开发者更好地管理复杂的依赖关系,而 GraphQL 则是一种用于 API 的查询语言,能够提…...

HBuilderX安装(uni-app和小程序开发)
下载HBuilderX 访问官方网站:https://www.dcloud.io/hbuilderx.html 根据您的操作系统选择合适版本: Windows版(推荐下载标准版) Windows系统安装步骤 运行安装程序: 双击下载的.exe安装文件 如果出现安全提示&…...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)
本期内容并不是很难,相信大家会学的很愉快,当然对于有后端基础的朋友来说,本期内容更加容易了解,当然没有基础的也别担心,本期内容会详细解释有关内容 本期用到的软件:yakit(因为经过之前好多期…...

HarmonyOS运动开发:如何用mpchart绘制运动配速图表
##鸿蒙核心技术##运动开发##Sensor Service Kit(传感器服务)# 前言 在运动类应用中,运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据,如配速、距离、卡路里消耗等,用户可以更清晰…...

[ACTF2020 新生赛]Include 1(php://filter伪协议)
题目 做法 启动靶机,点进去 点进去 查看URL,有 ?fileflag.php说明存在文件包含,原理是php://filter 协议 当它与包含函数结合时,php://filter流会被当作php文件执行。 用php://filter加编码,能让PHP把文件内容…...
django blank 与 null的区别
1.blank blank控制表单验证时是否允许字段为空 2.null null控制数据库层面是否为空 但是,要注意以下几点: Django的表单验证与null无关:null参数控制的是数据库层面字段是否可以为NULL,而blank参数控制的是Django表单验证时字…...

什么是VR全景技术
VR全景技术,全称为虚拟现实全景技术,是通过计算机图像模拟生成三维空间中的虚拟世界,使用户能够在该虚拟世界中进行全方位、无死角的观察和交互的技术。VR全景技术模拟人在真实空间中的视觉体验,结合图文、3D、音视频等多媒体元素…...
在树莓派上添加音频输入设备的几种方法
在树莓派上添加音频输入设备可以通过以下步骤完成,具体方法取决于设备类型(如USB麦克风、3.5mm接口麦克风或HDMI音频输入)。以下是详细指南: 1. 连接音频输入设备 USB麦克风/声卡:直接插入树莓派的USB接口。3.5mm麦克…...

麒麟系统使用-进行.NET开发
文章目录 前言一、搭建dotnet环境1.获取相关资源2.配置dotnet 二、使用dotnet三、其他说明总结 前言 麒麟系统的内核是基于linux的,如果需要进行.NET开发,则需要安装特定的应用。由于NET Framework 是仅适用于 Windows 版本的 .NET,所以要进…...