简介本资源为在 Windows 10 环境下使用 CMake 3.22 与 Visual Studio 2019 编译完成的 curl 64 位库版本 7.84.0支持 SSL面向需要在 Windows 平台进行 C/C 网络开发、又不愿自行折腾编译环境的开发者。包内已整理为 lib 与 include 的标准目录结构可直接接入 VS 工程使用省去从源码编译与依赖配置的繁琐过程。资源共 19 个文件以 11 个 h 头文件、2 个 am 构建脚本、1 个 lib 导入库、1 个 dll 动态库、1 个 exp 导出文件及 1 个 exe 可执行程序为主另附 README 说明与 gitignore压缩包约 354KB体积轻巧便于分发。其中内置的 curl.exe 可在命令行直接发起 HTTP 请求方便调试接口与验证网络连通性。目前已有 776 人学习下载适合希望快速获得可用 curl 库、专注业务逻辑而非环境搭建的开发者参考使用。1. 为什么 2024 年还在折腾 curl 7.84.0 的 Win10 64 位静态库如果你在 Win10 上做 C 桌面端、嵌入式上位机或者工业网关的二次开发大概率绕不开 libcurl。它把 HTTP、HTTPS、FTP、SMTP 这些协议封装成一套稳定的 C API省得自己拿 socket 去拼报文。但真正让人头疼的不是调用而是编译官方不提供 Windows 下开箱即用的 64 位静态库网上流传的预编译包要么版本对不上要么缺 SSL 后端要么是 32 位的。标题里这个「win10 下用 vs2019 编译好的 curl 64 位库 版本 7.84.0」说的就是这件事——在 Win10 上用 VS2019 工具链把 curl 7.84.0 编成 x64 可用的库直接丢进自己的工程里链接。7.84.0 这个版本号不是随便挑的。它是 2022 年 6 月发布的属于 7.x 后期比较稳的一版API 已经定型没有 8.x 那些破坏性改动很多老项目锁死在这个版本上。而 VS2019 的 MSVC 工具链v142在 Win10 上兼容性最好生成的静态库能直接给同版本或更高版本的 VS 用。这篇文章面向的是需要自己掌控依赖、不想被第三方包管理器绑架的开发者从环境准备一路讲到链接排错。2. 编译前必须想清楚的三个选型问题2.1 静态库还是动态库链接方式决定部署成本curl 在 Windows 下可以编成静态库.lib或动态库.dll .lib 导入库。静态库的好处是最终 exe 不依赖外部 curl.dll拷贝到别的机器上不会因为缺 dll 而启动失败这对工业现场那种「拷过去就得跑」的场景很关键。代价是 exe 体积会大几百 KB而且如果多个模块各自静态链接了 curl可能出现符号重复或全局状态不一致。动态库则相反部署时要带上 libcurl.dll但多个模块共享同一份运行时内存和句柄更省。我一般给客户做交付版选静态内部调试工具选动态。注意静态库还要处理运行时库的匹配问题curl 默认用 /MD多线程 DLL 运行时如果你的工程用 /MT链接时会报LNK2038运行时库不匹配。这个后面避坑章节会细说。2.2 SSL 后端选谁Schannel 还是 OpenSSLcurl 本身不实现 TLS它要挂一个 SSL 后端。Windows 上常见两个选择Schannel 和 OpenSSL。Schannel 是 Windows 自带的 TLS 实现不需要额外编译 OpenSSL直接用系统证书store体积小、证书管理省心。缺点是它跟系统绑定老版本 Win10 上 TLS 1.3 支持要看系统补丁而且 curl 对 Schannel 的某些高级选项支持不如 OpenSSL 全。OpenSSL 是跨平台的行为可预期支持 TLS 1.3 和各种 cipher 配置但你要先自己把 OpenSSL 编成 64 位库多一层依赖。如果你只是访问普通 HTTPS 接口Schannel 足够如果你要对接自签证书、双向认证或者需要精确控制 TLS 版本OpenSSL 更稳。标题里没指定 SSL 后端我下面以 Schannel 为主线讲因为它省掉编译 OpenSSL 这一步复现门槛最低。2.3 zlib 和 brotli要不要一起编进去curl 支持 gzip 和 brotli 压缩传输。如果服务端返回Content-Encoding: gzip没有 zlib 的 curl 不会自动解压你拿到的就是压缩后的二进制。很多 REST 接口默认开 gzip所以建议把 zlib 一起编进去。brotli 用得少一些但现代 CDN 有时会返回 br 编码编上更保险。zlib 的编译比 OpenSSL 简单得多源码包小用 VS2019 的 nmake 就能出静态库。brotli 稍微麻烦需要 CMake。如果项目对体积敏感且确定服务端不用 br可以只编 zlib。我的习惯是 zlib 必带brotli 看项目。3. 用 VS2019 从源码编出 x64 静态库的完整步骤3.1 准备源码和目录结构先建一个干净的工作目录避免路径里有中文和空格这是血泪经验——nmake 和 perl 脚本对空格路径的处理经常翻车。推荐结构D:\dev\curl-build\ curl-7.84.0\ # curl 源码 zlib-1.2.12\ # zlib 源码 build\ # 编译输出curl 7.84.0 源码包从官方渠道获取解压后根目录下有winbuild文件夹里面就是给 Windows 用的 nmake 构建脚本。zlib 用 1.2.12 或 1.2.13 都行跟 curl 7.84.0 兼容。打开「x64 Native Tools Command Prompt for VS 2019」注意必须是 x64 那个不是普通的 Developer Command Prompt否则编出来是 32 位。这个命令行窗口已经帮你设好了cl.exe、nmake.exe的路径和环境变量。3.2 先编 zlib 的 64 位静态库进入 zlib 源码目录执行nmake -f win32/Makefile.msc clean nmake -f win32/Makefile.msc zlib.lib第一行清掉旧对象第二行生成zlib.lib。默认生成的是 release 版如果你要 debug 版加CFLAGS-nologo -MD -Z7之类的参数但一般 curl 链接 release zlib 就够。编完后确认zlib.lib和zconf.h、zlib.h都在。把 zlib 根目录路径记下来比如D:\dev\curl-build\zlib-1.2.12下一步传给 curl 的构建脚本。提示如果 nmake 报fatal error U1077: rc说明资源编译器没在 PATH 里回到 x64 Native Tools 命令行重开一次即可。3.3 用 winbuild 脚本编 curl进入curl-7.84.0\winbuild目录核心命令是nmake /f Makefile.vc modestatic VC16 MACHINEx64 ^ WITH_ZLIBstatic ZLIB_PATHD:\dev\curl-build\zlib-1.2.12 ^ WITH_SSLschannel DEBUGno ENABLE_IDNno逐个参数说明modestatic生成静态库 libcurl_a.lib不是 dll。VC16VS2019 的编译器主版本号是 16VS2017 是 15VS2022 是 17写错会找不到工具集。MACHINEx64目标 64 位。WITH_ZLIBstatic和ZLIB_PATH...告诉 curl 用静态 zlib并给出路径。WITH_SSLschannel用 Windows 自带 TLS不需要 OpenSSL 路径。DEBUGnorelease 版要 debug 改成DEBUGyes。ENABLE_IDNno国际化域名支持一般用不上关掉少个依赖。执行后脚本会先编译再链接输出在builds\libcurl-vc16-x64-release-static-zlib-schannel-ipv6-sspi这样的目录下。里面lib子目录有libcurl_a.libinclude\curl下是头文件。3.4 验证库文件架构和符号编完别急着往工程里塞先确认它是 64 位。用 VS 自带的dumpbindumpbin /headers libcurl_a.lib | findstr machine输出里应该看到8664 (x64)如果是14C (x86)说明命令行开错了。再看导出符号dumpbin /symbols libcurl_a.lib | findstr curl_easy_init能搜到_curl_easy_init就说明符号在。静态库的符号前面通常带下划线这是 MSVC 的命名约定链接时不用管。4. 把编好的 curl 接进 VS2019 工程配置与第一个请求4.1 工程属性里的四个关键设置新建或打开你的 VS2019 C 工程右键项目 → 属性配置选Releasex64然后C/C → 常规 → 附加包含目录加上...\include也就是 curl 头文件所在目录。链接器 → 常规 → 附加库目录加上...\liblibcurl_a.lib 所在目录。链接器 → 输入 → 附加依赖项填libcurl_a.lib;ws2_32.lib;crypt32.lib;wldap32.lib;normaliz.lib。后面几个是 curl 在 Windows 下依赖的系统库缺一个都会报一堆LNK2019。C/C → 代码生成 → 运行时库必须和 curl 编译时一致。winbuild 默认用/MD所以这里选多线程 DLL (/MD)。如果你工程是/MT要么改工程要么重新编 curl 时指定/MT。4.2 一个最小可运行的 HTTPS 请求下面这段代码发起一个 GET 请求把响应写到内存里#include curl/curl.h #include string #include iostream // 回调把收到的数据块追加到 string static size_t WriteCallback(void* contents, size_t size, size_t nmemb, void* userp) { size_t total size * nmemb; static_caststd::string*(userp)-append(static_castchar*(contents), total); return total; } int main() { curl_global_init(CURL_GLOBAL_DEFAULT); // 进程级初始化必须最先调用 CURL* curl curl_easy_init(); if (!curl) { std::cerr init failed\n; return 1; } std::string response; curl_easy_setopt(curl, CURLOPT_URL, https://example.com); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, response); curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10L); // 总超时 10 秒 curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); // 跟随 301/302 CURLcode res curl_easy_perform(curl); if (res ! CURLE_OK) { std::cerr curl error: curl_easy_strerror(res) \n; } else { long code 0; curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, code); std::cout HTTP code , response.size() bytes\n; } curl_easy_cleanup(curl); curl_global_cleanup(); return 0; }逻辑说明curl_global_init只需在程序启动时调一次多线程环境下要在起线程之前调。CURLOPT_WRITEFUNCTION注册的回调会被 curl 分块调用所以用 string 追加而不是覆盖。CURLOPT_TIMEOUT是总耗时上限防止服务端不响应时卡死。CURLINFO_RESPONSE_CODE拿 HTTP 状态码比只看CURLcode更细。参数上CURLOPT_TIMEOUT单位是秒长轮询场景要调大CURLOPT_CONNECTTIMEOUT单独控制连接阶段超时可以设短一点比如 5 秒让连接失败快速返回。4.3 用 curl -v 对照排查请求行为命令行 curl 的-v输出是排查问题的利器。当代码里请求失败时先用命令行发同样的 URLcurl -v https://example.com -o nul看它打印的* Trying ...、* Connected to ...、 GET / HTTP/1.1、 HTTP/1.1 200这些行能快速区分是 DNS、TCP、TLS 还是应用层的问题。如果命令行能通而代码不通多半是代码里少了某个 option 或者链接的库版本不对。5. 编译和链接 curl 时最容易踩的五个坑5.1 LNK2038 运行时库不匹配现象链接时报LNK2038: 检测到RuntimeLibrary的不匹配项: 值MD_DynamicRelease不匹配值MT_StaticRelease。原因curl 用/MD编的你的工程用/MT两者对 CRT 的假设不同不能混链。解决把工程属性里「代码生成 → 运行时库」改成/MD。如果工程必须用/MT就回到 winbuild 命令加RTLIBCFGstatic重新编 curl让它也用静态 CRT。5.2 一堆 LNK2019 找不到符号现象LNK2019: 无法解析的外部符号 __imp_curl_easy_init。原因要么没把libcurl_a.lib加进附加依赖项要么加的是 dll 的导入库而不是静态库要么系统库ws2_32.lib等没加。解决确认附加依赖项里是libcurl_a.lib静态而不是libcurl.lib导入库并补齐ws2_32.lib;crypt32.lib;wldap32.lib;normaliz.lib。__imp_前缀说明链接器在找导入库说明你链错了库类型。5.3 HTTPS 请求返回 CURLE_PEER_FAILED_VERIFICATION现象代码里请求 https 返回错误码 60提示证书验证失败。原因Schannel 后端用系统证书store如果目标站点证书链不全、或者系统时间不对、或者根证书缺失就会失败。解决先确认系统时间和根证书正常。调试阶段可以临时用CURLOPT_SSL_VERIFYPEER设 0 绕过但生产环境绝不能关。正确做法是把站点证书链补全或者把自签根证书导入系统「受信任的根证书颁发机构」。5.4 编译时 nmake 报找不到 zlib.h现象fatal error C1083: 无法打开包括文件: zlib.h。原因ZLIB_PATH指错了或者 zlib 还没编。解决确认ZLIB_PATH指向 zlib 源码根目录里面有zlib.h的那层不是win32子目录。并且先完成 zlib 的 nmake 编译确保zlib.lib已生成。5.5 运行时报缺少 VCRUNTIME140.dll现象exe 拷到别的 Win10 机器上双击没反应提示缺VCRUNTIME140.dll或MSVCP140.dll。原因/MD编译的程序依赖 VC 运行时目标机器没装对应的 Redistributable。解决在目标机器安装 VS2019 对应的 VC Redistributable x64或者把工程改成/MT静态链接 CRT同时 curl 也要用RTLIBCFGstatic重编。工业现场我一般直接静态 CRT省得每台机器装运行时。6. 进阶把 curl 封装成项目里好用的请求类6.1 用 RAII 管住 CURL 句柄裸调curl_easy_init/curl_easy_cleanup很容易在异常路径上漏掉 cleanup。用一个简单的 RAII 包装class CurlHandle { public: CurlHandle() : h_(curl_easy_init()) {} ~CurlHandle() { if (h_) curl_easy_cleanup(h_); } CurlHandle(const CurlHandle) delete; CurlHandle operator(const CurlHandle) delete; CURL* get() const { return h_; } explicit operator bool() const { return h_ ! nullptr; } private: CURL* h_; };这样即使中途抛异常析构也会释放句柄。注意curl_global_init仍然要在 main 里单独调它管的是全局状态不是单个句柄。6.2 复用连接别每次请求都新建句柄如果程序要频繁请求同一个 host每次curl_easy_init都会重新做 DNS 和 TCP 握手。更好的做法是复用一个 CURL 句柄只改 URL 和回调CURL* curl curl_easy_init(); // 第一次请求 curl_easy_setopt(curl, CURLOPT_URL, https://api.example.com/a); curl_easy_perform(curl); // 第二次请求复用连接 curl_easy_setopt(curl, CURLOPT_URL, https://api.example.com/b); curl_easy_perform(curl);curl 内部会维护连接池同 host 的第二次请求会走已建立的连接。但要注意复用句柄时上一次设置的 option 会保留如果两次请求的回调或超时不同记得重新 set。6.3 用 curl_version_info 确认运行时能力编好的库到底支持哪些特性别靠猜运行时查一下curl_version_info_data* info curl_version_info(CURLVERSION_NOW); std::cout curl info-version \n; std::cout ssl: (info-ssl_version ? info-ssl_version : none) \n; std::cout features: info-features \n; if (info-features CURL_VERSION_SSL) std::cout HTTPS supported\n; if (info-features CURL_VERSION_LIBZ) std::cout gzip supported\n;features是个位掩码CURL_VERSION_SSL表示有 TLS 后端CURL_VERSION_LIBZ表示有 zlib。如果这里显示没有 SSL说明编译时WITH_SSL没生效HTTPS 请求会直接失败。这个检查我一般放在程序启动日志里出问题时一眼就能看出库的能力边界。最后说个习惯每次换机器或换 VS 版本重新编 curl 后我都会先跑一遍curl_version_info和那个最小 HTTPS 请求确认库是活的再往业务代码里接。这套流程在 Win10 VS2019 curl 7.84.0 上复现过很多次只要运行时库和 SSL 后端这两个点对齐基本不会翻车。希望帮到你。本文还有配套的精品资源点击获取