Aller au contenu

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.