Neu vorgestellt, Programmierung

CONZEPT 16 C++-Schnittstelle

CONZEPT 16 bietet mit der DLL-Schnittstelle und der externen Programmierschnittstelle bereits Möglichkeiten um CONZEPT 16-Anwendungen teilweise oder sogar komplett in anderen Programmiersprachen umzusetzen. Diese Schnittstellen stehen in der Programmiersprache C zur Verfügung. Diese Sprache hat den Vorteil, dass es aufgrund ihrer Einfachheit für so gut wie jede Plattform einen entsprechenden Compiler gibt. Diese Einfachheit stellt zugleich aber auch ihre Limitiertheit dar: Sie ist nicht objektorientiert. Dieser Artikel stellt eine neue, alternative Schnittstelle in der Programmiersprache C++ vor, die nicht nur von der Objektorientierung der Sprache profitiert.

Wir befinden uns in den letzten Zügen der Entwicklung der C++-Schnittstelle und freuen uns, diese hier vorzustellen. Gerne laden wir Sie dazu ein, uns über die Kommentarfunktion Ihre Meinung, Vorschläge, Fragen oder Kritikpunkte zu diesem neuen Projekt mitzuteilen.

Einleitung

Mit der C++-Schnittstelle können sowohl ergänzende Erweiterungen als auch eigenständige Applikationen mit der Programmiersprache C++ realisiert werden: Eine Erweiterung ergänzt die Prozeduren einer bestehenden CONZEPT 16-Anwendung um Funktionen, die in eine dynamische Bibliothek (unter Windows: DLL) ausgelagert werden. Eine Applikation stellt eine eigenständige Anwendung dar, die auch ohne den Aufruf von Prozeduren auf Datenbanken zugreifen kann.

Die Schnittstelle setzt dabei auf etablierte Konzepte der C++-Programmierung:

  • Ausnahmen (Exceptions) zur Signalisierung von Fehlerzuständen
  • Iteratoren zur Schleifenverarbeitung
  • Datenströme (Streams) zur Ein- und Ausgabe
  • Klassen- und Funktionsvorlagen (Templates) zur Umsetzung gleichartiger Klassen bzw. Funktionen

Alle Elemente der C++-Schnittstelle sind in einer englischsprachigen Dokumentation beschrieben, bestehend aus mehreren HTML-Seiten (Startseite: index.html). Sie steht am Ende dieses Artikels zum Download zur Verfügung. Sie enthält außerdem auf das Wesentliche beschränkte Beispiele zur Nutzung erklärungsbedürftiger Funktionen, die ein schnelles Verständnis der betroffenen Typen und Funktionen vermitteln sollen.

Sämtliche Typen (Klassen, Aufzählungen usw.) der C++-Schnittstelle sind im Namensraum C16 untergebracht. Einige weitere Typen sind in untergeordneten Namensräumen organisiert.

Datentypen

Der Namensraum C16::Value enthält alle Datentypen, die mit der C++-Schnittstelle verarbeitet werden können.

Folgende Typen sind dabei als Aliasse fundamentaler und standardisierter C++-Basistypen umgesetzt:

CONZEPT 16-TypC++-Typ (Alias)C++-BasistypC++-Standard-Header
alphaC16::Value::Alphastd::string<string>
logicC16::Value::Logicbool-
byte, int8C16::Value::Bytestd::uint8_t<cstdint>
word, int16C16::Value::Wordstd::uint16_t<cstdint>
int, long, int32C16::Value::Intstd::int32_t<cstdint>
bigint, int64C16::Value::Bigintstd::int64_t<cstdint>
floatC16::Value::Floatdouble-

Weitere unterstützte Typen, die nicht auf C++-Basistypen basieren:

CONZEPT 16-TypC++-Typ
dateC16::Value::Date
timeC16::Value::Time

Klassen

Die wohl wichtigste Klasse der C++-Schnittstelle ist C16::Database. Sie ist Ausgangspunkt für alle Operationen, die in Zusammenhang mit einer Datenbank stehen. Sie enthält beispielsweise Funktionen zum Ermitteln von Namen, Version und Status der Datenbank. Darüber hinaus stellt sie Funktionen zur Ermittlung von Datenstrukturelementen wie Tabellen, Teildatensätzen und Feldern zur Verfügung.

