当前位置: 首页 > news >正文

NodeJs使用Addon调用C++

本文介绍的是NodeJs使用node-addon-api调用C++的方法
node-addon-api是一个C++封装,基于N-API构建,目的是提供一个更高级和更易用的接口,但它仍然依赖N-API。
官方参考文档

开发环境

必须具备NodeJs环境
Window配置NodeJs环境(绅士版)
VSCode开发nodejs-c/c++必备插件

npm init -y
npm install node-addon-api
npm install node-gyp

下面介绍的调用C++函数,类,回调,promise,输出二进制等,都需要创建一个 binding.gyp配置文件。
binding.gyp 是一个配置文件,Node.js 使用 node-gyp 工具来编译原生(Native)添加模块时需要用到它,这个文件定义了如何生成原生模块的构建过程和配置。

一个基本的 binding.gyp 通常包含以下内容:

 {"targets": [{"target_name": "addon", //可执行目标的名称,可以在 JavaScript 中使用 require 来引用"sources": ["addon.cc"], //源文件列表,包含你要编译的C++源文件"include_dirs": ["<!@(node -p \"require('node-addon-api').include\")"], //动态地包含 node-addon-api 的头文件目录"dependencies": ["<!(node -p \"require('node-addon-api').gyp\")"], //动态地包括 node-addon-api 的GYP文件//下面这两个代表禁用异常处理。这可以减少一些特性以提高性能或减小生成文件的大小。"cflags!": ["-fno-exceptions"], "cflags_cc!": ["-fno-exceptions"],"defines": ["NAPI_CPP_EXCEPTIONS"] //定义预处理器宏,用于启用 node-addon-api 中的C++异常处理支持}]
}

NodeJs调用c++函数

一个简单的C++加法函数接口
创建C++源文件add.cc

#include <napi.h>Napi::Value Add(const Napi::CallbackInfo& info) //定义一个C++函数Add,返回类型是Napi::Number,参数是Napi::CallbackInfo&,它提供了对JavaScript调用此函数时传递的参数的访问
{Napi::Env env = info.Env();// 检查参数数量和类型if (info.Length() < 2 || !info[0].IsNumber() || !info[1].IsNumber()) {Napi::TypeError::New(env, "Number expected").ThrowAsJavaScriptException();return Napi::Number::New(env, 0);}//参数提取和运算double arg0 = info[0].As<Napi::Number>().DoubleValue();double arg1 = info[1].As<Napi::Number>().DoubleValue();double sum = arg0 + arg1;return Napi::Number::New(env, sum); //将C++的double变成JavaScript的数字返回。
}Napi::Object Init(Napi::Env env, Napi::Object exports) 
{//使用 exports.Set 方法将 C++ 函数 Add 导出为JavaScript可调用的函数。exports.Set(Napi::String::New(env, "add"), Napi::Function::New(env, Add)); //"add"是JavaScript中调用这个方法的名称。return exports;
}//使用 NODE_API_MODULE 宏来指定模块的名称 (add) 和初始化函数 (Init)。
//它告诉Node.js在加载模块时应该调用哪个初始化函数。
NODE_API_MODULE(add, Init)

创建index.js文件来调用C++ add函数接口

const a=require("./build/Release/add.node");
console.log(a.add(1,3));

编译与运行

node-gyp rebuild
node index.js

在这里插入图片描述

NodeJs调用c++类

一个简单的C++ get/set类
创建c++文件myclass.cc

#include <napi.h>// 定义一个简单的C++类MyClass,用于存储一个整数值
class MyClass {
public:MyClass(int value) : value_(value) {}  // 构造函数,用给定值初始化int getValue() { return value_; }      // 返回当前存储的值void setValue(int value) { value_ = value; }  // 设置新的值
private:int value_;  // 存储的整数值
};// 定义一个包装类Wrapper,用于将MyClass与JavaScript对象关联
class Wrapper : public Napi::ObjectWrap<Wrapper> {
public:// 初始化JavaScript包装类static Napi::Object Init(Napi::Env env, Napi::Object exports);// 构造函数,通过JavaScript调用Wrapper(const Napi::CallbackInfo &info);private:static Napi::FunctionReference constructor;  // 用于JavaScript构造此对象Napi::Value GetValue(const Napi::CallbackInfo &info);  // JavaScript访问函数void SetValue(const Napi::CallbackInfo &info);  // JavaScript修改函数MyClass* myClass_;  // 指向被包装的MyClass实例
};Napi::FunctionReference Wrapper::constructor;// 初始化Wrapper类,定义类函数并设置到exports对象
Napi::Object Wrapper::Init(Napi::Env env, Napi::Object exports) {Napi::HandleScope scope(env);Napi::Function func = DefineClass(env, "MyClass", {InstanceMethod("getValue", &Wrapper::GetValue),  // 绑定到JS对象的成员函数InstanceMethod("setValue", &Wrapper::SetValue)   // 绑定到JS对象的成员函数});constructor = Napi::Persistent(func);constructor.SuppressDestruct();  // 防止垃圾回收exports.Set("MyClass", func);  // 将构造函数导出为模块的一部分return exports;
}// 构造函数实现,用于初始化Wrapper对象,此时创建MyClass实例
Wrapper::Wrapper(const Napi::CallbackInfo &info) : Napi::ObjectWrap<Wrapper>(info) {Napi::Env env = info.Env();Napi::HandleScope scope(env);int value = info[0].As<Napi::Number>().Int32Value();  // 从JavaScript参数中获取整数myClass_ = new MyClass(value);  // 创建MyClass实例
}// 实现getValue,将C++中存储的值返回给JavaScript环境
Napi::Value Wrapper::GetValue(const Napi::CallbackInfo &info) {Napi::Env env = info.Env();Napi::HandleScope scope(env);int value = myClass_->getValue();return Napi::Number::New(env, value);  // 返回值作为JavaScript数字
}// 实现setValue,从JavaScript获取新值并设置到C++类中
void Wrapper::SetValue(const Napi::CallbackInfo &info) {Napi::Env env = info.Env();Napi::HandleScope scope(env);int val = info[0].As<Napi::Number>().Int32Value();myClass_->setValue(val);
}// 初始化模块,将Wrapper类注册到Node.js环境中
Napi::Object InitAll(Napi::Env env, Napi::Object exports) {return Wrapper::Init(env, exports);
}// 定义模块入口,让Node.js在加载时调用InitAll函数
NODE_API_MODULE(mytestclass, InitAll)

创建index.js文件来调用C++ 类

// 导入用C++编写的本地模块,生成的addon在build/Release目录中
const myclass = require('./build/Release/mytestclass');
// 创建MyClass的一个实例,并传递初始值100
const myClassInstance = new myclass.MyClass(100);
// 调用getValue方法,输出当前值(100)
console.log(myClassInstance.getValue());
// 调用setValue方法,将实例的值设置为200
myClassInstance.setValue(200);
// 再次调用getValue方法,输出更新后的值(200)
console.log(myClassInstance.getValue());

编译与运行

node-gyp rebuild
node index.js

在这里插入图片描述

NodeJs调用C++输入输出二进制流数据

一个简单的从JS传输二进制数据到C++,C++那边反转处理后传回到JS
创建C++文件bytearray.cc

#include <napi.h>
#include <vector>
#include <iostream>// 获取传入的ArrayBuffer或Buffer对象并将其反转
Napi::Value GetByteArray(const Napi::CallbackInfo& info) {Napi::Env env = info.Env();// 定义一个vector来存储二进制数据std::vector<uint8_t> binaryData;// 检查传入参数是否为Bufferif (info[0].IsBuffer()) {Napi::Buffer<uint8_t> inputBuffer = info[0].As<Napi::Buffer<uint8_t>>();// 将Buffer数据复制到vectorbinaryData.assign(inputBuffer.Data(), inputBuffer.Data() + inputBuffer.ByteLength());std::cout << "IsBuffer" << std::endl;}// 检查传入参数是否为ArrayBufferelse if (info[0].IsArrayBuffer()) {Napi::ArrayBuffer inputArrayBuffer = info[0].As<Napi::ArrayBuffer>();// 将ArrayBuffer数据复制到vectorbinaryData.assign(static_cast<uint8_t*>(inputArrayBuffer.Data()), static_cast<uint8_t*>(inputArrayBuffer.Data()) + inputArrayBuffer.ByteLength());std::cout << "IsArrayBuffer" << std::endl;}// 数据反转操作std::reverse(binaryData.begin(), binaryData.end());// 返回反转后的数据作为新的Buffer对象给JavaScript调用return Napi::Buffer<uint8_t>::Copy(env, binaryData.data(), binaryData.size());
}// 初始化模块,将GetByteArray函数导出为Node.js可用函数
Napi::Object InitAll(Napi::Env env, Napi::Object exports) {exports.Set(Napi::String::New(env, "getByteArray"), Napi::Function::New(env, GetByteArray));return exports;
}// 定义模块,这样Node.js可以在加载时调用InitAll函数
NODE_API_MODULE(bytearrary, InitAll)

**创建index.js文件来调用C++ **

const bytearrary = require('./build/Release/bytearrary');
const { Buffer } = require('node:buffer');const binaryData = Buffer.from([0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A]);// 获取底层 ArrayBuffer
const arrayBuffer = binaryData.buffer.slice(binaryData.byteOffset, binaryData.byteOffset + binaryData.byteLength);
//不能直接拿binaryData.buffer,会拿到整个buffer分配ArrayBuffer的内存池大小,通常为8192
//const arrayBuffer = binaryData.buffer;console.log(arrayBuffer);
console.log(arrayBuffer.byteLength); // 输出 ArrayBuffer 的字节长度const initialArray = new Uint8Array([1, 2, 3, 4, 5]); // 创建并初始化一个 Uint8Array
const buffer = initialArray.buffer;const byteArray = bytearrary.getByteArray(buffer);
console.log(byteArray); // 输出
console.log(byteArray.length); // 输出

编译与运行

node-gyp rebuild
node index.js

在这里插入图片描述

NodeJs调用C++ promise实现异步

一个简单C++封装promise提供给JS使用
创建C++文件promise.cc

#include <napi.h>
#include <chrono>
#include <thread>// 自定义的异步任务类,继承自Napi::AsyncWorker
class AsyncWorker : public Napi::AsyncWorker {
public:// 构造函数接收一个Promise的Deferred对象用于后续的resolve/reject操作AsyncWorker(Napi::Promise::Deferred deferred): Napi::AsyncWorker(Napi::Function::New(deferred.Env(), [](const Napi::CallbackInfo&) {})),deferred(deferred) {}// 此函数在后台线程中执行长时间的操作void Execute() override {// 模拟一个耗时操作,例如网络请求或I/Ostd::this_thread::sleep_for(std::chrono::seconds(2));// 假设操作得到的结果为42result_ = 42;}// 当Execute执行完成成功时,调用此函数void OnOK() override {// 使用deferred对象将结果传递回JavaScript,标记为resolved状态deferred.Resolve(Napi::Number::New(Env(), result_));}// 如果Execute过程中产生错误,调用此函数void OnError(const Napi::Error& e) override {// 使用deferred对象将错误传递回JavaScript,标记为rejected状态deferred.Reject(e.Value());}private:Napi::Promise::Deferred deferred; // 用于操作JavaScript中的Promise对象int result_; // 任务的计算结果
};// 在JavaScript中调用的函数,启动异步任务并返回Promise
Napi::Value AsyncFunction(const Napi::CallbackInfo& info) {Napi::Env env = info.Env();// 创建一个Promise的Deferred对象,供异步操作使用Napi::Promise::Deferred deferred = Napi::Promise::Deferred::New(env);// 创建并启动异步任务AsyncWorker* worker = new AsyncWorker(deferred);worker->Queue();// 返回Promise给JavaScript调用方return deferred.Promise();
}// 初始化模块,将asyncFunction导出为Node.js中的可用函数
Napi::Object InitAll(Napi::Env env, Napi::Object exports) {exports.Set(Napi::String::New(env, "asyncFunction"), Napi::Function::New(env, AsyncFunction));return exports;
}// 定义模块,在Node.js加载模块时调用InitAll函数
NODE_API_MODULE(promise, InitAll)

**创建index.js文件来调用C++ **

const addon = require('./build/Release/promise');async function test() {try {const result = await addon.asyncFunction();console.log(result); // 等待两秒输出: 42} catch (err) {console.error(err);}
}test();

编译与运行

node-gyp rebuild
node index.js

在这里插入图片描述

NodeJs调用C++回调

一个简单的C++回调提供给js使用
创建C++文件callback.cc

#include <napi.h>// 这个函数将在C++代码中被当作回调函数调用
void CallJsCallback(const Napi::CallbackInfo& info) {Napi::Env env = info.Env();// 获取传入的第一个参数,即JavaScript中的回调函数if (!info[0].IsFunction()) {Napi::TypeError::New(env, "Expecting a function as first argument").ThrowAsJavaScriptException();return;}Napi::Function callback = info[0].As<Napi::Function>();// 执行回调并传递参数// 这里我们传回数字42给JavaScriptcallback.Call(env.Global(), { Napi::Number::New(env, 42) });
}// 初始化模块,将CallJsCallback函数导出为Node.js中的可用函数
Napi::Object InitAll(Napi::Env env, Napi::Object exports) {exports.Set(Napi::String::New(env, "callJsCallback"), Napi::Function::New(env, CallJsCallback));return exports;
}// 定义模块,在Node.js加载模块时调用InitAll函数
NODE_API_MODULE(callbacke, InitAll)

**创建index.js文件来调用C++ **

const addon = require('./build/Release/callbacke');// 定义一个回调函数,将在C++代码中被调用
function myCallback(number) {console.log('Callback called with value:', number);
}// 调用本地模块的函数,并传递JavaScript的回调函数
addon.callJsCallback(myCallback);

编译与运行

node-gyp rebuild
node index.js

在这里插入图片描述
更多代码示例:
demo

相关文章:

NodeJs使用Addon调用C++

本文介绍的是NodeJs使用node-addon-api调用C的方法 node-addon-api是一个C封装&#xff0c;基于N-API构建&#xff0c;目的是提供一个更高级和更易用的接口&#xff0c;但它仍然依赖N-API。 官方参考文档 开发环境 必须具备NodeJs环境 Window配置NodeJs环境&#xff08;绅士版…...

YOLOv11(Ultralytics)视频选定区域目标统计计数及跟踪

在计算机视觉的众多应用场景中&#xff0c;对特定区域的目标进行检测、跟踪与计数是一个常见且重要的需求。无论是在智慧交通中统计通过特定路口的车辆数量&#xff0c;还是在零售分析中追踪进入特定区域的顾客行为&#xff0c;这一功能都发挥着不可或缺的作用。 随着深度学习…...

【Nginx系列】Nginx配置优先级

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...

搭建私有docker仓库

1. 安装docker依赖包 sudo yum install -y yum-utils device-mapper-persistent-data lvm2 sudo yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo sudo yum install docker-ce docker-ce-cli containerd.io sudo systemctl …...

C语言练级->##__VA_ARGS__(可变参数)的用法

有什么用&#xff1f; 通常__VA_ARGS__用于宏定义&#xff0c;其中关于日志宏需要用的&#xff0c;printf 等支持可变参数的函数的宏封装。 首先我们先知道这个__VA_ARGS__的英文全称是“Variadic Arguments” 叫可变参数。说到可变参数学过C语言的朋友们应该都会想到printf&…...

在 wordpress 中简易目录插件添加滑动条

实现思路 给目录容器添加一个 固定高度&#xff0c;并设置 CSS 的 overflow 属性 为 auto 或 scroll&#xff0c;使其内容可滚动。确保目录的滚动行为独立于页面的整体滚动。优化用户体验&#xff0c;添加平滑滚动效果。 操作步骤 1. 检查目录的 HTML 结构 首先&#xff0c;…...

Linux和Ubuntu的关系

Linux和Ubuntu的关系&#xff1a; 1. Linux本身是内核&#xff0c;Ubuntu系统是基于Linux内核的操作系统。 2. Linux内核操作系统的构成&#xff1a; 内核、shell、文件系统、应用程序 -应用程序&#xff1a;文本编辑器等 -文件系统&#xff1a;文件存放在存储设备上的组织方…...

【大数据学习 | Spark-Core】详解Spark的Shuffle阶段

1. shuffle前言 对spark任务划分阶段&#xff0c;遇到宽依赖会断开&#xff0c;所以在stage 与 stage 之间会产生shuffle&#xff0c;大多数Spark作业的性能主要就是消耗在了shuffle环节&#xff0c;因为该环节包含了大量的磁盘IO、序列化、网络数据传输等操作。 负责shuffle…...

缓存方案分享

不知道大家平常更新缓存是怎么做的&#xff0c;但是大部分时候都是更新数据的同时更新缓存&#xff0c;今天和同事一起聊到一个缓存方案的问题&#xff0c;感觉很有趣、非常精妙&#xff0c;记录一下。 基于此本文将介绍几种常见的缓存更新策略&#xff0c;包括简单的缓存覆盖…...

从零开始配置Qt+VsCode环境

从零开始配置QtVsCode环境 文章目录 从零开始配置QtVsCode环境写在前面扩展安装及配置Qt Configure配置 VsCode创建Qt工程VsCodeQMakeMinGwVsCodeQMakeMsvcVsCodeCMakeMinGwVsCodeCMakeMsvcQtCreatorQMakeMinGw->VsCodeQtCreatorQMakeMsvc->VsCodeQtCreatorCMakeMinGw-&g…...

Linux中离线安装gcc

gcc在安装一些其他工具的经常用到&#xff0c;在此记录下如何安装gcc。 1.在线安装 yum -y install gcc 2.离线安装 2.1 获取安装包链接&#xff1a; https://pan.baidu.com/s/1oDvt64ByWs1w-evz5TXU7w?pwd9cfo mpfr-3.1.1-4.el7.x86_64.rpmlibmpc-1.0.1-3.el7.x86_64.rp…...

告别 Kafka,拥抱 Databend:构建高效低成本的用户行为分析体系

用户行为数据埋点指标是数据仓库中不可或缺的重要数据源之一&#xff0c;同时也是企业最宝贵的资产之一。通常情况下&#xff0c;用户行为数据分析包含两大数据源&#xff1a;用户行为分析日志和上游关系型数据库&#xff08;如 MySQL&#xff09;。基于这些数据&#xff0c;企…...

【python 迪杰斯特拉-最短路径算法】

- 算法实现 import heapq import networkx as nx import matplotlib.pyplot as pltdef dijkstra(graph, start, goal):distances {node: float("infinity") for node in graph}distances[start] 0parents {node: None for node in graph}priority_queue [(0, st…...

从〇开始深度学习(0)——背景知识与环境配置

从〇开始深度学习(0)——背景知识与环境配置 文章目录 从〇开始深度学习(0)——背景知识与环境配置写在前面1.背景知识1.1.Pytorch1.2.Anaconda1.3.Pycharm1.4.CPU与GPU1.5.整体关系 2.环境配置2.1.准备工作2.1.1.判断有无英伟达显卡2.1.2.清理电脑里的旧环境 2.1.安装Anaconda…...

【NLP 2、机器学习简介】

人生的苦难不过伏尔加河上的纤夫 —— 24.11.27 一、机器学习起源 机器学习的本质 —— 找规律 通过一定量的训练样本找到这些数据样本中所蕴含的规律 规律愈发复杂&#xff0c;机器学习就是在其中找到这些的规律&#xff0c;挖掘规律建立一个公式&#xff0c;导致对陌生的数…...

多目标优化算法——多目标粒子群优化算法(MOPSO)

Handling Multiple Objectives With Particle Swarm Optimization&#xff08;多目标粒子群优化算法&#xff09; 一、摘要&#xff1a; 本文提出了一种将帕累托优势引入粒子群优化算法的方法&#xff0c;使该算法能够处理具有多个目标函数的问题。与目前其他将粒子群算法扩展…...

Edify 3D: Scalable High-Quality 3D Asset Generation

Deep Imagination Research | NVIDIA 目录 一、Abstract 二、核心内容 1、多视图扩散模型 3、重建模型&#xff1a; 4、数据处理模块&#xff1a; 三、结果 1、文本到 3D 生成结果 2、图像到 3D 生成结果 3、四边形网格拓扑结构 一、Abstract NVIDIA 开发的用于高质量…...

探索校企合作新模式:职业院校大数据专业实验(实训)室建设指南

一、引言 作为一种强大的信息处理与分析工具&#xff0c;大数据技术在企业管理、科研探索、社会治理等多个领域均产生了广泛而深远的影响。在此背景下&#xff0c;大数据实验室的建设显得尤为重要&#xff0c;而校企合作则为这一建设提供了坚实的支撑。学校借助企业资源&#…...

YOLO的框架及版本迭代

YOLO&#xff08;You Only Look Once&#xff09;是一种非常流行的实时目标检测算法&#xff0c;其特点是将目标检测任务转换为一个回归问题&#xff0c;通过一次前向传播就可以同时完成目标的分类和定位。以下是YOLO框架的整体架构和工作原理&#xff1a; 一、YOLO的基本框架…...

第四十篇 DDP模型并行

摘要 分布式数据并行(DDP)技术是深度学习领域中的一项重要技术,它通过将数据和计算任务分布在多个计算节点上,实现了大规模模型的并行训练。 DDP技术的基本原理是将数据和模型参数分割成多个部分,每个部分由一个计算节点负责处理。在训练过程中,每个节点独立计算梯度,…...

鸿蒙进阶篇-状态管理之@Provide与@Consume

大家好&#xff0c;这里是鸿蒙开天组&#xff0c;今天我们来学习一下状态管理中的Provide与Consume。 一、概述 嘿&#xff01;大家还记得这张图吗&#xff1f;不记得也要记得哦&#xff0c;因为这张图里的东西&#xff0c;既是高频必考面试题&#xff0c;也是实际开发中&…...

鸿蒙本地模拟器 模拟TCP服务端的过程

鸿蒙模拟器模拟TCP服务端的过程涉及几个关键步骤&#xff0c;主要包括创建TCPSocketServer实例、绑定IP地址和端口、监听连接请求、接收和发送数据以及处理连接事件。以下是详细的模拟过程&#xff1a; **1.创建TCPSocketServer实例&#xff1a;**首先&#xff0c;需要导入鸿蒙…...

Qt程序发布及打包成exe安装包

参考:Qt之程序发布以及打包成exe安装包 目录 一、简述 Qt 项目开发完成之后,需要打包发布程序,而因为用户电脑上没有 Qt 配置环境,所以需要将 release 生成的 exe 文件和所依赖的 dll 文件复制到一个文件夹中,然后再用 Inno Setup 打包工具打包成一个 exe 安装包,就可以…...

Spring Boot + ActiveMQ Artemis:快速实现高效消息队列处理功能

在现代微服务架构中&#xff0c;消息队列是实现异步通信、解耦系统的重要手段。而通过 Spring Boot 和 ActiveMQ Artemis&#xff0c;您可以快速搭建一个高效、可靠的消息队列处理系统&#xff0c;轻松应对订单处理、日志分析等场景。本文将带您从零开始&#xff0c;逐步实现一…...

【FPGA-MicroBlaze】串口收发以及相关函数讲解

前言 工具&#xff1a;Vivado2018.3及其所对应的SDK版本 目前网上有许多MicroBlaze 的入门教程&#xff0c;比如下面的这个参考文章&#xff0c;用串口打印一个hello world。 【FPGA】Xilinx MicroBlaze软核使用第一节&#xff1a;Hello World!_fpga软核microblaze-CSDN博客 个…...

CGAL CGAL::Polygon_mesh_processing::self_intersections解析

CGAL::Polygon_mesh_processing::self_intersections 是用于检测多边形网格&#xff08;Polygon Mesh&#xff09;中的自相交的函数。自相交是指网格中的某些面&#xff08;例如三角形&#xff09;与同一网格中的其他面交叉的情况。这种情况通常是不期望的&#xff0c;因为它会…...

猎户星空发布MoE大模型,推出AI数据宝AirDS

发布 | 大力财经 11月27日&#xff0c;猎户星空联合聚云科技举办了题为《Data Ready for Al&#xff0c;MoE大模型发布暨商业闭环分享》媒体见面会。猎户星空正式发布了自主研发的Orion-MoE 87B大模型&#xff0c;并携手聚云科技推出了基于该大模型的数据服务—AI数据宝AirDS&a…...

什么是JSON,有什么特点

什么是 JSON&#xff1f; JSON&#xff08;JavaScript Object Notation&#xff09;是一种轻量级的数据交换格式&#xff0c;易于人阅读和编写&#xff0c;同时也易于机器解析和生成。它基于 JavaScript 的子集&#xff0c;但独立于语言&#xff0c;被广泛用于服务器与 Web 应…...

SQL注入SQL盲注

SQL注入&#xff08;SQL Injection&#xff09;和 SQL盲注&#xff08;Blind SQL Injection&#xff09;是两种常见的Web安全攻击技术&#xff0c;用于攻击应用程序并操纵其与数据库的交互。以下是两者的概念和区别&#xff1a; 1. SQL注入 定义&#xff1a; SQL注入是通过将…...

汽车轮毂结构分析有哪些?国产3D仿真分析实现静力学+模态分析

本文为CAD芯智库原创&#xff0c;未经允许请勿复制、转载&#xff01; 之前分享了如何通过国产三维CAD软件如何实现「汽车/汽配行业产品设计」&#xff0c;兼容NX&#xff08;UG&#xff09;、Creo&#xff08;Proe&#xff09;&#xff0c;轻松降低企业上下游图纸交互成本等。…...

C++设计模式之组合模式在解决层次性问题中的好处

采用组合模式在处理层次型问题时&#xff0c;会带来以下重要好处&#xff1a; 简化客户端操作&#xff1a; 客户端代码可以统一地处理单个对象和组合对象&#xff0c;而无需区分它们。这意味着客户端可以使用相同的操作来对待所有对象&#xff0c;无论它们是简单的叶子节点还是…...

基于大数据爬虫+SpringBoot+Hive的网络电视剧收视率分析与可视化平台系统(源码+论文+PPT+部署文档教程等)

博主介绍&#xff1a;CSDN毕设辅导第一人、全网粉丝50W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行前辈交流✌ 技术范围&#xff1a;SpringB…...

【ESP32CAM+Android+C#上位机】ESP32-CAM在STA或AP模式下基于UDP与手机APP或C#上位机进行视频流/图像传输

前言: 本项目实现ESP32-CAM在STA或AP模式下基于UDP与手机APP或C#上位机进行视频流/图像传输。本项目包含有ESP32源码(arduino)、Android手机APP源码以及C#上位机源码,本文对其工程项目的配置使用进行讲解。实战开发,亲测无误。 AP模式,就是ESP32发出一个WIFI/热点提供给电…...

️ 如何优化爬虫程序以提高抓取效率?

在开发爬虫程序时&#xff0c;提高抓取效率是至关重要的。以下是一些常见的性能优化策略&#xff0c;可以帮助你优化Java爬虫程序&#xff1a; 多线程与分布式抓取&#xff1a; 利用多线程技术可以显著提高爬虫的抓取速度。例如&#xff0c;在WebMagic中&#xff0c;可以通过配…...

深入理解 MySQL 锁机制:分类、实现与优化

在高并发的数据库应用中&#xff0c;锁机制是保障事务在操作数据库时数据一致性和完整性的重要工具。MySQL 提供了多种类型的锁&#xff0c;不同的存储引擎和场景下的实现各具特点。本篇文章将详细介绍 MySQL 锁的分类、实现&#xff08;主动与被动&#xff09;以及优化策略。 …...

python-docx -- 读取word页眉、页脚

文章目录 sections介绍访问section添加section页眉、页脚综合案例:sections介绍 word支持section的概念,即一个文档的划分部分,不同的部分均包含相同的页面布局设置,如相同的边距、页面方向等;在每个section中可以定义页眉、页脚来应用于该section下的所有页面;大部分wor…...

DRM(数字权限管理技术)防截屏录屏----ffmpeg安装

提示&#xff1a;ffmpeg安装 文章目录 [TOC](文章目录) 前言一、下载二、配置环境变量三、运行ffmpeg四、文档总结 前言 FFmpeg是一套可以用来记录、转换数字音频、视频&#xff0c;并能将其转化为流的开源计算机程序。采用LGPL或GPL许可证。它提供了录制、转换以及流化音视频的…...

【Linux 篇】Docker 启动和停止的精准掌舵:操控指南

文章目录 【Linux 篇】Docker 启动和停止的精准掌舵&#xff1a;操控指南前言docker基本命令1. 帮助手册 2. 指令介绍 常用命令1. 查看镜像2. 搜索镜像3. 拉取镜像4. 删除镜像5. 从Docker Hub拉取 容器的相关命令1. 查看容器2. 创建与启动容器3. 查看镜像4. 启动容器5. 查看容…...

【电路设计】基于CD4511的八路抢答器电路解析

文章目录 0 前言1 CD45112 电路解析3 锁存分析4 电路优化思考5 总结 0 前言 最近收拾东西的时候找到了本科阶段学电路焊接时焊的一个八路抢答器的电路板&#xff0c;如下图所示。 一共有9个按键&#xff0c;左侧8个为抢答按键&#xff0c;依次对应1-8&#xff0c;按下之后会有…...

Python 爬虫入门教程:从零构建你的第一个网络爬虫

网络爬虫是一种自动化程序&#xff0c;用于从网站抓取数据。Python 凭借其丰富的库和简单的语法&#xff0c;是构建网络爬虫的理想语言。本文将带你从零开始学习 Python 爬虫的基本知识&#xff0c;并实现一个简单的爬虫项目。 1. 什么是网络爬虫&#xff1f; 网络爬虫&#x…...

2024年11月27日Github流行趋势

项目名称&#xff1a;screenshot-to-code 项目维护者&#xff1a;abi clean99 sweep-ai kachbit vagusX项目介绍&#xff1a;通过上传截图将其转换为整洁的代码&#xff08;支持HTML/Tailwind/React/Vue&#xff09;。项目star数&#xff1a;62,429项目fork数&#xff1a;7,614…...

深入浅出摸透AIGC文生图产品SD(Stable Diffusion)

hihi,朋友们,时隔半年(24年11月),终于能腾出时间唠一唠SD了🤣,真怕再不唠一唠,就轮不到SD了,技术更新换代是在是太快! 朋友们,最近(24年2月)是真的没时间整理笔记,每天都在疯狂的学习Stable Diffusion和WebUI & ComfyUI,工作实在有点忙,实践期间在飞书上…...

thinkphp日志记录到文件

日志 //控制器中 //这种方法调用的话&#xff0c;在general_technology下按照日期写入日志 LogService::requestLog(general_technology,$this->baseUrl .$url,$params,$res); LogService::responseLog(general_technology/hebei_product_add_error, $syncData,$msg); LogSe…...

WPF ItemsControl控件

ItemsControl 是 WPF 中一个非常灵活的控件&#xff0c;用于显示一组数据项。它是一个基类&#xff0c;许多其他控件&#xff08;如 ListBox, ListView, ComboBox 等&#xff09;都是从 ItemsControl 继承而来。ItemsControl 的主要特点是它可以自定义数据项的显示方式&#xf…...

【Android+多线程】IntentService 知识总结:应用场景 / 使用步骤 / 源码分析

定义 IntentService 是 Android中的一个封装类&#xff0c;继承自四大组件之一的Service 功能 处理异步请求 & 实现多线程 应用场景 线程任务 需 按顺序、在后台执行 最常见的场景&#xff1a;离线下载不符合多个数据同时请求的场景&#xff1a;所有的任务都在同一个T…...

编译 LLVM 源码,使用 Clion 调试 clang

版权归作者所有&#xff0c;如有转发&#xff0c;请注明文章出处&#xff1a;https://cyrus-studio.github.io/blog/ 1. LLVM 简介 LLVM 是一个开源的编译器基础架构&#xff0c;最初由 Chris Lattner 于 2000 年在伊利诺伊大学开发&#xff0c;后来成为一个广泛应用于编译器和…...

ssm199旅游景点管理系统设计+jsp(论文+源码)_kaic

毕 业 设 计&#xff08;论 文&#xff09; 题目&#xff1a;旅游景点管理系统设计与实现 摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本旅游景点管理系统…...

在英文科技论文中分号后面的单词首字母需不需要大写

英文科技论文中分号后面的单词首字母需不需要大写 分号后完整句子的首字母规则&#xff1a;1. **首字母不大写**&#xff1a;2. **专有名词大写**&#xff1a;3. **特殊上下文**&#xff1a; 在分号后&#xff0c;即使后面是一个完整的句子&#xff08;包含主语和谓语&#xff…...

<项目代码>YOLOv8 停车场空位识别<目标检测>

YOLOv8是一种单阶段&#xff08;one-stage&#xff09;检测算法&#xff0c;它将目标检测问题转化为一个回归问题&#xff0c;能够在一次前向传播过程中同时完成目标的分类和定位任务。相较于两阶段检测算法&#xff08;如Faster R-CNN&#xff09;&#xff0c;YOLOv8具有更高的…...

微知-lspci访问到指定的PCIe设备的几种方式?(lspci -s bus;lspci -d devices)

通过bdf号查看 -s &#xff08;bus&#xff09; lspci -s 03:00.0通过vendor id或者device id等设备查看 -d &#xff08;device&#xff09; lspci -d 15b3: #这里是vendor号&#xff0c;所以在前面 lspci -d :1021 #这里是设备号&#xff0c;所以要:在前vendorid和deviceid…...