CocosCreator3.8源码分析
- Cocos Creator架构
Cocos Creator 拥有两套引擎内核,C++ 内核 和 TypeScript 内核。C++ 内核用于原生平台,TypeScript 内核用于 Web 和小游戏平台。 在引擎内核之上,是用 TypeScript 编写的引擎框架层,用以统一两套内核的差异,让开发更便捷。
- engine的图像与Android的Surface对接
安卓平台下是从一个标准的activity启动,然后加载一个NativeActivity ,NativeActivity是纯c++语言实现,调用入口为全局函数android_main,里面循环执行渲染任务
然后c++端获取ANativeWindow,然后从ANativeWindow创建surface,然后使用EGL接口创建渲染表面,接着创建渲染环境
调用堆栈:
创建device,准备渲染环境:
cc::gfx::GLES3Device::doInit(const cc::gfx::DeviceInfo &) GLES3Device.cpp:79
cc::gfx::Device::initialize(const cc::gfx::DeviceInfo &) GFXDevice.cpp:67
cc::gfx::DeviceAgent::doInit(const cc::gfx::DeviceInfo &) DeviceAgent.cpp:68
cc::gfx::Device::initialize(const cc::gfx::DeviceInfo &) GFXDevice.cpp:67
cc::gfx::DeviceValidator::doInit(const cc::gfx::DeviceInfo &) DeviceValidator.cpp:76
cc::gfx::Device::initialize(const cc::gfx::DeviceInfo &) GFXDevice.cpp:67
cc::gfx::DeviceManager::tryCreate<…>(const cc::gfx::DeviceInfo &, cc::gfx::Device **) GFXDeviceManager.h:162
cc::gfx::DeviceManager::create(const cc::gfx::DeviceInfo &) GFXDeviceManager.h:105
cc::gfx::DeviceManager::create() GFXDeviceManager.h:72
cc::Engine::init() Engine.cpp:123
cc::CocosApplication::init() CocosApplication.cpp:56
cc::BaseGame::init() BaseGame.cpp:73
Game::init() Game.cpp:55
cocos_main(int, const char **) Game.cpp:65
cc::GameInputProxy::handleAppCommand(int) AndroidPlatform.cpp:533
cc::handleCmdProxy(android_app *, int) AndroidPlatform.cpp:704
process_cmd android_native_app_glue.c:177
cc::AndroidPlatform::loop() AndroidPlatform.cpp:827
cc::AndroidPlatform::run(int, const char **) AndroidPlatform.cpp:808
android_main(android_app *) JniCocosEntry.cpp:38
android_app_entry android_native_app_glue.c:210
__pthread_start(void*) 0x00000000e84c5828
__start_thread 0x00000000e847c5ce
V8引擎回调:添加一个任务到消息队列,初始化Swapchain:
cc::gfx::SwapchainAgent::doInit(const cc::gfx::SwapchainInfo &) SwapchainAgent.cpp:50
cc::gfx::Swapchain::initialize(const cc::gfx::SwapchainInfo &) GFXSwapchain.cpp:45
cc::gfx::SwapchainValidator::doInit(const cc::gfx::SwapchainInfo &) SwapchainValidator.cpp:51
cc::gfx::Swapchain::initialize(const cc::gfx::SwapchainInfo &) GFXSwapchain.cpp:45
cc::gfx::Device::createSwapchain(const cc::gfx::SwapchainInfo &) GFXDevice.h:234
cc::Root::createRenderWindowFromSystemWindow(cc::ISystemWindow *) Root.cpp:119
cc::Root::initialize(cc::gfx::Swapchain *) Root.cpp:82
js_cc_Root__initialize(se::State &) jsb_scene_auto.cpp:4918
jsbFunctionWrapper(const v8::FunctionCallbackInfo<…> &, bool (*)(se::State &), const char *) HelperMacros.cpp:99
js_cc_Root__initializeRegistry(const v8::FunctionCallbackInfo<…> &) jsb_scene_auto.cpp:4923
v8::internal::FunctionCallbackArguments::Call(v8::internal::CallHandlerInfo) 0x00000000bd00ba24
执行消息队列初始化Swapchain任务:初始化上屏surface
cc::gfx::GLES3Swapchain::doInit(const cc::gfx::SwapchainInfo &) GLES3Swapchain.cpp:117
cc::gfx::Swapchain::initialize(const cc::gfx::SwapchainInfo &) GFXSwapchain.cpp:45
SwapchainInit::execute() SwapchainAgent.cpp:50
cc::MessageQueue::executeMessages() MessageQueue.cpp:249
cc::MessageQueue::flushMessages() MessageQueue.cpp:236
cc::MessageQueue::consumerThreadLoop() MessageQueue.cpp:277
decltype(*std::__ndk1::forward<cc::MessageQueue*>(fp0).*fp()) std::__ndk1::__invoke<void (cc::MessageQueue::*)() noexcept, cc::MessageQueue*, void>(void (cc::MessageQueue::*&&)() noexcept, cc::MessageQueue*&&) type_traits:3815
void std::__ndk1::__thread_execute<std::__ndk1::unique_ptr<std::__ndk1::__thread_struct, std::__ndk1::default_delete<std::__ndk1::__thread_struct>>, void (cc::MessageQueue::*)() noexcept, cc::MessageQueue*, 2u>(std::__ndk1::tuple<std::__ndk1::unique_ptr<std::__ndk1::__thread_struct, std::__ndk1::default_delete<std::__ndk1::__thread_struct>>, void (cc::MessageQueue::*)() noexcept, cc::MessageQueue*>&, std::__ndk1::__tuple_indices<2u>) thread:273
void* std::__ndk1::__thread_proxy<std::__ndk1::tuple<std::__ndk1::unique_ptr<std::__ndk1::__thread_struct, std::__ndk1::default_delete<std::__ndk1::__thread_struct>>, void (cc::MessageQueue::*)() noexcept, cc::MessageQueue*>>(void*) thread:284
__pthread_start(void*) 0x00000000e84c5828
__start_thread 0x00000000e847c5ce
3. V8简介
3.1 V8的API定义了几个基本概念:句柄(handle)、作用域(scope)、上下文环境(Context)、模板(Templates)。
- 上下文环境Context就是脚本的运行环境,JavaScript的变量、函数等都存在于上下文环境Context中。Context可以嵌套,即当前函数有一个Context,调用其它函数时如果又有一个Context,则在被调用的函数中javascript是以最近的Context为准的,当退出这个函数时,又恢复到了原来的Context。
- 句柄(handle)就是一个指向V8对象的指针,有点像C++的智能指针。所有的v8对象必须使用句柄来操作。没有句柄指向的V8对象,很快会被垃圾回收器回收了。
- 作用域(scope)是句柄的容器,一个作用域(scope)可以有很多句柄(handle)。当离开一个作用域(scope)时,所有在作用域(scope)里的句柄(handle)都会被释放了。
- 模板(Templates)分为函数模板和对象模板,是V8对JavaScript的函数和对象的封装。方便C++语言操作JavaScript的函数和对象。
V8 API定义了一组类或者模板,用来与JavaScript的语言概念一一对应。比如:
V8的 Function模板与JavaScript的函数对应
V8的Object类与JavaScript的对象对应
V8的String类与JavaScript的字符对应
V8的Script类与JavaScript的脚本文本对应,它可以编译并执行一段脚本
3.2 c++和JavaScript交互 - c++调用JavaScript
在C++中访问Javascript脚本中的内容,首先要调用Context::GetCurrent()->Global()获取到Global全局对象,再通过Global全局对象的Get函数来提取Javascript的全局变量、全局函数、全局复杂对象。 - JavaScript调用c++
使用V8,在Javascript脚本中想要访问C++中的内容,必须先将C++的变量、函数、类注入到Javacsript中。注入时,首先要调用Context::GetCurrent()->Global()获取到Global对象,再通过Global对象的Set函数来注入全局变量、全局函数、类对象。
4. Cocos引擎内部Cpp和js交互方式
4.1 Jsb绑定机制,实现为上一小结JavaScript调用c++的方式
手动绑定的c++接口位置:engine\native\cocos\bindings\manual
自动绑定:工程构建时通过Cmake 脚本engine\native\cmake\predefine.cmake批量 生成jsb2.0可绑定得c++方法到:工程目录\build\android\proj\build\Debug\xxxxxx\armeabi-v7a\generated\cocos\bindings\auto,swig工具配置文件目录: engine\native\tools\swig-config
基于反射的旧方式:jsb.reflection.callStaticMethod,支持从 ts 端直接调用 Native 端的接口,性能较jsb慢
4.2 共享内存:共享 CPP 的内存到 JS ,实现类:bindings::NativeMemorySharedToScriptActor。
5. Cocos启用V8引擎
V8引擎启动堆栈:
se::ScriptEngine::start() ScriptEngine.cpp:772
cc::CocosApplication::init() CocosApplication.cpp:95
cc::BaseGame::init() BaseGame.cpp:73
Game::init() Game.cpp:55
cocos_main(int, const char ) Game.cpp:65
cc::GameInputProxy::handleAppCommand(int) AndroidPlatform.cpp:533
cc::handleCmdProxy(android_app *, int) AndroidPlatform.cpp:704
process_cmd android_native_app_glue.c:177
cc::AndroidPlatform::loop() AndroidPlatform.cpp:827
cc::AndroidPlatform::run(int, const char ) AndroidPlatform.cpp:808
android_main(android_app *) JniCocosEntry.cpp:38
se引擎调用main.js入口文件堆栈
se::ScriptEngine::evalString(const char *, unsigned int, se::Value *, const char *) ScriptEngine.cpp:880
setCanvasCallback(se::Object *) Engine.cpp:97
se::ScriptEngine::callRegisteredCallback() ScriptEngine.cpp:758
se::ScriptEngine::start() ScriptEngine.cpp:800
cc::CocosApplication::init() CocosApplication.cpp:95
cc::BaseGame::init() BaseGame.cpp:73
Game::init() Game.cpp:55
cocos_main(int, const char ) Game.cpp:65
cc::GameInputProxy::handleAppCommand(int) AndroidPlatform.cpp:533
cc::handleCmdProxy(android_app *, int) AndroidPlatform.cpp:704
process_cmd android_native_app_glue.c:177
cc::AndroidPlatform::loop() AndroidPlatform.cpp:827
cc::AndroidPlatform::run(int, const char ) AndroidPlatform.cpp:808
android_main(android_app *) JniCocosEntry.cpp:38
android_app_entry android_native_app_glue.c:210
__pthread_start(void*) 0x00000000e84c5828
__start_thread 0x00000000e847c5ce
V8引擎调用c++,创建渲染表面:
cc::gfx::SwapchainAgent::doInit(const cc::gfx::SwapchainInfo &) SwapchainAgent.cpp:50
cc::gfx::Swapchain::initialize(const cc::gfx::SwapchainInfo &) GFXSwapchain.cpp:45
cc::gfx::SwapchainValidator::doInit(const cc::gfx::SwapchainInfo &) SwapchainValidator.cpp:51
cc::gfx::Swapchain::initialize(const cc::gfx::SwapchainInfo &) GFXSwapchain.cpp:45
cc::gfx::Device::createSwapchain(const cc::gfx::SwapchainInfo &) GFXDevice.h:234
cc::Root::createRenderWindowFromSystemWindow(cc::ISystemWindow *) Root.cpp:119
cc::Root::initialize(cc::gfx::Swapchain *) Root.cpp:82
js_cc_Root__initialize(se::State &) jsb_scene_auto.cpp:4918
jsbFunctionWrapper(const v8::FunctionCallbackInfo<…> &, bool (*)(se::State &), const char *) HelperMacros.cpp:99
js_cc_Root__initializeRegistry(const v8::FunctionCallbackInfo<…> &) jsb_scene_auto.cpp:4923
v8::internal::FunctionCallbackArguments::Call(v8::internal::CallHandlerInfo) 0x00000000bd00ba24
6. Native引擎流程图
7. 工程加载
7.1 构建配置声明文件:
resources\app.asar.unpacked\builtin\builder@types\public\build-result.d.ts
7.2 模板&入口文件:
engine\platforms\native\builtin*.js 编译为-> jsb-adapter/web-adapter.js //web接口封装
engine\platforms\native\engine*.js 编译为-> jsb-adapter/engine-adapter.js //引擎接口封装
engine\templates\native\index.ejs -> main.js
engine\templates\launcher\application.ejs -> application.js
7.3 工程启动流程图
有空补
8. Cocos Creator引擎流程图
9. Cocos 渲染管线
Cocos 渲染管线有内置的两种渲染管线:前向渲染管线、延迟渲染管线,和可自定义的渲染管线:
9.1 前向渲染管线
引擎默认使用 前向渲染管线,前向渲染管线的执行流程如下图所示:
前向渲染主要包括 ShadowFlow 和 ForwardFlow 两个阶段:
- ShadowFlow 中包含一个 ShadowStage 会预先对场景中需要投射阴影的物体进行阴影贴图的绘制。
- ForwardFlow 包含一个 ForwardStage,会对场景中所有物体按照 非透明 -> 光照 -> 透明 -> UI 的顺序依次进行绘制。在计算光照时,每个物体都会与所有光照进行计算确定是否照射到该物体,照射到该物体的光照将会执行绘制并进行光照计算,目前场景中只支持一个平行光,可接受的最大光照数量为 16。
9.2 延迟渲染管线
目前引擎提供了试验版本的内置 延迟渲染管线,对于光照数量比较多的项目可以使用 延迟渲染管线 来缓解光照计算的压力。延迟管线的执行流程如下图所示:
内置的延迟渲染管线主要包括 ShadowFlow 和 MainFlow 两个过程:
- ShadowFlow 与前向渲染一致,用于预先进行阴影贴图的绘制。
- MainFlow 包含了 GBufferStage、LightingStage、BloomStage 和 PostProcessStage 四个阶段:
- GbufferStage 会对场景中的非透明物体进行绘制;
- 然后 LightingStage 会对输出到 GBuffer 中的非透明物体信息进行基于屏幕空间的光照计算,再绘制半透明物体。如果有非透明物体并且设备支持 ComputeShader,还会进行 SSPR 的资源收集与绘制;
- 若还开启了 Bloom 效果,BloomStage 会对已经经过 LightingStage 处理后的图像进行 Bloom 后处理;
- 最后 PostProcessStage 会把 BloomStage/LightingStage 输出的全屏图像绘制到主屏幕中,再进行 UI 的绘制。
9.3 自定义渲染管线
自定义渲染管线以数据流(Dataflow)的形式概括了渲染的整个流程,用渲染图(RenderGraph)描述。
渲染图由不同的渲染节点组成,比如渲染通道(RenderPass),计算通道(ComputePass)等。每个渲染通道有数据输入与输出,比如渲染目标(RenderTarget)、深度模板(DepthStencil)、贴图(Texture)等。这些输入与输出会在计算节点间构成链接关系,形成数据流。
在渲染通道、计算通道节点下,可以有渲染队列(RenderQueue)子节点,用于控制渲染的顺序。渲染队列节点下,可以有渲染内容(RenderContent)子节点,用于控制渲染的内容。
渲染内容 可以是 场景、屏幕 矩形,也可以是计算任务的 分发(Dispatch),不同的通道支持不同的渲染内容。
自定义渲染管线 的【渲染通道、渲染队列、渲染内容】构成一个森林:
自定义渲染管线的【渲染通道、渲染资源】构成一个有向无环图(DAG):
9.4 :前向渲染pipeline流程
有空补
10. Cocos原生引擎调试方法
10.1 原生平台 JavaScript 调试
Android 真机调试
如果游戏只有在真机上才能运行,那就必须用真机对打包后的游戏进行调试。调试步骤如下:
- 确保 Android/iOS 设备与 Windows 或者 Mac 在同一个局域网中。注意在调试过程中请勿开启代理,否则可能导致无法正常调试。
- 在 Creator 的 构建发布 面板选择 Android/iOS 平台、Debug 模式,构建编译运行工程(iOS 平台建议通过 Xcode 连接真机进行编译运行)。
- 用 Chrome 浏览器打开地址:devtools://devtools/bundled/js_app.html?v8only=true&ws=设备的本地 IP:6086/00010002-0003-4004-8005-000600070008 即可进行调试。公司电脑因为网络问题,6086这个端口号用不了,可通过运行apk从logcat查看分配的端口号,Android Studio logcat信息如下:
adb shell ip -4 -br addr
查询手机IP地址
Windows 平台及 Mac 平台调试
在 Windows 平台及 Mac 平台下调试游戏,步骤与真机调试类似,将工程用 IDE 编译运行之后,此时便可进行调试。步骤如下:
- 用 IDE 将打包好的工程编译并运行(Windows 平台请使用 Visual Studio,Mac 平台请使用 Xcode)
- 在游戏运行时打开 Chrome 浏览器,输入地址:devtools://devtools/bundled/js_app.html?v8only=true&ws=127.0.0.1:6086/00010002-0003-4004-8005-000600070008 即可进行打断点调试
10.2 c++中查看当前的 JS 调用栈
A. c++ 源码中使用se引擎获取js堆栈接口
通过在 C++ 中断点我们能很便捷地看到 C++ 的调用栈,但并不能同时看到 JS 的调用栈,这个割裂的过程常常会破坏调试的体验
源码中使用ScriptEngine引擎的这个接口,可以获取当前js调用栈:
se::ScriptEngine::getInstance()->getCurrentStackTrace()
或 :
utils::getStacktraceJS()
B. Android 平台下使用LLDB工具注入命令(慎用,自测总是闪退,报解析错误):
断点后LLDB终端输入如下命令:
po se::ScriptEngine::getInstance()->getCurrentStackTrace()
相关文章:

