C++ Bibliotheksammlung veröffentlich (cpplocate, cppassist, cppfs, cppexpose)

CG Internals hat vier ihrer Projekte veröffentlicht: cpplocate, cppassist, cppfs und cppexpose. Die Projekte stellen diverse, domänenunspezifische Features für C++ bereit. Im Speziellen werden durch die Bibliotheken Features wie Asset-Lokalisierung zur Laufzeit, Command Line Argumentverarbeitung, Logging, Hilfsfunktionen und -klassen für Parallelisierung und Vektorisierung, Cross-platform Dateisystemzugriff, Objektintrospektion, Skriptanbindungen, als auch ein Plugin-System bereitgestellt.

Alle Quelltexte sind unter MIT-kompatibler Lizenz auf Github veröffentlicht. Es sind Installer für Windows und .deb Pakete über die cginternals PPA verfügbar.

Eine kurze Einführung der vier Bibliotheken:


cpplocate-logo

cpplocate ist eine cross-platform C++ Bibliothek, die Funktionen für Software bereitstellt, ihre Assets und Daten zur Laufzeit zu lokalisieren. Die Bibliothek unterstützt verschiedene Setups wie Applikationen, Bibliotheken oder App Bundles. Für den allgemeinen Anwendungsfall, die eigenen Daten zu finden, stellt die Bibliothek eine separate Funktion bereit. Intern ist cpplocate in reinem C implementiert. Die ebenfalls mitgelieferte Bibliothek liblocate ist für Projekte gedacht, die nicht mit einer C++ Schnittstelle arbeiten wollen.

Weiterführende Informationen und Dokumentation sind online verfügbar.

Beispiel:

#include <cpplocate/cpplocate.h>

#include <glbinding/gl/gl.h>

const std::string assetPath = cpplocate::locatePath("data/cubescape", "share/glbinding", reinterpret_cast<void *>(&gl::glCreateShader));
// assetPath now contains the path to the directory containing "data/cubescape"


cppassist-logo

cppassist ist eine Sammlung von cross-platform C++ Funktionen, Klassen und Bibliotheken, welche für sich genommen zu klein für eine eigenständige Bibliothek wären. Dabei wird diese Bibliothek als Sammelort für nützlichen und wiederverwendbaren Code benutzt, welcher bei der Programmierung mit C++ wiederkehrend benötigt wird.

Weiterführende Informationen und Dokumentation sind online verfügbar.

Zum aktuellen Stand bestehht cppassist aus folgenden Modulen:

  • cmdline: Ein Command Line Parser für Konsolenanwendungen
  • flags: Ein Flag-Datentyp um das Sprachkonstrukt enum für bitweise Flag-Manipulation zu verwenden
  • fs: Hilfsklassen zum Lesen von Binärdateien mit Key-Value Header Informationen
  • logging: C++-Stream-artige Schnittstelle zum Loggen mit konfigurierbarer Ausgabe
  • memory: Hilfskonstrukte für Speichermanagement
  • simd: Strukturen und Algorithmen für SIMD Datenprozessierung mittels SSE und AVX
  • string: Hilfsfunktionen für Konvertierungen von und zu Strings, Manipulationen von Strings und regulären Ausdrücken
  • threading: Hilfsfunktionen für nebenläufige Schleifenausführung
  • tokenizer: Ein Basis-Tokenizer, z.B. zum Parsen von Texten wie Konfigurationsdateien
  • typelist: Ein Datentyp zur Iteration über eine Liste von Datentypen, umgesetzt durch Instanziierung von Templates

Beispiel zu logging:

#include <cppassist/logging/logging.h>

cppassist::setVerbosityLevel(LogMessage::Debug + 2);

cppassist::critical() << "A normal critical message.";
cppassist::error() << "A normal error message.";
cppassist::warning() << "A normal warning message.";
cppassist::info() << "A normal info message.";
cppassist::debug() << "A normal debug message.";
cppassist::debug(1) << "Another debug message.";

cppassist::info("A") << "Info message from context A";
cppassist::warning("B") << "Warning from context B";
cppassist::critical("C") << "Critical message from context C";

Beispiel zur Stringmanipulation:

#include <cppassist/string/manipulation.h>

const auto commaSeparatedList = cppassist::join({ 1, 2, 3, 4, 5}, ",");
const auto stringVector = cppassist::split("1,2,3,4,5", ',', false);
const auto trimmedString = cppassist::trim("     Hallo     ");
const auto strippedString = cppassist::stripped("1-2-3-4-5-6", { '-' });

Beispiel zu threading:

#include <cppassist/threading/parallelfor.h>

bool parallelize = size > 25; // use parallel computation if threshold is reached

// Beware that start and end are both inclusive
cppassist::forEach(0u, size, [this](std::uint32_t number)
{
    // concurrent calls of this with 0 <= number <= size
}, parallelize);

