news 2026/10/9 20:31:11

C++ cpr网络库在MinGW-w64 gcc Windows下的编译配置与TaoToken接入实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C++ cpr网络库在MinGW-w64 gcc Windows下的编译配置与TaoToken接入实践

1. Windows 下用 MinGW-w64 gcc 编译 cpr 网络库到底难在哪

如果你在 Windows 上写 C++,又想发 HTTP 请求,cpr 是个很顺手的选择——它的接口几乎照搬 Python 的 requests,cpr::Get、cpr::Post一行就能发请求。但真正动手编译时,很多人会卡在同一个地方:MinGW-w64 gcc 环境下,cpr 依赖 libcurl 和 OpenSSL,而这两个库在 Windows 上并不像 Linux 那样apt install就完事。CMake 找不到头文件、链接阶段报undefined reference to curl_easy_init、OpenSSL 路径识别失败,几乎是必经之路。

这篇就聚焦 Windows 平台用 MinGW-w64 gcc 编译 cpr 的完整流程,把依赖库链接和 CMake 配置这两块讲透。我会给出可以直接复制的 CMakeLists 配置、编译命令,以及一段验证 HTTP 请求的测试代码。最后演示怎么把 API 端点改到 TaoToken 统一 Key 通道,完成一次真实的连通性验证——这样你编译出来的 cpr 不只是能跑 demo,而是能直接对接大模型接口。

适合谁看:在 Windows 上用 MinGW-w64 写 C++、需要 HTTP 客户端、又不想被 Visual Studio 绑定的人。如果你用的是 MSVC,流程会简单一些,但本文的 CMake 配置思路同样有参考价值。

先说清楚整体链路:cpr 本身是个薄封装,底层调用 libcurl;libcurl 要支持 HTTPS,就得链接 OpenSSL(或 Schannel)。所以编译 cpr 本质上是三件事——准备好 curl 和 OpenSSL 的库文件、让 CMake 找到它们、把 cpr 编成静态库或动态库供你的项目链接。MinGW-w64 的坑主要出在第二步和第三步:路径写法、库文件名、链接顺序。

我试过直接拿官网的源码包丢进 CMake GUI 点 Configure,结果 OPENSSL 找不到、CURL 找不到,报错刷了一屏。后来把依赖一个个手动指定才通。下面按顺序来,你跟着做基本能一次过。

2. 编译前的依赖准备与 TaoToken 接入前置

在动手编译之前,先把需要的东西备齐。cpr 的源码里有个opt目录,专门用来放第三方依赖,这是官方推荐的放置方式,能省掉很多路径配置的麻烦。

你需要准备这几样:

cpr 库本体,从 GitHub 仓库下载源码压缩包,解压后得到cpr-master目录。libcurl 的 Windows 预编译包,注意要选和 MinGW-w64 匹配的版本,通常用 MinGW 编译的 curl 包,里面会有include和lib两个目录。OpenSSL 的 Windows 预编译包,同样要 MinGW 版本,或者用 MSYS2 里pacman -S mingw-w64-x86_64-openssl装出来的也行。mongoose 这个库 cpr 的测试会用到,从 GitHub 下载后解压。

把这些依赖解压后,按 cpr 的约定放进cpr-master/opt下对应的子目录。curl 放进opt/libcurl,OpenSSL 放进opt/openssl,mongoose 放进opt/mongoose。目录结构大致是这样:

cpr-master/ ├── opt/ │ ├── libcurl/ │ │ ├── include/ │ │ └── lib/ │ ├── openssl/ │ │ ├── include/ │ │ └── lib/ │ └── mongoose/ ├── include/ ├── cpr/ └── CMakeLists.txt

放好之后,还要确认你的 MinGW-w64 工具链在 PATH 里。打开命令行敲gcc --version和cmake --version,能输出版本号就说明环境没问题。我用的 gcc 是 8.1.0 x64 版本,cmake 是 3.x,版本不用太新,够用就行。

接下来是 TaoToken 的前置准备。TaoToken 是一个统一的大模型 API 接入通道,你注册后拿到一个 API Key,就能通过同一个端点调用不同厂商的模型。对本文来说,它的作用是给我们一个真实的 HTTPS 接口来验证 cpr 编译结果——毕竟编译完总得发个请求确认能用。

你需要做两件事:一是到官网 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 注册账号;二是进控制台 https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 创建一个 API Key。这个 Key 后面会写进测试代码里。API 的基础地址是 https://taotoken.net/api,注意这个地址不带 UTM 参数,是纯接口地址。