Außerdem gibt es Klassen zum Zugriff auf Datenbankinhalte, wie Datensätze, Texte, Prozeduren, Selektionen und binäre Objekte.

Weitere erwähnenswerte Klassen sind C16::Array<Element> und C16::Variant: Die Klasse C16::Array stellt eine Folge fester Größe vom Typ Element dar. Die Elemente des Arrays können verändert werden, aber es können keine Elemente gelöscht oder hinzugefügt werden. Die Klasse C16::Variant kapselt eine von mehreren möglichen alternativen Inhalten. Sie kommt zum Einsatz, wenn der Typ eines Elements variabel ist, wie zum Beispiel bei Argumenten für Prozeduren.

Beispiele

Nachfolgend soll je ein Beispiel für eine Erweiterung und eine Applikation die Verwendung der C++-Schnittstelle illustrieren.

Erweiterung

Mit der Funktion DllCall() wird aus einer Prozedur die Einstiegsfunktion der Erweiterung aufgerufen. Die Einstiegsfunktion namens C16_Entry() hat die folgende Signatur:

C16::Value::Int C16_Entry
(
C16::Database& database,
C16::Array<C16::Variant>& arguments
)

Als Argumente werden ihr die aufrufende Datenbank (C16::Database) und eventuell mitgelieferte Argumente (C16::Array<C16::Variant>) übergeben. Als Rückgabe liefert sie eine Ganzzahl (C16::Value::Int), die als Rückgabe von DllCall() ausgewertet werden kann.

Beispiel für eine CONZEPT 16-Prozedur zum Ordnen von Array-Elementen:

@A+
@C+

define
{
// Elemente sortieren

sCommandSort : 1
// Elemente mischen

sCommandShuffle : 2
}

global Data
{
gDll : handle;
}

sub Init
{
VarAllocate(Data);
// Erweiterung laden

gDll # DllLoad('ArraySort.dll');
}

sub Term
{
// Erweiterung entladen

gDll->DllUnload();
VarFree(Data);
}

sub Sort
(
var vArray : alpha[];
)
{
// Erweiterung aufrufen

gDll->DllCall(sCommandSort, var vArray);
}

sub Shuffle
(
var vArray : alpha[];
)
{
// Erweiterung aufrufen

gDll->DllCall(sCommandShuffle, var vArray);
}

Beispiel für eine C++-Erweiterung zum Ordnen von Array-Elementen:

#include "C16/LibraryExtension.hpp" // Alle Typen der C++-Schnittstelle für Erweiterungen
#include <algorithm> // std::sort
#include <random> // std::default_random_engine

using namespace C16;

namespace Command
{
static const Value::Int SORT = 1;
static const Value::Int SHUFFLE = 2;
}


Value::Int C16_Entry
(
Database& database,
Array<Variant>& arguments
)
{
// 1. Argument als Int erwarten
Value::Int command = arguments[0];
// 2. Argument als Array von Zeichenketten erwarten
Array<Value::Alpha>& data = arguments[1];

switch (command)
{
// Array sortieren
case Command::SORT :
{
std::sort(data.begin(), data.end());
break;
}
// Array mischen
case Command::SHUFFLE :
{
std::shuffle
(
data.begin(), data.end(),
std::default_random_engine(std::random_device()())
);
break;
}
}

return 0;
}

Applikation

Damit die Applikation auf eine Datenbank zugreifen kann, benötigt sie ein Objekt der Klasse C16::Client, um auf einen Server, der Datenbanken verwaltet, zugreifen zu können.

Beispiel für eine C++-Konsolenapplikation zum Zählen aller Datensätze mit geradem Feldwert:

#include "C16/LibraryApplication.hpp" // Alle Typen der C++-Schnittstelle für Applikationen
#include <iostream> // std::cout

using namespace C16;