Tokenizer Beispiel:

#include <cppassist/tokenizer/Tokenizer.h>

// Create tokenizer for JSON
cppassist::Tokenizer tokenizer;

tokenizer.setOptions(
    cppassist::Tokenizer::OptionParseStrings
    | cppassist::Tokenizer::OptionParseNumber
    | cppassist::Tokenizer::OptionParseBoolean
    | cppassist::Tokenizer::OptionParseNull
    | cppassist::Tokenizer::OptionCStyleComments
    | cppassist::Tokenizer::OptionCppStyleComments
);

tokenizer.setQuotationMarks("\"");
tokenizer.setSingleCharacters("{}[],:");


cppfs-logo

cppfs ist eine cross-platform C++ Bibliothek mit objektorientierter Abstraktionsschicht zum Arbeiten mit Dateien und Dateisystemen. Dabei kann sie für das lokale Dateisystem, aber auch für Netzwerklaufwerke und virtuelle Dateisysteme verwendet werden. Zum Ergänzen neuer Protokolle und virtuelle Dateisystemtypen ist nur eine Spezialisierung des Backend erforderlich.

Weiterführende Informationen und Dokumentation sind online verfügbar.

Iterieren über Dateisystemordner:

#include <cppfs/fs.h>
#include <cppfs/FileHandle.h>

using namespace cppfs;

void listDir(const std::string & path)
{
    FileHandle dir = fs::open(path);

    if (dir.isDirectory())
    {
        for (FileIterator it = dir.begin(); it != dir.end(); ++it)
        {
            std::string path = *it;
        }
    }
}

Öffnen einer Datei zum Lesen und Schreiben:

#include <cppfs/fs.h>
#include <cppfs/FileHandle.h>

using namespace cppfs;

void openFile(const std::string & filename)
{
    FileHandle fh = fs::open(filename);

    if (fh.isFile())
    {
        auto in = fh.createInputStream();
        // ...

        auto out = fh.createOutputStream();
        // ...
    }
}


cppexpose-logo

cppexpose ist eine cross-platform C++ Bibliothek zur Introspektion von Typen, Attributen und Klassen. Das ermöglicht das dynamische Anbieten und Verarbeiten von Programmschnittstellen zur Laufzeit, was wiederum benutzt werden kann um z. B. automatische Formulare oder andere grafische Oberflächen zu erstellen oder C++ Objekte in Skripten zu verwenden. Die Implementierung basiert auf standard C++11 ohne Spracherweiterungen und ohne separatem Compiler, was die Integration vereinfacht und Typsicherheit gewährleistet.

Weiterführende Informationen und Dokumentation sind online verfügbar.

Komponentenkonzept und Plugins:

int main(int, char * [])
{
    // Create a component manager
    cppexpose::ComponentManager componentManager;

    // Search for plugins in the current working directory
    componentManager.addPluginPath(".");
    componentManager.scanPlugins();

    // List available components
    std::cout << "Components:" << std::endl;
    std::cout << std::endl;
    for (cppexpose::AbstractComponent * component : componentManager.components())
    {
        std::cout << "----------------------------------------" << std::endl;
        std::cout << "name:        " << component->name() << std::endl;
        std::cout << "type:        " << component->type() << std::endl;
        std::cout << "description: " << component->description() << std::endl;
        std::cout << "tags:        " << component->tags() << std::endl;
        std::cout << "annotations: " << component->annotations() << std::endl;
        std::cout << "vendor:      " << component->vendor() << std::endl;
        std::cout << "version:     " << component->version() << std::endl;
        std::cout << "----------------------------------------" << std::endl;
        std::cout << std::endl;
    }
}

Introspektion in Klassen:

// Create object and print its initial contents
MyObject obj;
obj.print();

// Enumerate properties
std::cout << "Properties:" << std::endl;
for (auto it : obj.properties())
{
    cppexpose::AbstractProperty * property = it.second;
    std::cout << "- " << property->name() << " (" << property->typeName() << ")" << std::endl;
}
std::cout << std::endl;

Scripting:

int main(int, char * [])
{
    ScriptContext scriptContext;

    // Create scripting environment
    Object script("script");
    scriptContext.addGlobalObject(&script);

    MyObject obj ("obj");
    script.addProperty(&obj);

    TreeNode tree("tree");
    script.addProperty(&tree);

    // Provide a script console
    bool done = false;
    while (!done && !std::cin.eof())
    {
        // Prompt
        std::cout << "> " << std::flush;

        // Read command
        std::string cmd;
        std::getline(std::cin, cmd);

        // Process command
        if (cmd != "exit") {
            Variant result = scriptContext.evaluate(cmd);
            std::cout << result.toString() << std::endl;
        } else done = true;
    }

    // Exit application
    return 0;
}



Pressemitteilung erstellt von Willy Scheibel, 25. Oktober 2018.