Frameworks courants¶
L'écosystème C et C++ est riche en bibliotheques specialisees, chacune occupant une niche bien définie. Contrairement a d'autres langages, il n'existe pas de framework "full-stack" dominant : on assemble des composants selon les besoins. Cette section distingue clairement les bibliotheques C++ générales, les GUI, le réseau, et l'écosystème C pur.
Vue d'ensemble des bibliotheques C++¶
| Bibliotheque | Domaine | Licence | Particularite |
|---|---|---|---|
| Qt | GUI, réseau, DB | LGPL/GPL | Framework complet, signaux/slots, QML |
| Boost | Génériques | BSL-1.0 | Incubateur de fonctionnalités futures de la STL |
| POCO | Réseau, HTTP, JSON | BSL-1.0 | API portable style Java, adapté aux services réseau |
| Abseil | Utilitaires Google | Apache 2 | Base de code de Google, conteneurs et strings robustes |
| {fmt} | Formatage | MIT | Base de std::format C++20, plus rapide que printf |
| spdlog | Logging | MIT | Logging zero-overhead base sur |
| nlohmann/json | JSON | MIT | JSON header-only, API intuitive |
Qt — framework GUI complet¶
Qt est le framework C++ le plus complet. Il couvre l'interface graphique, le réseau, les bases de données, le XML, le multimedia et bien plus. Son système de signaux/slots est un mécanisme de communication entre objets sans couplage fort.
// Application Qt minimale avec un bouton et un signal/slot
// Compilation : qmake hello.pro && make
// hello.pro : QT += widgets
// SOURCES = main.cpp
#include <QApplication>
#include <QPushButton>
#include <QMessageBox>
int main(int argc, char* argv[]) {
QApplication app(argc, argv);
// Creation d'un bouton
QPushButton bouton("Cliquez ici");
bouton.resize(200, 50);
// Connexion signal -> slot avec syntaxe fonctionnelle (Qt5+)
// Le lambda est appele quand clicked() est emis
QObject::connect(&bouton, &QPushButton::clicked, [&]() {
QMessageBox::information(&bouton, "Bonjour", "Hello depuis Qt !");
});
bouton.show();
return app.exec(); // Boucle evenementielle Qt
}
// Qt avec QNetworkAccessManager — requete HTTP asynchrone
#include <QCoreApplication>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QTimer>
#include <iostream>
int main(int argc, char* argv[]) {
QCoreApplication app(argc, argv);
QNetworkAccessManager manager;
auto* reply = manager.get(QNetworkRequest(QUrl("https://httpbin.org/get")));
QObject::connect(reply, &QNetworkReply::finished, [&]() {
if (reply->error() == QNetworkReply::NoError) {
std::cout << reply->readAll().toStdString() << "\n";
}
reply->deleteLater();
app.quit();
});
QTimer::singleShot(10000, &app, &QCoreApplication::quit); // Timeout 10s
return app.exec();
}
Boost — le laboratoire de la STL¶
Boost est une collection de plus de 160 bibliotheques C++ portables. Beaucoup de fonctionnalités de la STL moderne (smart pointers, regex, filesystem) sont issues de Boost.
// Boost.Asio — I/O asynchrone (base de nombreux frameworks reseau)
// Compilation : g++ -std=c++17 asio_demo.cpp -lboost_system -pthread
#include <boost/asio.hpp>
#include <iostream>
#include <string>
namespace asio = boost::asio;
using tcp = asio::ip::tcp;
int main() {
asio::io_context ctx;
// Resolveur DNS
tcp::resolver resolver(ctx);
auto endpoints = resolver.resolve("example.com", "80");
// Socket TCP
tcp::socket socket(ctx);
asio::connect(socket, endpoints);
// Requete HTTP/1.1 minimale
std::string requete =
"GET / HTTP/1.1\r\n"
"Host: example.com\r\n"
"Connection: close\r\n\r\n";
asio::write(socket, asio::buffer(requete));
// Lecture de la reponse
asio::streambuf reponse;
boost::system::error_code ec;
asio::read(socket, reponse, ec); // ec ignore : erreur EOF normale
std::cout << &reponse;
return 0;
}
Boost.Asio sans Boost
Asio est disponible en version standalone (sans le reste de Boost) sur asio.github.io. C'est la base de networking TS, le futur réseau de la STL C++.
POCO — services réseau portables¶
POCO (Portable Components) se concentre sur le réseau, HTTP, JSON, XML et les bases de données. Son API rappelle Java, ce qui facilite la prise en main.
// Serveur HTTP POCO minimal
// Compilation : g++ -std=c++17 server.cpp -lPocoNet -lPocoUtil -lPocoFoundation
#include <Poco/Net/HTTPServer.h>
#include <Poco/Net/HTTPRequestHandler.h>
#include <Poco/Net/HTTPRequestHandlerFactory.h>
#include <Poco/Net/HTTPServerRequest.h>
#include <Poco/Net/HTTPServerResponse.h>
#include <Poco/Net/ServerSocket.h>
#include <Poco/Util/ServerApplication.h>
#include <ostream>
#include <string>
using namespace Poco::Net;
using namespace Poco::Util;
// Handler pour chaque requete
class HelloHandler : public HTTPRequestHandler {
public:
void handleRequest(HTTPServerRequest& req, HTTPServerResponse& res) override {
res.setContentType("application/json");
res.setStatus(HTTPResponse::HTTP_OK);
std::ostream& out = res.send();
out << R"({"message":"Bonjour depuis POCO"})";
}
};
// Fabrique de handlers
class HelloFactory : public HTTPRequestHandlerFactory {
public:
HTTPRequestHandler* createRequestHandler(const HTTPServerRequest&) override {
return new HelloHandler;
}
};
class MonServeur : public ServerApplication {
int main(const std::vector<std::string>&) override {
ServerSocket socket(8080);
HTTPServer server(new HelloFactory, socket, new HTTPServerParams);
server.start();
waitForTerminationRequest(); // Attend Ctrl+C
server.stop();
return Application::EXIT_OK;
}
};
int main(int argc, char* argv[]) {
MonServeur app;
return app.run(argc, argv);
}
Abseil — utilitaires Google¶
Abseil est la bibliotheque d'utilitaires C++ open-sourcee par Google. Elle offre des conteneurs plus efficaces que la STL standard, des types de strings robustes et des outils de logging.
// Abseil — absl::string_view et absl::flat_hash_map
// Compilation : g++ -std=c++17 abseil_demo.cpp -labsl_base -labsl_container
#include <absl/container/flat_hash_map.h>
#include <absl/strings/str_split.h>
#include <absl/strings/str_join.h>
#include <iostream>
#include <string>
int main() {
// flat_hash_map : table de hachage plus cache-friendly que std::unordered_map
absl::flat_hash_map<std::string, int> scores;
scores["Alice"] = 95;
scores["Bob"] = 87;
scores["Carol"] = 92;
// absl::StrSplit — decoupage de chaine efficace
std::string csv = "Alice,Bob,Carol,Dave";
std::vector<std::string> noms = absl::StrSplit(csv, ',');
// absl::StrJoin — recomposition
std::string rejoints = absl::StrJoin(noms, " | ");
std::cout << rejoints << "\n"; // Alice | Bob | Carol | Dave
for (const auto& [nom, score] : scores)
std::cout << nom << ": " << score << "\n";
return 0;
}
Interfaces graphiques alternatives¶
| Bibliotheque | Style | Licence | Cas d'usage |
|---|---|---|---|
| Qt | Natif / QML | LGPL | Applications desktop complètes |
| Dear ImGui | Immédiate mode | MIT | Outils de debug, éditeurs de jeux, DevTools |
| wxWidgets | Natif OS | wxWindows | Applications multi-OS avec look natif |
| FLTK | Léger | LGPL | Interfaces très légères, embarque |
// Dear ImGui — interface de debug immediate-mode
// Base d'utilisation avec SDL2 + OpenGL backend
// (Code simplifie — voir imgui/examples/ pour le setup complet)
#include "imgui.h"
#include "imgui_impl_sdl2.h"
#include "imgui_impl_opengl3.h"
void rendreFenetreDebug(float& vitesse, bool& pause) {
// Chaque appel a ImGui::Begin/End cree une fenetre flottante
ImGui::Begin("Panneau de controle");
ImGui::Text("Etat de la simulation");
ImGui::Separator();
// Slider qui modifie directement la variable vitesse
ImGui::SliderFloat("Vitesse", &vitesse, 0.0f, 100.0f);
// Checkbox liee a la variable pause
ImGui::Checkbox("Pause", &pause);
if (ImGui::Button("Reset")) {
vitesse = 1.0f;
pause = false;
}
ImGui::Text("FPS: %.1f", ImGui::GetIO().Framerate);
ImGui::End();
}
Réseau et gRPC¶
// cpp-httplib — serveur HTTP header-only
// Compilation : g++ -std=c++17 http_server.cpp -lpthread
// Inclure httplib.h depuis https://github.com/yhirose/cpp-httplib
#include "httplib.h"
#include <nlohmann/json.hpp>
#include <string>
int main() {
httplib::Server srv;
// Route GET avec reponse JSON
srv.Get("/health", [](const httplib::Request&, httplib::Response& res) {
nlohmann::json j = {{"status", "ok"}, {"version", "1.0"}};
res.set_content(j.dump(), "application/json");
});
// Route POST — parsing du body JSON
srv.Post("/echo", [](const httplib::Request& req, httplib::Response& res) {
try {
auto body = nlohmann::json::parse(req.body);
res.set_content(body.dump(2), "application/json");
} catch (const nlohmann::json::exception& e) {
res.status = 400;
res.set_content(R"({"error":"JSON invalide"})", "application/json");
}
});
srv.listen("0.0.0.0", 8080);
return 0;
}
Écosystème C pur¶
| Bibliotheque | Domaine | Licence | Particularite |
|---|---|---|---|
| glib | Utilitaires | LGPL | Tableaux, tables de hachage, boucle événements |
| libcurl | HTTP/FTP/SFTP | MIT-like | Client réseau universel, base de curl CLI |
| OpenSSL | TLS/Crypto | Apache 2 | TLS 1.3, certificats X.509, chiffrement |
| libuv | I/O asynchrone | MIT | Backend de Node.js, boucle événements portable |
| SQLite | Base de données | Domaine public | Fichier unique, embedded, très portable |
/* libcurl — requete HTTP GET simple en C */
/* Compilation : gcc -Wall curl_demo.c -lcurl -o curl_demo */
#include <stdio.h>
#include <curl/curl.h>
#include <string.h>
#include <stdlib.h>
/* Callback pour ecrire les donnees recues dans un buffer */
typedef struct {
char* data;
size_t taille;
} Buffer;
static size_t callback_ecriture(void* contenu, size_t taille,
size_t nmemb, void* userp) {
size_t octets = taille * nmemb;
Buffer* buf = (Buffer*)userp;
buf->data = realloc(buf->data, buf->taille + octets + 1);
if (!buf->data) return 0;
memcpy(buf->data + buf->taille, contenu, octets);
buf->taille += octets;
buf->data[buf->taille] = '\0';
return octets;
}
int main(void) {
CURL* curl = curl_easy_init();
if (!curl) return 1;
Buffer reponse = {NULL, 0};
curl_easy_setopt(curl, CURLOPT_URL, "https://httpbin.org/get");
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, callback_ecriture);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &reponse);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10L);
CURLcode res = curl_easy_perform(curl);
if (res == CURLE_OK) {
printf("Reponse (%zu octets) :\n%s\n", reponse.taille, reponse.data);
} else {
fprintf(stderr, "Erreur curl : %s\n", curl_easy_strerror(res));
}
free(reponse.data);
curl_easy_cleanup(curl);
return (res == CURLE_OK) ? 0 : 1;
}
C vs C++ — ne pas melanger les styles
Dans un projet C++, privilegier les bibliotheques C++ natives (cpp-httplib, Boost.Beast, gRPC C++) plutôt que d'utiliser directement libcurl ou des API C bas niveau. Les wrappers RAII évitent les fuites mémoire et les erreurs de gestion de ressources. Utiliser les API C directement uniquement dans du code C pur ou lors de l'écriture de bindings.