Heutzutage ist die Nutzung von Web-APIs eine gängige Praxis für den Datenaustausch zwischen Anwendungen. Tutorials zur Verwendung von APIs in Sprachen wie JavaScript, Python oder PHP gibt es in Hülle und Fülle, doch C – das oft mit der Programmierung auf Systemebene in Verbindung gebracht wird – wird für diesen Zweck selten in Betracht gezogen. C ist jedoch durchaus in der Lage, API-Anfragen zu verarbeiten, was es zu einer brauchbaren Wahl für Szenarien wie Point-of-Sale-Systeme (PoS), IoT-Geräte oder eingebettete Anwendungen macht, in denen C aufgrund seiner Effizienz und einfachen Steuerung bereits verwendet wird.
In diesem Artikel wird untersucht, wie man APIs in C nutzt und dabei die libcurl-Bibliothek nutzt. Am Ende werden Sie verstehen, wie Sie mit C Daten von APIs abrufen und verarbeiten und warum dieser Ansatz auch in der modernen Entwicklung relevant ist.
Warum C zum Konsumieren von APIs verwenden?
Während höhere Sprachen die Webentwicklung dominieren, ist C immer noch eine praktische Wahl für die Nutzung von APIs in bestimmten Anwendungsfällen:
- Leistung: C bietet hohe Leistung und minimalen Overhead und eignet sich daher für ressourcenbeschränkte Umgebungen wie IoT-Geräte.
- Kontrolle: Die direkte Speicherverwaltung ermöglicht eine fein abgestimmte Optimierung, insbesondere für eingebettete Systeme.
- Interoperabilität: Die weit verbreitete Verwendung von C bedeutet, dass es sich gut in Vorgänge auf Systemebene integrieren lässt, wie z. B. die Steuerung von Hardware, Sensoren oder anderen Peripheriegeräten.
- Langlebigkeit: In C erstellte Anwendungen haben oft eine lange Lebensdauer, insbesondere in Branchen wie dem Einzelhandel oder der Fertigung.
Wir stellen vor: libcurl: das Tool für HTTP in C
Um APIs in C zu nutzen, ist libcurl die Bibliothek der Wahl. Es handelt sich um eine Open-Source-, portable und funktionsreiche Bibliothek zur Bearbeitung von Netzwerkanfragen über HTTP, HTTPS, FTP und mehr. Es unterstützt:
- GET-, POST- und andere HTTP-Anfragen stellen.
- Verwaltung von Headern und Authentifizierung.
- Antworten effizient bearbeiten.
Grundlegende Schritte zum Nutzen einer API in C
Lassen Sie uns den Prozess der Nutzung einer API mit C durchgehen und uns dabei auf ein reales Beispiel für das Abrufen von JSON-Daten konzentrieren.
Einrichtung und Installation
Um libcurl verwenden zu können, müssen Sie es auf Ihrem System installieren. Bei den meisten Linux-Distributionen kann dies erfolgen mit:
sudo apt-get install libcurl4-openssl-dev
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Unter Windows können Sie vorkompilierte Binärdateien von der libcurl-Website herunterladen: https://curl.se/download.html
Wenn Sie Homebrew unter macOS verwenden, können Sie es über
installieren
brew install curl
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Strukturieren Sie Ihr C-Programm
Ein einfaches C-Programm zum Abrufen von Daten von einer API umfasst die folgenden Komponenten:
- Libcurl wird initialisiert.
- Konfigurieren der API-Anfrage (URL, HTTP-Methode, Header usw.).
- Empfangen und Speichern der Antwort.
- Ressourcen bereinigen.
Hier ist ein Beispielprogramm zum Abrufen von JSON-Daten von einer öffentlichen API:
sudo apt-get install libcurl4-openssl-dev
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Schritte zum Ausführen
Speichern Sie den Code in einer Datei, z. B. get.c.
Kompilieren Sie es mit dem folgenden Befehl:
brew install curl
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Führen Sie das kompilierte Programm aus:
#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
Nach dem Login kopieren
Nach dem Login kopieren
';
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;
}
Den Rückrufmechanismus in HTTP-Antworten mit libcurl verstehen
Wenn Sie mit libcurl arbeiten, um HTTP-Antworten in C zu verarbeiten, ist es wichtig, das Verhalten der Rückruffunktion zu verstehen. Die Rückruffunktion, die Sie zum Verarbeiten der Antwortdaten definieren, z. B. die ResponseCallback-Funktion, kann für eine einzelne HTTP-Antwort mehrmals aufgerufen werden. Hier erfahren Sie, warum und wie das funktioniert.
Warum wird der Rückruf mehrmals aufgerufen?
Der Rückrufmechanismus in libcurl ist darauf ausgelegt, Daten effizient und flexibel zu verarbeiten. Anstatt darauf zu warten, dass die gesamte Antwort heruntergeladen wurde, bevor sie verarbeitet wird, verarbeitet libcurl die Antwort in kleineren Blöcken und ruft Ihre Rückruffunktion auf, sobald jeder Block empfangen wird.
Dieses Verhalten ermöglicht:
- Effiziente Speichernutzung: Durch die inkrementelle Verarbeitung von Blöcken vermeiden Sie die Notwendigkeit, im Voraus einen großen Speicherblock für die gesamte Antwort zuzuweisen.
- Gestreamte Verarbeitung: Sie können jeden Block verarbeiten oder darauf reagieren, sobald er ankommt. Dies ist nützlich, um große Antworten zu streamen oder Daten in Echtzeit zu verarbeiten.
Wie funktioniert es?
Jedes Mal, wenn ein Datenblock vom Server empfangen wird, ruft libcurl Ihre Rückruffunktion auf. Die Größe jedes Blocks hängt von den Netzwerkbedingungen, den Puffergrößen und der internen Logik von libcurl ab.
Der Rückruf muss die Blöcke akkumulieren und letztendlich die vollständige Antwort rekonstruieren.
Hier ist eine Beispielsequenz:
- Der Server beginnt mit dem Senden der Antwort.
- libcurl empfängt den ersten Block und ruft den Rückruf auf.
- Der Rückruf verarbeitet oder speichert den Chunk.
- libcurl empfängt den nächsten Block und ruft den Rückruf erneut auf.
- Dieser Vorgang wird fortgesetzt, bis die gesamte Antwort eingegangen ist.
Schritt-für-Schritt-Erklärung des Quellcodes für die ResponseCallback-Funktion
Der ResponseCallback ist die Funktion, die aufgerufen wird, wenn Daten von libcurl empfangen werden.
Funktionsdeklaration
sudo apt-get install libcurl4-openssl-dev
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
-
void *contents: Dies ist ein Zeiger auf die vom Server empfangenen Daten. libcurl stellt diesen Puffer bereit und füllt ihn mit den heruntergeladenen Daten.
-
size_t size und size_t nmemb: Diese stellen die Größe jedes Speicherblocks (Size) und die Anzahl der Blöcke (nmemb) dar. Zusammen ergibt size * nmemb die Gesamtgröße der in diesem Block empfangenen Daten.
-
void *userp: Dies ist ein benutzerdefinierter Zeiger, der über curl_easy_setopt(curl, CURLOPT_WRITEDATA, ...) an die Callback-Funktion übergeben wird. In diesem Beispiel handelt es sich um einen Zeiger auf ein Strukturspeicherobjekt, das die vollständige Antwort speichert.
Berechnen Sie die Gesamtdatengröße
brew install curl
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Dadurch wird die Gesamtgröße des aktuell empfangenen Datenblocks berechnet, indem die Größe eines Blocks (Größe) mit der Anzahl der Blöcke (nmemb) multipliziert wird.
Wenn der Server beispielsweise 8 Blöcke mit jeweils 256 Byte sendet, beträgt die Gesamtgröße 8 * 256 = 2048 Byte.
Auf Benutzerdaten zugreifen (Strukturspeicher)
#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
Nach dem Login kopieren
Nach dem Login kopieren
';
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;
}
Der Userp-Zeiger wird in eine Struktur Memory * umgewandelt. Diese Struktur wurde zuvor im Hauptprogramm übergeben und wird zum Sammeln der empfangenen Daten verwendet.
Die Struktur Memory ist definiert als:
./get
Nach dem Login kopieren
-
Antwort: eine dynamisch zugewiesene Zeichenfolge, die die heruntergeladenen Daten speichert.
-
Größe: die aktuelle Größe der Antwortzeichenfolge.
Speicher neu zuweisen
static size_t ResponseCallback(void *contents, size_t size, size_t nmemb, void *userp)
Nach dem Login kopieren
Ändert die Größe des Antwortpuffers, um den neuen Datenblock aufzunehmen:
-
mem->size: die aktuelle Größe des Puffers.
-
totalSize: Die Größe des neuen Blocks.
-
1: Platz für den Nullterminator ( ), um daraus einen gültigen C-String zu machen.
-
realloc: Weist Speicher für den Antwortpuffer dynamisch neu zu.
Wenn die Zuweisung fehlschlägt, gibt realloc NULL zurück und der alte Speicher bleibt gültig.
Behandeln Sie Speicherzuordnungsfehler
size_t totalSize = size * nmemb;
Nach dem Login kopieren
Wenn die Speicherzuweisung fehlschlägt (also ptr NULL ist), geben Sie eine Fehlermeldung aus und geben Sie 0 zurück. Die Rückgabe von 0 signalisiert libcurl, die Übertragung abzubrechen.
Aktualisieren Sie den Puffer
struct Memory *mem = (struct Memory *)userp;
Nach dem Login kopieren
-
mem->response = ptr: Weisen Sie den neu zugewiesenen Speicher wieder dem Antwortzeiger zu.
-
memcpy: Kopieren Sie den neuen Datenblock aus dem Inhalt in den Puffer:
-
&(mem->response[mem->size]): Die Position im Puffer, an der die neuen Daten angehängt werden sollen (Ende der aktuellen Daten).
-
Inhalt: Die vom Server empfangenen Daten.
-
totalSize: Die Größe der zu kopierenden Daten.
Aktualisieren Sie die Gesamtgröße
struct Memory {
char *response;
size_t size;
};
Nach dem Login kopieren
Erhöhen Sie die Größe des Antwortpuffers, um die neue Gesamtgröße nach dem Anhängen des neuen Blocks widerzuspiegeln.
Beenden Sie die Antwortzeichenfolge mit Null
sudo apt-get install libcurl4-openssl-dev
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Fügen Sie am Ende des Antwortpuffers einen Nullterminator hinzu, um daraus einen gültigen C-String zu machen.
Dadurch wird sichergestellt, dass die Antwort sicher als normale nullterminierte Zeichenfolge behandelt werden kann.
Gibt die Gesamtgröße zurück
brew install curl
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Gibt die Anzahl der verarbeiteten Bytes zurück (totalSize).
Dies signalisiert libcurl, dass der Datenblock erfolgreich verarbeitet wurde.
Wann sollte man C für APIs wählen?
Verwenden Sie C zum Konsumieren von APIs, wenn:
- Leistung zählt: C ist ideal für geschwindigkeitskritische Anwendungen.
- Systemintegration: Sie müssen Netzwerkanfragen mit Hardwarevorgängen kombinieren (z. B. das Abrufen von Daten für ein PoS-System).
- Eingebettete Systeme: Geräte mit begrenzten Ressourcen profitieren von der Effizienz von C.
-
Neugier und Erkundung: Manchmal verwenden Sie C einfach, weil Ihnen das Programmieren Spaß macht und Sie sich selbst herausfordern möchten, indem Sie eine Sprache auf niedrigerem Niveau für Aufgaben erforschen, die oft höheren Programmiersprachen vorbehalten sind. Es ist eine großartige Möglichkeit, Ihr Verständnis dafür zu vertiefen, wie die Dinge unter der Haube funktionieren!
Abschluss
Die Nutzung von APIs in C mag in der heutigen High-Level-Programmierwelt unkonventionell erscheinen, aber es ist ein leistungsstarkes Tool für Szenarien, die Leistung, Kontrolle und Integration mit Vorgängen auf Systemebene erfordern. Durch die Verwendung von Bibliotheken wie libcurl können Entwickler HTTP-Anfragen problemlos in C-Anwendungen integrieren und so die Lücke zwischen modernen APIs und traditioneller Programmierung auf Systemebene schließen.
Mit diesem Wissen können Sie C-Anwendungen erstellen, die nahtlos mit APIs interagieren und so beweisen, dass C auch in modernen Entwicklungsworkflows relevant bleibt.
Das obige ist der detaillierte Inhalt vonNutzung von APIs in C: ein praktischer Leitfaden für moderne Entwickler. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!