简介cpr-1.3.0 是面向 C 开发者的预编译 HTTP 客户端库文件包基于 C Requests 项目封装 libcurl适合需要在 VS2015 环境中快速接入网络请求、又不想从源码编译依赖的开发者。包内共 27 个文件以 21 个头文件和 4 个 lib、2 个 dll 为主头文件对应会话、响应、认证、超时、代理、重定向、SSL 选项等接口lib 与 dll 分别提供 Debug/Release 链接库和 libcurl 动态库压缩包约 738KB解压后可直接加入工程引用。资源省去自行编译 cpr 与 libcurl 的时间便于快速验证 GET/POST、参数传递、Cookie、超时与代理等常见调用也适合作为课程实验或小工具项目的 HTTP 通信基础。已有 691 人学习对希望减少环境配置、专注业务代码的 C 学习者较有参考价值。1. 从一段两百行的 curl 胶水代码说起cpr 1.3.0 到底替你封装了什么接手一个 C 边缘服务时最怕看到业务代码里散着几十处curl_easy_setopt超时、header、回调、内存释放全挤在一起改一个字段要翻三处。cpr 1.3.0C Requests就是冲这个场景来的——它把 libcurl 的 C 状态机包成 RAII 风格的 C 对象Url、Parameters、Header、Body、Timeout都是可组合的请求选项Response直接给出status_code、text、header和error。它不试图替代重型网络框架而是让一个 C11 工程在半小时内拥有接近脚本语言的 HTTP 调用体验。适合谁手里已有 libcurl、又不想在业务层直接碰CURLOPT_*的团队需要 HTTPS、表单、JSON、文件下载但不想引入完整 RPC 栈的维护者。不适合谁需要 HTTP/2 精细控制、连接池跨线程共享、或者必须零依赖的单文件场景——那些情况直接写 libcurl 反而更透明。2. 把 cpr 1.3.0 编进工程CMake 集成、依赖链与四个构建开关2.1 目录结构与依赖链cpr、libcurl、SSL 后端、zlib拿到 cpr 1.3.0 的源码包先别急着cmake ..。解开后看顶层include/cpr是对外头文件cpr目录是源文件test是测试根目录的CMakeLists.txt决定它怎么找依赖。cpr 本身不实现 socket 和 TLS它把活交给 libcurl所以真正要盯的是三件事libcurl 能不能被 CMake 找到、SSL 后端是哪一个、zlib 要不要一起链。Linux 上常见组合是系统 libcurl OpenSSLWindows 上如果自己编 libcurl要注意 debug/release 运行库一致否则会在链接期报一堆LNK2038。我一般先跑一遍依赖探测把 libcurl 的版本和 SSL 后端打印出来再决定用源码内嵌还是系统包。cmake_minimum_required(VERSION 3.14) project(cpr_demo LANGUAGES CXX) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON) # 把 cpr 1.3.0 放在 third_party/cpr直接作为子目录编进来 add_subdirectory(third_party/cpr) add_executable(cpr_demo src/main.cpp) target_link_libraries(cpr_demo PRIVATE cpr)上面这段的关键不是add_subdirectory本身而是target_link_libraries里写的是cpr这个 target不是手写-lcpr。cpr 的 CMake target 会把 include 路径和 libcurl 的传递依赖一起带出来手写库名很容易漏掉curl、ssl、crypto、z这一串。编译时先关测试省时间cmake -S . -B build \ -DCPR_BUILD_TESTSOFF \ -DCPR_ENABLE_SSLON \ -DCMAKE_BUILD_TYPEDebug cmake --build build -jCPR_BUILD_TESTSOFF是常规操作cpr 的测试会拉一些额外依赖业务工程没必要编。CPR_ENABLE_SSLON控制是否编 HTTPS 支持如果这版 CMakeLists 里选项名有差异传了最多得到一个 unused variable 警告不会把构建弄挂但最好先grep -n option( third_party/cpr/CMakeLists.txt确认一遍。CMAKE_BUILD_TYPEDebug建议在接入期打开链接失败时能看到完整符号。2.2 两种接入方式add_subdirectory 与 find_package源码内嵌适合“我要固定 1.3.0 这个版本、不希望构建机预装 cpr”的场景。把整个目录放进third_party/cpr主工程只依赖一个相对路径换机器不用改环境。缺点是主工程配置阶段会多编一个库CI 缓存没做好的话每次全量构建会多几十秒。另一种方式是先安装 cpr再用find_packagefind_package(cpr REQUIRED) target_link_libraries(cpr_demo PRIVATE cpr::cpr)cpr::cpr是安装后导出的命名空间 target。如果find_package报cprConfig.cmake找不到先确认安装前缀有没有进CMAKE_PREFIX_PATHcmake -S . -B build \ -DCMAKE_PREFIX_PATH/opt/cpr-1.3.0 \ -DCMAKE_BUILD_TYPERelease这里有个选择逻辑团队里如果有人负责基础镜像find_package更干净如果 cpr 只是这个项目的一个小依赖add_subdirectory更省事。我通常在新项目里先用add_subdirectory跑通等接口稳定了再切成安装包避免一开始就在“找包”上耗时间。注意两种方式不要混用既add_subdirectory又find_package容易出现两个 cpr target 同名链接行里出现重复符号。2.3 静态链接与动态链接传递依赖和运行期库路径cpr 1.3.0 默认跟着BUILD_SHARED_LIBS走。静态链接的好处是部署简单坏处是 libcurl 的依赖会全部压进最终产物动态链接的好处是多个进程共享库坏处是运行期要找得到.so或.dll。我一般这样切# 动态库构建安装到 dist 目录 cmake -S . -B build-shared \ -DBUILD_SHARED_LIBSON \ -DCMAKE_INSTALL_PREFIX./dist \ -DCPR_BUILD_TESTSOFF cmake --build build-shared -j cmake --install build-shared编完之后用ldd看一眼最终可执行文件依赖了哪些库ldd build-shared/cpr_demo | grep -E cpr|curl|ssl|crypto如果libcpr.so显示not found不是链接错了是运行期搜索路径没配。Linux 下可以在 CMake 里设INSTALL_RPATH或者把dist/lib加进LD_LIBRARY_PATHWindows 下把cpr.dll和libcurl.dll放到 exe 同目录。这里常见的翻车点是编译机上有 libcurl运行容器里没有程序启动直接报error while loading shared libraries。所以动态链接方案一定要在目标环境里跑一次ldd别只在开发机验证。提示如果链接期报undefined reference to curl_easy_init先看链接行里有没有-lcurl。用cmake --build build --verbose把完整链接命令打出来比猜快得多。3. 第一个可复现请求GET/POST、参数编码与响应对象拆解3.1 最小 GETUrl、Parameters 与 Response 字段先写一个能跑的最小 GET不要一上来就封工具类。下面这段请求https://example.com/search带两个查询参数超时 3 秒#include cpr/cpr.h #include iostream int main() { cpr::Response r cpr::Get( cpr::Url{https://example.com/search}, cpr::Parameters{{q, c http}, {page, 1}}, cpr::Header{{User-Agent, cpr-demo/1.0}}, cpr::Timeout{3000} ); if (r.error.code ! cpr::ErrorCode::OK) { std::cerr request failed: r.error.message \n; return 1; } std::cout status r.status_code \n; std::cout elapsed_ms r.elapsed.count() \n; std::cout body_size r.text.size() \n; std::cout content_type r.header[Content-Type] \n; return 0; }cpr::Parameters会自动做 URL 编码c http里的空格和加号不用自己处理。cpr::Timeout{3000}的单位是毫秒不是秒这里写 3000 就是 3 秒。r.error.code比status_code更早判断DNS 失败、连接超时、SSL 握手失败时status_code是 0只有error里有原因。r.elapsed是总耗时单位毫秒打日志时很有用。r.header按响应头键名取如果服务端返回的键名大小写和预期不一致先遍历打印一遍别硬编码。字段类型用途status_codeintHTTP 状态码连接失败时为 0textstd::string响应体小响应直接读headercpr::Header响应头按 key 取urlcpr::Url最终 URL重定向后看这个elapsed时间量总耗时单位毫秒errorcpr::Error错误码和消息先判它3.2 POST 的两种 bodyPayload 表单与 Body Content-TypePOST 最容易出错的是“到底该用 Payload 还是 Body”。cpr::Payload走application/x-www-form-urlencodedkey 和 value 会自动编码cpr::Body是原样发送Content-Type 必须自己设。两者别混// 表单提交Content-Type 自动为 application/x-www-form-urlencoded cpr::Response form cpr::Post( cpr::Url{https://example.com/login}, cpr::Payload{{user, demo}, {password, pss word}} ); // JSON 提交Body 原样发送必须显式设 Content-Type cpr::Response json cpr::Post( cpr::Url{https://example.com/api/items}, cpr::Header{{Content-Type, application/json}}, cpr::Body{R({name:测试项,count:3})} );Payload里的空格会被编码成或%20服务端按表单解析时能正确还原。Body里的中文要求源文件是 UTF-8且 JSON 字符串本身要合法如果拼字符串时漏了转义引号服务端会返回 400但 cpr 不会替你校验 JSON。一个实用习惯把 JSON body 单独存成const std::string发之前打印长度和前 200 字节比出问题后抓瞎强。3.3 超时、重定向与 Header 的显式设置cpr 的请求选项可以叠加但默认值不要猜。重定向是否跟随、SSL 是否校验、连接超时多少最好在代码里写死cpr::Response r cpr::Get( cpr::Url{https://example.com/redirect}, cpr::Timeout{3000}, // 整个请求最多 3 秒 cpr::ConnectTimeout{800}, // 连接阶段最多 800 毫秒 cpr::Redirect{true}, // 显式跟随 3xx cpr::VerifySsl{true} // 生产环境保持开启 );Timeout覆盖从发起到收完响应的总时间ConnectTimeout只覆盖 TCP 和 TLS 握手。两个都设才能区分“连不上”和“连上了但服务端慢”。Redirect{true}显式写出来避免升级版本后默认行为变化导致 302 被当成失败。VerifySsl{false}只在本地自签证书调试时用提交前记得改回来生产环境关掉校验等于把中间人攻击的门打开。Header 里不要手动设Content-Length让 libcurl 自己算手设容易和实际 body 长度不一致。4. Session 复用与并发边界三个必须显式设置的参数4.1 Session 的生命周期一个线程一个 Sessioncpr::Session不是线程安全的它内部持有一个 libcurl easy handlehandle 上有连接缓存、cookie、认证状态。多线程共享一个 Session轻则响应串包重则段错误。正确做法是每个线程一个 Session线程内循环复用#include cpr/cpr.h #include thread #include vector #include iostream void worker(int id, const std::string url, int rounds) { cpr::Session session; // 每个线程独立 Session session.SetUrl(cpr::Url{url}); session.SetTimeout(cpr::Timeout{2000}); session.SetConnectTimeout(cpr::ConnectTimeout{500}); session.SetHeader(cpr::Header{{Connection, keep-alive}}); for (int i 0; i rounds; i) { cpr::Response r session.Get(); // 复用同一个 easy handle if (r.error.code ! cpr::ErrorCode::OK) { std::cerr worker id error: r.error.message \n; continue; } // 业务处理 } } int main() { const std::string url http://127.0.0.1:8080/health; std::vectorstd::thread threads; for (int i 0; i 8; i) { threads.emplace_back(worker, i, url, 500); } for (auto t : threads) t.join(); return 0; }这段代码的重点不是线程数而是session在for循环外面。放在循环里面每轮都新建 easy handle连接复用直接归零。SetHeader里的Connection: keep-alive在 HTTP/1.1 里是默认行为显式写是为了让中间层别随手关连接。SetTimeout和SetConnectTimeout也是每个 Session 设一次不要每轮重复设。4.2 连接复用、DNS 缓存与超时参数cpr 1.3.0 没有把 libcurl 的所有连接池参数都暴露出来但“同一个 Session 连续请求会复用连接”这一点是成立的。复用的收益在短请求上最明显省掉 TCP 握手和 TLS 握手单次延迟能从几十毫秒降到几毫秒。DNS 缓存也挂在 easy handle 上Session 活得越久重复解析越少。所以我的习惯是一个线程一个长生命周期 Session请求参数用SetUrl、SetParameters、SetBody逐次覆盖不要每次cpr::Get新建临时对象。但长生命周期带来两个边界。第一cookie 和认证状态会累积如果业务需要无状态请求每轮开始前session.SetCookies(cpr::Cookies{})清一下或者干脆用短 Session。第二连接被服务端关掉后下一次请求会重连这是正常现象不要因为偶发一次延迟升高就怀疑复用失效。超时参数要按业务分健康检查 500 毫秒连接超时、2 秒总超时文件下载 5 秒连接超时、60 秒总超时。别一套超时打天下。4.3 并发验证用本地服务观察连接数复用有没有生效不看日志看连接数。本地起一个 HTTP 服务监听 8080跑上面的多线程程序同时在另一个终端执行# 观察 8080 端口上 ESTABLISHED 的连接数 ss -tan state established ( dport :8080 ) | tail -n 2 | wc -l如果每轮请求都新建连接这个数字会随请求量快速上涨复用生效时8 个线程大致稳定在 8 到 16 条连接具体取决于服务端 keep-alive 超时。这个数字不是绝对指标但能快速判断“连接到底有没有复用”。另一个观察点是r.elapsed第一轮通常偏慢后面几轮明显下降说明 TLS 和连接建立被省掉了。注意线程数不是越多越好。cpr 每个 Session 占一个连接连接数超过服务端 keep-alive 上限后反而会出现大量 TIME_WAIT。先压 8 个线程看延迟分布再决定要不要加到 32。5. 编译与运行期常见问题排查五个血泪坑5.1 头文件找不到include 路径少了一层现象编译报fatal error: cpr/cpr.h: No such file or directory。原因通常不是没下载源码而是只把third_party/cpr加进了 include 路径而实际头文件在third_party/cpr/include/cpr/cpr.h少了一层include。另一个常见原因是主工程手动写了target_include_directories但漏了cpr子目录。解决方式很简单用 target 链接别手写路径。add_subdirectory(third_party/cpr) target_link_libraries(cpr_demo PRIVATE cpr) # 不要写成 target_include_directories(cpr_demo PRIVATE third_party/cpr)如果必须手动加写${CMAKE_SOURCE_DIR}/third_party/cpr/include不是${CMAKE_SOURCE_DIR}/third_party/cpr。编之前用find third_party/cpr -name cpr.h确认文件位置比反复改 CMake 快。5.2 链接报 curl_easy_init 未定义传递依赖断了现象编译通过链接报undefined reference to curl_easy_init或undefined reference to SSL_CTX_new。原因有两个一是只链接了cpr静态库没有把 libcurl 放进链接行二是系统里存在多个 libcurlCMake 找到了旧版本符号对不上。先看完整链接命令cmake --build build --verbose如果链接行里只有libcpr.a没有-lcurl用 target 方式链接 cpr让 CMake 带出传递依赖。如果已经有-lcurl还报错检查curl-config --version和 CMake 找到的路径是否一致。兜底方案是显式找 CURL 并链接find_package(CURL REQUIRED) target_link_libraries(cpr_demo PRIVATE cpr CURL::libcurl)Windows 下还要注意 debug/release 不能混debug 版 cpr 链 release 版 libcurl会在运行期崩在堆上。5.3 SSL 证书校验失败CA 路径和自签证书是两回事现象请求 HTTPS 地址返回error: SSL peer certificate or SSH remote key was not OK或者problem with the SSL CA cert。原因通常是运行环境缺少 CA 证书包比如精简容器里没装ca-certificates或者CURL_CA_BUNDLE环境变量指向了一个不存在的文件再或者服务端用的是自签证书。先确认系统证书路径ls -l /etc/ssl/certs/ca-certificates.crt如果文件不存在装 CA 证书包如果存在还报错检查CURL_CA_BUNDLE有没有被设错。本地调试自签服务时可以临时cpr::VerifySsl{false}但不要把这个选项带进生产配置。更稳妥的做法是把自签 CA 加到系统信任链而不是关校验。5.4 POST 中文乱码Payload 和 Body 用混了现象服务端收到name%E4%B8%AD%E6%96%87但解码后乱码或者 JSON 解析直接失败。原因有三个常见组合表单请求用了Body却没设Content-Type: application/x-www-form-urlencoded用了Payload又手动 URL 编码了一次造成双重编码JSON body 里的中文源文件不是 UTF-8。解决方式是按内容类型选 API表单用PayloadJSON 用BodyContent-Type: application/json不要在Payload外面再套一层编码函数。// 正确表单交给 Payload 编码 cpr::Post(cpr::Url{url}, cpr::Payload{{name, 中文}}); // 正确JSON 自己保证 body 合法Header 显式声明 cpr::Post(cpr::Url{url}, cpr::Header{{Content-Type, application/json}}, cpr::Body{R({name:中文})});排查时打印 body 的十六进制前几十字节看%是不是出现了两次比看日志字符串准。5.5 多线程偶发崩溃Session 被共享了现象压力一上来就偶发segmentation fault或者 A 请求收到 B 的响应。原因几乎都是多个线程共用一个cpr::Session。Session 内部的 easy handle 有连接状态和缓冲区libcurl 明确要求同一个 handle 不能并发使用。解决方式是每个线程独立构造 Session线程内复用需要共享的只是 URL、Header 这些配置值不是 Session 对象本身。// 错误全局 Session 被多个线程同时 Get // cpr::Session g_session; // 正确线程函数内部构造 void worker() { cpr::Session session; session.SetUrl(cpr::Url{url}); // ... }如果确实需要跨线程传递配置封一个struct RequestConfig每个线程用自己的 Session 去Set不要复制 Session。这个坑一次就能记住代价通常是半夜被报警叫起来。6. 进阶用 cpr 1.3.0 做下载落盘与校验的验证脚本大文件下载不要用r.text接整包进内存几百兆就能把进程打爆。cpr 1.3.0 可以用WriteCallback流式写文件边收边落盘#include cpr/cpr.h #include fstream #include iostream int main() { const std::string url https://example.com/files/demo.bin; const std::string part demo.bin.part; std::ofstream out(part, std::ios::binary); if (!out) { std::cerr open output failed\n; return 1; } cpr::Response r cpr::Get( cpr::Url{url}, cpr::WriteCallback{ [](std::string data, intptr_t userdata) { auto* os reinterpret_caststd::ofstream*(userdata); os-write(data.data(), static_caststd::streamsize(data.size())); return os-good(); }, reinterpret_castintptr_t(out) }, cpr::Timeout{30000}, cpr::ConnectTimeout{3000} ); out.close(); if (r.error.code ! cpr::ErrorCode::OK || r.status_code ! 200) { std::cerr download failed: r.error.message \n; return 2; } std::cout content-length r.header[Content-Length] \n; return 0; }WriteCallback每收到一块数据就调一次userdata用来传文件流指针。回调返回false会中断传输所以写完要检查os-good()。下载到.part临时文件成功后再改名避免半截文件被下游当成完整文件读走stat -c %s demo.bin.part # 和响应头里的 Content-Length 对比一致再改名 mv demo.bin.part demo.bin校验这一步别省。Content-Length对不上说明连接中途断了或者服务端返回了错误页如果服务端还给了ETag把它记进日志下次请求带If-None-Match可以省流量。重试只对连接超时和 5xx 做4xx 重试没有意义重试前把.part删掉别在旧文件上追加。我现在的习惯是任何 cpr 1.3.0 的下载逻辑先跑一遍小文件确认回调路径再换大文件看内存曲线每次接入新工程先把add_subdirectory、每线程一个 Session、超时单位这三件事写进模板再谈业务。希望帮到你。本文还有配套的精品资源点击获取
企业数字化 ERP 产品动态
相关推荐
Univer SDK:面向B端的富文档协同引擎与可编辑表格实现 1. 项目概述:Univer 是什么,它解决的不是“又一个表格工具”问题Univer 这个名字乍一听容易让人联想到“universe”(宇宙),但实际它是一个开源的、面向开发者的富文档协同引擎。它不是一款直接面向终端用户销售的 SaaS… · 2026/11/5 7:52:22
Agent Sandbox 安全隔离:Firecracker microVM 架构与实战 1. 从一次线上事故说起:为什么 Agent 需要独立沙箱去年年底我们团队在做一个代码执行类 Agent 产品,用户输入一段 Python 脚本,Agent 在云端跑完把结果返回。上线第三天就出了事:一个用户提交了while True: os.fork(),… · 2026/11/5 3:24:16
Nginx实战:3种跨域解决方案与性能优化 1. 为什么前端开发总会遇到跨域问题?第一次接手前后端分离项目时,我在本地调试时遇到了经典的跨域报错:"No Access-Control-Allow-Origin header is present on the requested resource"。这个看似简单的错误背后,其实是… · 2026/11/2 9:33:36
基于Hadoop+Spark的民宿智能推荐系统设计与实现 1. 项目概述:大数据时代的民宿智能推荐这个毕业设计项目融合了当前大数据领域最主流的技术栈,构建了一个完整的民宿推荐系统解决方案。作为一名长期从事大数据系统开发的工程师,我认为这个选题非常贴合实际应用场景——随着旅游业的复苏和共享… · 2026/11/5 14:59:25
ADS122U04IPWR+STM32F427ZI工业级温度测量信号链设计 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 14:10:41
UART接口24位ADC搭配RS485,解决远距离温度监控难题 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 14:10:41
UART接口24位ADC搭配PIC18F46K22的RTD与热电偶测温实践 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 14:10:41
GD32E10x官方例程入门:从GPIO点灯到串口调试 简介:这份GD32E10x系列官方例程面向嵌入式硬件与单片机开发者,基于ARM Cortex-M3内核,汇集兆易创新GD32E10x的示例代码,适合工业控制、消费电子、通信设备等场景的学习、验证与二次开发。压缩包共935个文件,约11.16MB&… · 2026/11/5 13:52:29
基于Django的运维平台实战:资产、发布、巡检、告警一体化 简介:这份资源是一套基于Django框架开发的运维平台源码,面向具备Python基础、希望了解Web运维系统实现思路的开发者与运维人员,可用于学习主机管理、服务监控、日志查看、任务调度、权限控制、资源统计、脚本执行与故障告警等常见运维模块的落… · 2026/11/5 13:49:27
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:27:59
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:28:03
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:28:07
多智能体协作系统架构设计与实践优化 1. 多智能体协作系统的时代背景2017年Transformer架构的诞生彻底改变了人工智能的发展轨迹。当行业还沉浸在单一大模型带来的性能突破时,Anthropic的研究团队已经将目光投向了更前沿的领域——如何让多个智能体通过协作产生超越单体能力的系统智能。这就像交响乐团中… · 2026/11/5 0:00:39
大模型系统性入门实战指南:从原理到部署微调的全链路路线 提到大模型的系统性入门,我先说个结论:这事真不难,难的是资料太散、路线太多,今天这个框架明天那个工具,新人很容易在“收藏夹吃灰”和“教程看到一半放弃”之间反复横跳。市面上关于大模型的内容少说有几十万篇&#… · 2026/11/5 0:00:39
鸿蒙文件系统沙箱机制解析与开发实践 1. 鸿蒙文件系统沙箱机制深度解析作为一名从Android转向鸿蒙开发的工程师,我深刻体会到文件系统访问是迁移过程中最先遇到的"拦路虎"。在Android上运行良好的文件读写代码,在鸿蒙真机环境却频频出现文件写入后神秘消失或直接抛出权限拒绝错误的… · 2026/11/5 0:00:39
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:27:59
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:28:03
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:28:07