提示:API Key 属于敏感信息,测试代码里建议用环境变量读取,别直接硬编码提交到仓库。本文为了演示方便会写在代码里,你实际用时记得改掉。

依赖和 Key 都备齐后,就可以进入 CMake 配置环节了。这一步是整个流程里最容易出问题的,下一节详细说。

3. 可复制的 CMakeLists 配置与编译命令

这一节是核心。cpr 自带的 CMakeLists 在 MinGW-w64 下经常找不到依赖,与其在 GUI 里一项项改,不如直接写一个自己的 CMakeLists,把路径和链接关系写死,可控性最高。

先看一个最小可用的 CMakeLists.txt,放在你的项目根目录,假设 cpr 源码在third_party/cpr-master:

cmake_minimum_required(VERSION 3.10) project(cpr_demo CXX) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) # 依赖路径,按你的实际解压位置改 set(CURL_ROOT "${CMAKE_SOURCE_DIR}/third_party/cpr-master/opt/libcurl") set(OPENSSL_ROOT "${CMAKE_SOURCE_DIR}/third_party/cpr-master/opt/openssl") # 头文件目录 include_directories( ${CURL_ROOT}/include ${OPENSSL_ROOT}/include ${CMAKE_SOURCE_DIR}/third_party/cpr-master/include ) # 库文件目录 link_directories( ${CURL_ROOT}/lib ${OPENSSL_ROOT}/lib ) # 把 cpr 源码直接编进来,避免单独编译安装 file(GLOB_RECURSE CPR_SOURCES ${CMAKE_SOURCE_DIR}/third_party/cpr-master/cpr/*.cpp ) add_library(cpr STATIC ${CPR_SOURCES}) target_include_directories(cpr PUBLIC ${CMAKE_SOURCE_DIR}/third_party/cpr-master/include ${CURL_ROOT}/include ${OPENSSL_ROOT}/include ) # 链接 curl 和 openssl,注意顺序 target_link_libraries(cpr PUBLIC curl ssl crypto ws2_32 crypt32 wldap32 normaliz ) add_executable(cpr_demo main.cpp) target_link_libraries(cpr_demo PRIVATE cpr)

几个关键点解释一下。ws2_32、crypt32、wldap32是 Windows 下 curl 依赖的系统库,漏掉会报一堆undefined reference。normaliz是 curl 在 Windows 上可能用到的库,有些版本需要。链接顺序上,curl 要放在 ssl 和 crypto 前面,否则静态链接时符号解析会失败。

如果你不想把 cpr 源码编进项目,也可以先单独编译 cpr 生成静态库。用 CMake 命令行方式:

cd cpr-master mkdir build && cd build cmake -G "MinGW Makefiles" \ -DCMAKE_BUILD_TYPE=Release \ -DCURL_INCLUDE_DIR=../opt/libcurl/include \ -DCURL_LIBRARY=../opt/libcurl/lib/libcurl.a \ -DOPENSSL_INCLUDE_DIR=../opt/openssl/include \ -DOPENSSL_SSL_LIBRARY=../opt/openssl/lib/libssl.a \ -DOPENSSL_CRYPTO_LIBRARY=../opt/openssl/lib/libcrypto.a \ -DCPR_BUILD_TESTS=OFF \ .. mingw32-make -j4

注意-DCPR_BUILD_TESTS=OFF,cpr 的测试依赖 mongoose,关掉能省不少事。-G "MinGW Makefiles"指定生成器,别用默认的,否则可能生成 Visual Studio 工程。

编译过程中如果报Could NOT find OpenSSL,就是路径没指对,检查OPENSSL_INCLUDE_DIR是否指向了包含openssl/ssl.h的那层目录。如果报undefined reference to __imp_curl_easy_init,说明链接的是动态库的导入库但没找到对应的 dll,换成静态库.a文件即可。

编译完成后,build/lib下会有libcpr.a,把它和 curl、openssl 的静态库一起链接到你的项目就行。下面给一个完整的链接命令示例:

g++ main.cpp -o demo.exe \ -I./cpr-master/include \ -I./cpr-master/opt/libcurl/include \ -I./cpr-master/opt/openssl/include \ -L./cpr-master/build/lib \ -L./cpr-master/opt/libcurl/lib \ -L./cpr-master/opt/openssl/lib \ -lcpr -lcurl -lssl -lcrypto \ -lws2_32 -lcrypt32 -lwldap32 -lnormaliz \ -static-libgcc -static-libstdc++