CocosCreator3.8源码分析
Cocos Creator架构 Cocos Creator 拥有两套引擎内核,C 内核 和 TypeScript 内核。C 内核用于原生平台,TypeScript 内核用于 Web 和小游戏平台。 在引擎内核之上,是用 TypeScript 编写的引擎框架层,用以统一两套内核的差异…...

(已解决)spingboot 后端发送QQ邮箱验证码
打开QQ邮箱pop3请求服务:(按照QQ邮箱引导操作) 导入依赖(不是maven项目就自己添加jar包): <!-- 邮件发送--><dependency><groupId>org.springframework.boot</groupId><…...

【蓝桥杯冲冲冲】[NOIP2001 普及组] 装箱问题
蓝桥杯备赛 | 洛谷做题打卡day26 文章目录 蓝桥杯备赛 | 洛谷做题打卡day26题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 提示思路 题解代码我的一些话 [NOIP2001 普及组] 装箱问题 题目描述 有一个箱子容量为 V V V,同时有 n n n 个物品,每…...

2024牛客寒假算法基础集训营1
文章目录 A DFS搜索M牛客老粉才知道的秘密G why外卖E 本题又主要考察了贪心B 关鸡C 按闹分配 今天的牛客,说是都是基础题,头昏昏的,感觉真不会写,只能赛后补题了 A DFS搜索 写的时候刚开始以为还是比较难的,和dfs有关…...