int main()
{
// Client erzeugen
Client client;

// Datenbankverbindung herstellen
Database database
(
client,
"my_server", "my_database", "my_user"
);


// Tabelle ermitteln
const Table& table =
database.tables().get("my_table");


// Datensatzmenge sortiert nach 1. Schlüssel erzeugen
RecordsKey records(table, 1);

// Datensatzpuffer ermitteln
const Record& record =
records.record();

// Feldpuffer erzeugen
const Record::FieldConstInt field =
record.field_int("my_field");

// Zähler definieren
int count = 0;

// Datensätze iterieren
for
(
Result result = records.read(Place::FIRST);
result < Result::NO_REC;
result = records.read(Place::NEXT)
)
{
// Feldwert gerade
if (field % 2 == 0)
// Zähler inkrementieren
++count;
}

// Zähler auf Konsole ausgeben
std::cout << count << std::endl;
}

Fazit

Mit der C++-Schnittstelle steht eine weitere Option der Interoperabilität von CONZEPT 16 mit anderen Programmiersprachen zur Verfügung. Die Objektorientierung und weitere Konzepte von C++ erleichtern die Entwicklung moderner Programme.

Aktuell arbeiten wir an den letzten Feinheiten der C++-Schnittstelle und bieten Ihnen hiermit Gelegenheit Einfluss auf die Entwicklung der C++-Schnittstelle zu nehmen. Zu einem späteren Zeitpunkt werden wir Sie über die finale Freigabe informieren.

CONZEPT 16 C++ API – Documentation

3 Kommentare

3 Kommentare “CONZEPT 16 C++-Schnittstelle”

  1. Finde ich gut, wobei die bestehende Schnittstelle auch bereits ok ist.

    Wo liegen denn die wichtigsten Unterschiede zwischen den Schnittstellen? Wird der Befehlssatz der neuen Schnittstelle grösser sein, bequemer sein oder so als der in der bestehenden? Wird die neue Schnittstelle anders als die alte thread-sicher sein? Oder geht es tatsächlich hauptsächlich darum, die C-Schnittstelle durch eine C++-Schnittstelle zu ersetzen?

    Ansonsten würde mich noch interessieren, welche Compiler man bei der neuen Schnittstelle einsetzen können soll. Beim Einsatz von mingw/gcc in der C-Schnittstelle für externe Programme hatte ich Probleme, wohingegen das Erstellen von DLLs bisher immer funktioniert hat, auch mit mingw/gcc. Wie wird das mit der neuen Schnittstelle sein?

    1. Danke für Deine Fragen.

      Die Vorteile der C++-Schnittstelle gegenüber den C-Schnittstellen abseits der Vorteile von C++ gegenüber C sind die folgenden:

      – Größere Robustheit durch Typisierung: In den C-Schnittstellen wird an einigen Stellen mit void-Zeigern gearbeitet. Dort kann zur Laufzeit keine Überprüfung des Typs stattfinden. In der C++-Schnittstelle werden polymorphe Objekte verwendet, an Stellen mit Argumenten oder Rückgabewerten variablen Typs.

      – Vereinheitlichung: In den C-Schnittstellen wird für die Programmierschnittstelle und die DLL-Schnittstelle jeweils ein eigener, wenn auch namentlich identischer, Funktionssatz benötigt. Das verhindert, dass Anwender den selben Code für beide Schnittstellen nutzen können. Mit der C++-Schnittstelle kann für Applikationen und Erweiterungen derselbe Code verwendet werden.

      – Vereinfachung: Die C++-Schnittstelle zielt auf eine deutlich komfortablere Nutzung ab, als sie die C-Schnittstellen bieten.

      Zur Thread-Sicherheit: Die C++-Schnittstelle ist aktuell nicht auf Thread-Sicherheit ausgelegt. Bei Bedarf würden wir diese Anforderung genauer untersuchen.

      Zu Compilern: Wir planen, die C++-Schnittstelle als statische Bibliothek bereit zu stellen, die von Microsoft Visual Studio ab Version 2015 eingebunden werden kann.

  2. Danke für die Antworten.

    Dann würde ich mal sagen: Ich finde das Vorhaben/Projekt gut. Ich werde die neue Schnittstelle wenn sie dann verfügbar ist, gern mal testen.

    Wenn die beiden Punkte:
    1) Schnittstelle ist thread-safe
    2) neben Visual C++ werden andere Compiler wie gcc offiziell unterstützt
    umgesetzt werden würden, wäre das für mich ein recht starker Grund, die neue statt der alten Schnittstelle zu nutzen.

Kommentar abgeben