現在、Web API を使用してアプリケーション間でデータを交換するのが一般的です。 JavaScript、Python、PHP などの言語で API を使用するためのチュートリアルはたくさんありますが、システム レベルのプログラミングに関連付けられることが多い C がこの目的で考慮されることはほとんどありません。ただし、C は API リクエストを完全に処理できるため、効率性と低レベルの制御のために C がすでに使用されている、販売時点情報管理 (PoS) システム、IoT デバイス、組み込みアプリケーションなどのシナリオでは実行可能な選択肢となります。
この記事では、libcurl ライブラリを利用して C で API を使用する方法について説明します。最後には、C を使用して API からデータをフェッチして処理する方法と、このアプローチが最新の開発にも関連する理由を理解できるようになります。
Web 開発では高級言語が主流ですが、特定のユースケースで API を使用するには C が依然として実用的な選択肢です。
C で API を使用するには、libcurl が頼りになるライブラリです。これは、HTTP、HTTPS、FTP などを介したネットワーク リクエストを処理するための、オープンソースでポータブルな機能豊富なライブラリです。以下をサポートします:
JSON データをフェッチする実際の例に焦点を当てて、C を使用して API を使用するプロセスを見てみましょう。
libcurl を使用するには、システムにインストールする必要があります。ほとんどの Linux ディストリビューションでは、これは次のように実行できます。
sudo apt-get install libcurl4-openssl-dev
Windows では、libcurl Web サイトからプリコンパイルされたバイナリをダウンロードできます: 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; }
libcurl を使用して C で HTTP 応答を処理する場合、コールバック関数の動作を理解することが重要です。応答データを処理するために定義したコールバック関数 (ResponseCallback 関数など) は、1 つの HTTP 応答に対して複数回呼び出される場合があります。これがその理由と仕組みです。
libcurl のコールバック メカニズムは、データを効率的かつ柔軟に処理できるように設計されています。応答全体がダウンロードされるのを待ってから処理するのではなく、libcurl は応答を小さなチャンクに分割して処理し、各チャンクが受信されるたびにコールバック関数を呼び出します。
この動作により以下が可能になります:
仕組みは?
データのチャンクをサーバーから受信するたびに、libcurl はコールバック関数を呼び出します。各チャンクのサイズは、ネットワークの状態、バッファ サイズ、libcurl の内部ロジックによって異なります。
コールバックはチャンクを蓄積し、最終的に完全な応答を再構築する必要があります。
シーケンスの例を次に示します:
ResponseCallback は、libcurl によってデータが受信されたときに呼び出される関数です。
sudo apt-get install libcurl4-openssl-dev
brew install curl
これは、1 つのブロックのサイズ (size) とブロック数 (nmemb) を乗算して、受信したデータの現在のチャンクの合計サイズを計算します。
たとえば、サーバーがそれぞれ 256 バイトのブロックを 8 つ送信する場合、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 * にキャストされます。この構造体はメイン プログラムの前半で渡され、受信したデータを蓄積するために使用されます。
構造体メモリは次のように定義されます:
./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 に通知します。
次の場合に API の使用に C を使用します。
C で API を使用することは、今日の高レベル プログラミングの世界では型破りに思えるかもしれませんが、パフォーマンス、制御、およびシステム レベルの操作との統合が必要なシナリオにとっては強力なツールです。 libcurl のようなライブラリを使用することで、開発者は HTTP リクエストを C アプリケーションに簡単に統合し、最新の API と従来のシステムレベルのプログラミングの間のギャップを埋めることができます。
この知識があれば、API とシームレスに対話する C アプリケーションを構築でき、最新の開発ワークフローでも C が関連性を維持していることが証明されます。
以上がC での API の使用: 最新の開発者のための実践的なガイドの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。