元素的显示与隐藏,精灵图,字体图标,CSSC三角
元素的显示与隐藏 类似网站广告,当我们点击关闭就不见了,但是我们重新刷新页面,会重新出现 本质:让元素在页面中隐藏或者显示出来。 1.display显示隐藏 2.visibility显示隐藏 3.overflow溢出显示隐藏 1.display属性(…...

最新!2024顶级SCI优化!TTAO-CNN-BiGRU-MSA三角拓扑聚合优化、双向GRU融合注意力的多变量回归预测程序!
适用平台:Matlab 2023版及以上 TTOA三角聚合优化算法,将在2024年3月正式发表在中科院1区顶级SCI期刊《Expert Systems with Applications》上。 该算法提出时间极短,目前以及近期内不会有套用这个算法的文献。新年伊始,尽快拿下…...
Flink SQL Client 安装各类 Connector、组件的方法汇总(持续更新中....)
一般来说,在 Flink SQL Client 中使用各种 Connector 只需要该 Connector 及其依赖 Jar 包部署到 ${FLINK_HOME}/lib 下即可。但是对于某些特定的平台,如果 AWS EMR、Cloudera CDP 等产品会有所不同,主要是它们中的某些 Jar 包可能被改写过&a…...

React18-模拟列表数据实现基础表格功能
文章目录 分页功能分页组件有两种接口参数分页类型用户列表参数类型 模拟列表数据分页触发方式实现目录 分页功能 分页组件有两种 table组件自带分页 <TableborderedrowKey"userId"rowSelection{{ type: checkbox }}pagination{{position: [bottomRight],pageSi…...

MySQL查询数据(十)
MySQL查询数据(十) 一、SELECT基本查询 1.1 SELECT语句的功能 SELECT 语句从数据库中返回信息。使用一个 SELECT 语句,可以做下面的事: **列选择:**能够使用 SELECT 语句的列选择功能选择表中的列,这些…...

AJAX-常用请求方法和数据提交
常用请求方法 请求方法:对服务器资源,要执行的操作 axios请求配置 url:请求的URL网址 method:请求的方法,如果是GET可以省略;不用区分大小写 data:提交数据 axios({url:目标资源地址,method…...

2024美国大学生数学建模竞赛美赛B题matlab代码解析
2024美赛B题Searching for Submersibles搜索潜水器 因为一些不可抗力,下面仅展示部分代码(很少部分部分)和部分分析过程,其余代码看文末 Dthxlsread(C:\Users\Lenovo\Desktop\Ionian.xlsx); DpDth(:,3:5); dy0.0042; dx0.0042; …...
【DouYing Desktop】
I) JD 全日制大专及以上学历; 2. 3年以上的IT服务支持相关工作经验 3. 有较强的桌面相关trouble shooting与故障解决能力,能够独立应对各类型桌面问题; 4. 具备基础的网络、系统知识,能够独立解决常见的网络、系统等问题…...

正则表达式与文本处理工具
目录 引言 一、正则表达式基础 (一)字符匹配 1.基本字符 2.特殊字符 3.量词 4.边界匹配 (二)进阶用法 1.组与引用 2.选择 二、命令之-----grep (一)基础用法 (二)高级用…...

IDEA中的Run Dashboard
Run Dashboard是IntelliJ IDEA中的工具【也就是View中的Services】,提供一个可视化界面,用于管理控制应用程序的运行和调试过程。 在Run DashBoard中,可以看到所有的运行配置,以及每个配置的运行状态(正在运行…...

【力扣白嫖日记】SQL
前言 练习sql语句,所有题目来自于力扣(https://leetcode.cn/problemset/database/)的免费数据库练习题。 今日题目: 1407.排名靠前的旅行者 表:Users 列名类型idintnamevarchar id 是该表中具有唯一值的列。name …...
自动化报告pptx-python|高效通过PPT模版制造报告(三)
这是自动化报告学习的第三篇了,前面两篇分别是: 自动化报告的前奏|使用python-pptx操作PPT(一)自动化报告pptx-python|如何将pandas的表格写入PPTX(二)本篇是逼着笔者看到JoStudio 大佬自己写的一个jojo-office 库,基于pptx-python开发成一套试用office软件的依赖,非…...
Linux升级openssh的解决方案
大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…...

YOLOv5白皮书-第Y3周:yolov5s.yaml文件解读
YOLOv5白皮书-第Y3周:yolov5s.yaml文件解读 YOLOv5白皮书-第Y3周:yolov5s.yaml文件解读一、前言二、我的环境三、yolov5s.yaml源文件内容四、Parameters五、anchors配置六、backbone七、head八、总结 OLOv5-第Y2周:训练自己的数据集) YOLOv5白皮书-第Y3周:yolov5s.…...

C++ pair+map+set+multimap+multiset+AVL树+红黑树(深度剖析)
文章目录 1. 前言2. 关联式容器3. pair——键值对4. 树形结构的关联式容器4.1 set4.1.1 set 的介绍4.1.2 set 的使用 4.2 map4.2.1 map 的介绍4.2.2 map 的使用 4.3 multiset4.3.1 multiset 的介绍4.3.2 multiset 的使用 4.4 multimap4.4.1 multimap 的介绍4.4.2 multimap 的使…...

指针的学习1
目录 什么是指针? 野指针 造成野指针的原因: 如何避免野指针? 内存和指针 如何理解编址? 指针变量和地址 取地址操作符& 指针变量和解引用操作符 指针变量 如何拆解指针类型? 指针变量的大小 指针变量…...
深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法
深入浅出:JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中,随机数的生成看似简单,却隐藏着许多玄机。无论是生成密码、加密密钥,还是创建安全令牌,随机数的质量直接关系到系统的安全性。Jav…...
FastAPI 教程:从入门到实践
FastAPI 是一个现代、快速(高性能)的 Web 框架,用于构建 API,支持 Python 3.6。它基于标准 Python 类型提示,易于学习且功能强大。以下是一个完整的 FastAPI 入门教程,涵盖从环境搭建到创建并运行一个简单的…...

基于Docker Compose部署Java微服务项目
一. 创建根项目 根项目(父项目)主要用于依赖管理 一些需要注意的点: 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件,否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...
什么是EULA和DPA
文章目录 EULA(End User License Agreement)DPA(Data Protection Agreement)一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA(End User License Agreement) 定义: EULA即…...
leetcodeSQL解题:3564. 季节性销售分析
leetcodeSQL解题:3564. 季节性销售分析 题目: 表:sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...

深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南
🚀 C extern 关键字深度解析:跨文件编程的终极指南 📅 更新时间:2025年6月5日 🏷️ 标签:C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言🔥一、extern 是什么?&…...

在Mathematica中实现Newton-Raphson迭代的收敛时间算法(一般三次多项式)
考察一般的三次多项式,以r为参数: p[z_, r_] : z^3 (r - 1) z - r; roots[r_] : z /. Solve[p[z, r] 0, z]; 此多项式的根为: 尽管看起来这个多项式是特殊的,其实一般的三次多项式都是可以通过线性变换化为这个形式…...

手机平板能效生态设计指令EU 2023/1670标准解读
手机平板能效生态设计指令EU 2023/1670标准解读 以下是针对欧盟《手机和平板电脑生态设计法规》(EU) 2023/1670 的核心解读,综合法规核心要求、最新修正及企业合规要点: 一、法规背景与目标 生效与强制时间 发布于2023年8月31日(OJ公报&…...
Monorepo架构: Nx Cloud 扩展能力与缓存加速
借助 Nx Cloud 实现项目协同与加速构建 1 ) 缓存工作原理分析 在了解了本地缓存和远程缓存之后,我们来探究缓存是如何工作的。以计算文件的哈希串为例,若后续运行任务时文件哈希串未变,系统会直接使用对应的输出和制品文件。 2 …...

小智AI+MCP
什么是小智AI和MCP 如果还不清楚的先看往期文章 手搓小智AI聊天机器人 MCP 深度解析:AI 的USB接口 如何使用小智MCP 1.刷支持mcp的小智固件 2.下载官方MCP的示例代码 Github:https://github.com/78/mcp-calculator 安这个步骤执行 其中MCP_ENDPOI…...