libcurl是C++调用Web API最成熟跨平台选择;Linux用apt安装,macOS用Homebrew,Windows推荐vcpkg;发JSON POST需设CURLOPT_POSTFIELDS、Content-Type头、WriteCallback,并处理重定向、gzip、SSL验证等细节。

用 C++ 调用 Web API 接口,libcurl 是最成熟、跨平台、可控性最强的选择;它不依赖 Qt 或 Boost 等大型框架,适合嵌入式、服务端或轻量 CLI 工具场景。
怎么引入 libcurl(Windows / Linux / macOS)
不同系统下,libcurl 的获取和链接方式差异明显,直接决定后续能否编译通过:
- Linux(Ubuntu/Debian):
sudo apt install libcurl4-openssl-dev,编译时加-lcurl - macOS:用 Homebrew 安装
brew install curl,头文件在/opt/homebrew/include/curl/(Apple Silicon),链接时加-lcurl,注意可能需指定路径:-L/opt/homebrew/lib - Windows:推荐用 vcpkg:
vcpkg install curl:x64-windows,然后在 CMake 中find_package(CURL REQUIRED);手动链接容易漏ws2_32.lib和wldap32.lib,导致undefined reference to 'curl_easy_init'
怎么发一个标准 JSON POST 请求
多数 Web API 要求 Content-Type: application/json,且请求体是 UTF-8 编码的 JSON 字符串。关键点不在“发出去”,而在“发得对”:
- 必须调用
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json_str.c_str()),不能只设 URL 后靠GET拼参 - 必须显式设置
Content-Typeheader:struct curl_slist* headers = nullptr; headers = curl_slist_append(headers, "Content-Type: application/json"); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); -
json_str必须是std::string(非const char*临时字面量),否则curl可能在发送中途读到已释放内存 - 务必检查返回值:
CURLcode res = curl_easy_perform(curl);,res != CURLE_OK时,用curl_easy_strerror(res)查错,而不是只看 HTTP 状态码
#include#include #include size_t WriteCallback(void contents, size_t size, size_t nmemb, void userp) { ((std::string)userp)->append((char)contents, size nmemb); return size nmemb; }
int main() { CURL* curl; CURLcode res; std::string readBuffer; std::string json = R"({"name":"Alice","age":30})";
curl = curl_easy_init(); if (!curl) return -1; curl_easy_setopt(curl, CURLOPT_URL, "https://httpbin.org/post"); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json.c_str()); curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, json.length()); struct curl_slist* headers = nullptr; headers = curl_slist_append(headers, "Content-Type: application/json"); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer); curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10L); res = curl_easy_perform(curl); if (res != CURLE_OK) { std::cerr << "curl_easy_perform() failed: " << curl_easy_strerror(res) << "\n"; } else { long http_code = 0; curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code); std::cout << "HTTP " << http_code << "\n" << readBuffer << "\n"; } curl_slist_free_all(headers); curl_easy_cleanup(curl); return 0;}
立即学习“C++免费学习笔记(深入)”;
为什么 response 返回空或乱码?常见陷阱
不是接口没响应,而是
libcurl默认不处理重定向、不自动解压、不校验证书——这些都得手动开:
- 遇到 301/302 重定向但没跳转?补上:
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);- 返回 gzip 压缩内容却显示乱码?加:
curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, "");(空字符串表示接受所有编码,libcurl自动解压)- HTTPS 请求失败,报
SSL certificate problem?开发阶段可临时禁用验证:curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);(上线前必须删掉)- 中文字段在 response 里变成
\u4f60\u597d?那是服务器返回了 Unicode 转义,不是libcurl的问题;解析 JSON 时用支持 UTF-8 的库(如nlohmann/json),别用手工substr真正难的不是写通第一个请求,而是让错误可定位、超时可控制、证书可配置、JSON 可解析、重定向可追溯——这些细节堆起来,才构成一次生产可用的 API 调用。