-static-libgcc -static-libstdc++是为了避免运行时缺 GCC 的 dll,发布时更省心。

4. 验证 HTTP 请求与 TaoToken 连通性测试

编译通过只是第一步,得发个真实请求确认。先写一个最简单的测试,请求一个公开接口,确认 cpr 基本功能正常:

#include <cpr/cpr.h> #include <iostream> int main() { auto r = cpr::Get(cpr::Url{"https://httpbin.org/get"}); std::cout << "status: " << r.status_code << std::endl; std::cout << "body: " << r.text.substr(0, 200) << std::endl; return 0; }

编译运行后如果输出status: 200,说明 cpr 和 HTTPS 都正常。如果报 SSL 相关错误,多半是 OpenSSL 没链接对,或者证书路径有问题。

接下来把端点换成 TaoToken,验证统一 Key 通道。TaoToken 的接口兼容 OpenAI 格式,所以用 cpr 发一个 chat completions 请求即可:

#include <cpr/cpr.h> #include <nlohmann/json.hpp> #include <iostream> using json = nlohmann::json; int main() { const char* api_key = std::getenv("TAOTOKEN_API_KEY"); if (!api_key) { std::cerr << "请设置 TAOTOKEN_API_KEY 环境变量" << std::endl; return 1; } json payload = { {"model", "gpt-4o-mini"}, {"messages", { {{"role", "user"}, {"content", "用一句话说明什么是HTTP"}} }}, {"max_tokens", 100} }; auto r = cpr::Post( cpr::Url{"https://taotoken.net/api/v1/chat/completions"}, cpr::Header{ {"Content-Type", "application/json"}, {"Authorization", std::string("Bearer ") + api_key} }, cpr::Body{payload.dump()}, cpr::Timeout{30000} ); std::cout << "status: " << r.status_code << std::endl; if (r.status_code == 200) { auto resp = json::parse(r.text); std::cout << resp["choices"][0]["message"]["content"] << std::endl; } else { std::cout << "error: " << r.text << std::endl; } return 0; }

这里用到了 nlohmann/json 来构造和解析 JSON,它是个 header-only 库,下载一个json.hpp放进 include 目录就行。编译时加上-I./include。

运行前设置环境变量:

set TAOTOKEN_API_KEY=你的Key demo.exe

如果返回 200 并打印出模型回复,说明整条链路通了:cpr 编译正确、HTTPS 正常、TaoToken 的 Key 通道可用。如果返回 401,检查 Key 是否正确、有没有多余空格。如果返回 404,检查 URL 路径是不是/api/v1/chat/completions。

注意:TaoToken 的模型 ID 要填它支持的名称,具体可以在模型对话页面 https://taotoken.net/models?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 查看可用列表。填错模型名会返回 400。

5. 编译与请求常见报错排查

这一节把实际会遇到的报错列出来,对照着查。

报错一:Could NOT find CURL (missing: CURL_LIBRARY CURL_INCLUDE_DIR)

CMake 没找到 curl。解决方法是显式指定路径,在 cmake 命令里加-DCURL_INCLUDE_DIR=.../include -DCURL_LIBRARY=.../lib/libcurl.a。注意CURL_LIBRARY要指向具体的库文件,不是目录。

报错二:undefined reference to 'curl_easy_init'

链接阶段找不到 curl 符号。原因通常是链接顺序不对,或者链接的是导入库而非静态库。把-lcurl放在-lssl -lcrypto前面,并确认用的是.a静态库。如果用的是.dll.a导入库,运行时还需要对应的 dll 在 PATH 里。

报错三:local proxy failed或连接超时

cpr 默认会读取系统代理设置。如果你的环境有代理配置但代理不可用,请求会失败。可以在代码里显式禁用代理:

auto r = cpr::Get( cpr::Url{"https://taotoken.net/api/v1/models"}, cpr::Proxies{{"http", ""}, {"https", ""}} );

或者在系统环境变量里清掉HTTP_PROXY、HTTPS_PROXY。

报错四:error: 'reading choices'或 JSON 解析失败

请求返回了非 200,但代码直接去解析choices字段。先判断r.status_code == 200再解析,否则打印r.text看服务端返回的错误信息。常见的是 401(Key 无效)或 400(请求体格式错误)。

报错五:OAuth 或认证失败

