如今,使用 Web API 是在應用程式之間交換資料的常見做法。關於使用 JavaScript、Python 或 PHP 等語言的 API 的教學課程有很多,但 C(通常與系統層級程式設計相關)很少被考慮用於此目的。然而,C 完全有能力處理API 請求,使其成為銷售點(PoS) 系統、物聯網設備或嵌入式應用程式等場景的可行選擇,在這些場景中,C 已經因其效率和低階控製而被使用。
本文探討如何利用 libcurl 函式庫使用 C 語言的 API。最後,您將了解如何使用 C 從 API 取得和處理數據,以及為什麼這種方法即使在現代開發中也有意義。
雖然高階語言主導 Web 開發,但 C 仍然是在特定用例中使用 API 的實用選擇:
要使用 C 語言的 API,libcurl 是首選函式庫。它是一個開源、可移植且功能豐富的函式庫,用於處理透過 HTTP、HTTPS、FTP 等的網路請求。它支援:
讓我們逐步了解使用 C 語言使用 API 的過程,並專注於獲取 JSON 資料的實際範例。
要使用 libcurl,您需要在系統上安裝它。對於大多數 Linux 發行版,這可以透過以下方式完成:
sudo apt-get install libcurl4-openssl-dev
在 Windows 上,您可以從 libcurl 網站下載預先編譯的二進位檔案:https://curl.se/download.html
在 macOS 上,如果您使用 Homebrew,可以透過
安裝它
brew install curl
從 API 取得資料的簡單 C 程式涉及以下元件:
這是一個從公用 API 取得 JSON 資料的範例程式:
sudo apt-get install libcurl4-openssl-dev
將程式碼保存在檔案中,例如 get.c。
使用以下命令編譯它:
brew install curl
運行編譯好的程式:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <curl/curl.h> // Struct to hold response data struct Memory { char *response; size_t size; }; // Callback function to handle the data received from the API static size_t ResponseCallback(void *contents, size_t size, size_t nmemb, void *userp) { size_t totalSize = size * nmemb; struct Memory *mem = (struct Memory *)userp; printf(". %zu %zu\n", size, nmemb); char *ptr = realloc(mem->response, mem->size + totalSize + 1); if (ptr == NULL) { printf("Not enough memory to allocate buffer.\n"); return 0; } mem->response = ptr; memcpy(&(mem->response[mem->size]), contents, totalSize); mem->size += totalSize; mem->response[mem->size] = '<pre class="brush:php;toolbar:false">gcc get.c -o get -lcurl'; return totalSize; } int main() { CURL *curl; CURLcode res; struct Memory chunk; chunk.response = malloc(1); // Initialize memory chunk.size = 0; // No data yet curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if (curl) { // Set URL of the API endpoint char access_token[] = "your-access-token"; char slug[] = "home"; char version[]= "draft"; char url[256]; snprintf(url, sizeof(url), "https://api.storyblok.com/v2/cdn/stories/%s?version=%s&token=%s", slug, version, access_token); // Print the URL printf("URL: %s\n", url); // initializing libcurl // setting the URL curl_easy_setopt(curl, CURLOPT_URL, url ); // Follow redirect curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); // Set callback function to handle response data curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, ResponseCallback); // Pass the Memory struct to the callback function curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk); // Perform the HTTP GET request res = curl_easy_perform(curl); // Check for errors if (res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } else { printf("Response data size: %zu\n", chunk.size); //printf("Response data: \n%s\n", chunk.response); } // Cleanup curl_easy_cleanup(curl); } // Free allocated memory free(chunk.response); curl_global_cleanup(); return 0; }
在 C 中使用 libcurl 處理 HTTP 回應時,了解回呼函數的行為非常重要。您定義的用於處理回應資料的回呼函數(例如 ResponseCallback 函數)可能會針對單一 HTTP 回應呼叫多次。這就是為什麼以及它是如何工作的。
libcurl 中的回呼機制旨在高效、靈活地處理資料。 libcurl 不會在處理整個回應之前等待下載整個回應,而是以較小的區塊處理回應,並在收到每個區塊時呼叫回調函數。
此行為允許:
它是如何運作的?
每次從伺服器接收到一塊資料時,libcurl 都會呼叫您的回呼函數。每個區塊的大小取決於網路條件、緩衝區大小和 libcurl 的內部邏輯。
回調必須累積塊,最終重建完整的響應。
這是一個範例序列:
ResponseCallback 是 libcurl 接收資料時呼叫的函式。
sudo apt-get install libcurl4-openssl-dev
brew install curl
透過將一個區塊的大小 (size) 乘以區塊的數量 (nmemb) 來計算目前接收到的資料區塊的總大小。
例如,如果伺服器發送 8 個區塊,每個區塊 256 字節,totalSize 將為 8 * 256 = 2048 位元組。
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <curl/curl.h> // Struct to hold response data struct Memory { char *response; size_t size; }; // Callback function to handle the data received from the API static size_t ResponseCallback(void *contents, size_t size, size_t nmemb, void *userp) { size_t totalSize = size * nmemb; struct Memory *mem = (struct Memory *)userp; printf(". %zu %zu\n", size, nmemb); char *ptr = realloc(mem->response, mem->size + totalSize + 1); if (ptr == NULL) { printf("Not enough memory to allocate buffer.\n"); return 0; } mem->response = ptr; memcpy(&(mem->response[mem->size]), contents, totalSize); mem->size += totalSize; mem->response[mem->size] = '<pre class="brush:php;toolbar:false">gcc get.c -o get -lcurl'; return totalSize; } int main() { CURL *curl; CURLcode res; struct Memory chunk; chunk.response = malloc(1); // Initialize memory chunk.size = 0; // No data yet curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if (curl) { // Set URL of the API endpoint char access_token[] = "your-access-token"; char slug[] = "home"; char version[]= "draft"; char url[256]; snprintf(url, sizeof(url), "https://api.storyblok.com/v2/cdn/stories/%s?version=%s&token=%s", slug, version, access_token); // Print the URL printf("URL: %s\n", url); // initializing libcurl // setting the URL curl_easy_setopt(curl, CURLOPT_URL, url ); // Follow redirect curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); // Set callback function to handle response data curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, ResponseCallback); // Pass the Memory struct to the callback function curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk); // Perform the HTTP GET request res = curl_easy_perform(curl); // Check for errors if (res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } else { printf("Response data size: %zu\n", chunk.size); //printf("Response data: \n%s\n", chunk.response); } // Cleanup curl_easy_cleanup(curl); } // Free allocated memory free(chunk.response); curl_global_cleanup(); return 0; }
userp 指標被轉換為 struct Memory *。此結構體已在主程式中前面傳遞,用於累積接收到的資料。
結構體 Memory 定義為:
./get
static size_t ResponseCallback(void *contents, size_t size, size_t nmemb, void *userp)
調整響應緩衝區的大小以容納新的資料區塊:
如果分配失敗,realloc回傳NULL,舊記憶體仍然有效。
size_t totalSize = size * nmemb;
如果記憶體分配失敗(因此 ptr 為 NULL),則列印錯誤訊息並傳回 0。傳回 0 表示 libcurl 中止傳輸。
struct Memory *mem = (struct Memory *)userp;
struct Memory { char *response; size_t size; };
增加響應緩衝區的大小以反映附加新區塊後的新總大小。
sudo apt-get install libcurl4-openssl-dev
在回應緩衝區末端新增一個空終止符,使其成為有效的 C 字串。
這確保了回應可以被安全地視為常規的空終止字串。
brew install curl
傳回已處理的位元組數(totalSize)。
這向 libcurl 發出訊號,表明資料區塊已成功處理。
在下列情況下使用 C 來使用 API:
在當今的高階程式設計世界中,使用 C 語言的 API 似乎不合常規,但對於需要效能、控制以及與系統級操作整合的場景來說,它是一個強大的工具。透過使用 libcurl 等函式庫,開發人員可以輕鬆地將 HTTP 請求整合到 C 應用程式中,從而彌合現代 API 和傳統系統級程式設計之間的差距。
有了這些知識,您就可以建立與 API 無縫交互的 C 應用程序,證明 C 即使在現代開發工作流程中仍然具有相關性。
以上是使用 C 語言 API:現代開發人員的實用指南的詳細內容。更多資訊請關注PHP中文網其他相關文章!