如果返回 401 且提示认证问题,检查Authorization头格式是不是Bearer <key>,中间有一个空格。cpr 的 Header 是std::map,重复的 key 会被覆盖,别写错。

报错六:cannot find -lnormaliz

有些 curl 版本不需要 normaliz。如果链接报这个错,把-lnormaliz去掉再试。反之如果报其他 Windows 库缺失,按报错提示补上对应的-l参数。

报错七:CMake 生成的是 Visual Studio 工程

没指定-G "MinGW Makefiles",CMake 默认用了 VS 生成器。重新执行 cmake 时加上生成器参数,并清空 build 目录。

排查时有个通用技巧:把CMAKE_VERBOSE_MAKEFILE设为 ON,能看到完整的编译和链接命令,哪一步出错一目了然。

cmake -G "MinGW Makefiles" -DCMAKE_VERBOSE_MAKEFILE=ON ..

6. 把 cpr 接入长期编码工作流的建议

编译通了、请求也验证过了,接下来是怎么把它用顺。如果你打算在项目里长期用 cpr 对接大模型接口,有几个实践建议。

第一,把 API Key 和 Base URL 抽成配置。别硬编码在源码里,用环境变量或配置文件读取。TaoToken 的 Base URL 是https://taotoken.net/api,所有模型共用这一个端点,换模型只改model字段,这对写多模型对比的代码特别方便。

第二,封装一个薄客户端。cpr 的接口已经很简洁,但每次手写 Header 和 JSON 还是啰嗦。可以封一个ChatClient类,构造时传入 Key,提供chat(prompt)方法,内部处理请求和错误。这样业务代码里只有一行调用。

第三,注意超时和重试。大模型接口响应可能较慢,cpr::Timeout设 30 秒比较稳妥。网络抖动时加重试逻辑,cpr 本身不提供重试,需要自己包一层循环。

第四,静态链接发布。用-static-libgcc -static-libstdc++加上静态链接 curl 和 openssl,生成的 exe 不依赖额外 dll,拷到别的机器直接能跑。代价是体积大一些,但省心。

如果你需要管理多个项目的 Key,或者想用 Coding Plan 的方式统一管理调用额度,可以到 https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 看看。对于需要频繁调用模型的编码场景,统一通道比每个项目单独配 Key 要清爽得多。

最后说个实际踩过的坑:MinGW-w64 的版本和 curl 预编译包的版本要匹配,32 位对 32 位,64 位对 64 位。混用会在链接时报架构不匹配的错误,而且报错信息不明显,容易查半天。编译前先确认gcc -dumpmachine的输出,和 curl 包的架构对上。

整套流程走下来,从依赖准备到编译再到请求验证,顺利的话半小时内能搞定。卡住的地方基本都在 CMake 找依赖和链接顺序上,对照第 5 节的报错表查,大部分问题能定位。编译好的 cpr 静态库可以复用,下次新项目直接链接就行,不用重新编。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/9 20:23:58

视频微表情识别中自适应关键帧算法:选帧、光流与序列模型实践

简介&#xff1a;面向计算机视觉与情感计算研究者的微表情识别项目&#xff0c;基于自适应关键帧思想处理视频中的瞬时面部变化&#xff0c;解决微表情持续时间短、特征微弱导致识别困难的问题。资源围绕视频预处理、关键帧检测、LBP/DoG特征提取、SVM/CNN分类及模型优化等环节…

作者头像 李华
网站建设 2026/10/9 20:22:23

RabbitMQ入门实战:从安装配置到消息队列原理与可靠投递

1. 为什么要用RabbitMQ&#xff1a;消息队列到底在解决什么问题接触RabbitMQ之前&#xff0c;我一直觉得它是个很神秘的东西。"消息队列"这四个字听起来就像某种高深莫测的中间件&#xff0c;好像只有大厂核心系统才配用它。直到我自己在项目里真正把它跑起来之后&am…

作者头像 李华
网站建设 2026/10/9 20:21:29

OpenClaw 安装包实测:把 DeepSeek V4 接入 TaoToken 统一通道的完整配置

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/9 20:19:05

Python批量合并Excel实战:纵向追加、横向拼接与多Sheet处理

1. 为什么我最终放弃了手工复制粘贴如果你手头经常要处理多个Excel文件&#xff0c;比如每周从不同渠道导出的销售数据、每月各部门提交的报表、或者从系统里分批下载的流水记录&#xff0c;那你一定经历过这种场景&#xff1a;打开十几个文件&#xff0c;挨个复制数据&#xf…

作者头像 李华