⚙️ C-API / C-ABI, Conan, NPM & PIP Paketmanager
Dieses Kapitel beschreibt die plattformübergreifenden Schnittstellen und Paketmanager-Integrationen von MeinCMS (wissen-ahrensburg.de). Es erläutert die C-API / C-ABI Exporte des Parser-Crates, die Paketierung für C/C++ über Conan sowie Ubuntu Linux-Alternativen (APT, vcpkg, pkg-config, CMake, Ubuntu Security Portale), die verwendeten NPM-Pakete für Dokumentations-Builds sowie die Anbindung an das Python/PIP-Ökosystem.
1. C-API & C-ABI Interface (meincms_parser)
Das Subsystem meincms_parser bietet eine native C-ABI (Application Binary Interface)-Schnittstelle, die es erlaubt, den Hochleistungs-Parser in externen C-, C++- oder Fremdsprachen-Projekten (Python, PHP, Go, C#) einzubinden.
Configuration in Cargo.toml
Durch die Angabe von cdylib baut Cargo bei cargo build eine dynamische C-Bibliothek (libmeincms_parser.so unter Linux, .dylib unter macOS, .dll unter Windows):
[lib]
crate-type = ["cdylib", "rlib"]
Exportierte C-Funktionen (src/ffi.rs)
Alle exportierten Funktionen nutzen #[no_mangle] und unsafe extern "C" zur Einhaltung der Standard C-Aufrufkonvention.
| C-Funktion | Beschreibung | Rückgabe |
|---|---|---|
meincms_markdown_to_html(input: *const c_char) | Wandelt Markdown in HTML um | *mut c_char (String-Pointer) |
meincms_markdown_get_categories(input: *const c_char) | Extrahiert Kategorien aus Markdown als JSON-Array | *mut c_char (JSON String-Pointer) |
meincms_wikitext_to_html(input: *const c_char) | Wandelt MediaWiki/WikiText in HTML um | *mut c_char (String-Pointer) |
meincms_wikitext_get_categories(input: *const c_char) | Extrahiert Kategorien aus WikiText als JSON-Array | *mut c_char (JSON String-Pointer) |
meincms_free_string(ptr: *mut c_char) | Gibt vom Rust-Heap allokierten Speicher frei | void |
⚠️ Wichtiger Speicherhinweis: Rückgabewerte vom Typ
*mut c_charwerden von Rust allokiert und müssen in C/C++ nach Nutzung zwingend mitmeincms_free_string(ptr)freigegeben werden, um Speicherlecks zu vermeiden!
Header-Datei (meincms_parser.h) für C / C++
#ifndef MEINCMS_PARSER_H
#define MEINCMS_PARSER_H
#ifdef __cplusplus
extern "C" {
#endif
// Wandelt Markdown in HTML um
char* meincms_markdown_to_html(const char* input);
// Extrahiert Kategorien aus Markdown als JSON-String
char* meincms_markdown_get_categories(const char* input);
// Wandelt WikiText in HTML um
char* meincms_wikitext_to_html(const char* input);
// Extrahiert Kategorien aus WikiText als JSON-String
char* meincms_wikitext_get_categories(const char* input);
// Gibt CString Speicher auf dem Rust-Heap frei
void meincms_free_string(char* ptr);
#ifdef __cplusplus
}
#endif
#endif // MEINCMS_PARSER_H
C++ Verwendungsbeispiel
#include <iostream>
#include "meincms_parser.h"
int main() {
const char* markdown = "# Hallo Welt\nDies ist ein **Test** mit [[kategorie:Dokumentation]].";
// HTML konvertieren
char* html = meincms_markdown_to_html(markdown);
std::cout << "HTML Output: " << html << std::endl;
meincms_free_string(html); // Speichergabe
// Kategorien extrahieren
char* categories_json = meincms_markdown_get_categories(markdown);
std::cout << "Kategorien (JSON): " << categories_json << std::endl;
meincms_free_string(categories_json); // Speichergabe
return 0;
}
2. Conan Paketmanager & Ubuntu Linux Alternativen
2.1 Conan Paketmanager
Conan ist ein verbreiteter, plattformübergreifender C/C++ Paketmanager. Um meincms_parser als wiederverwendbares Paket in C/C++-Projekte (z. B. via CMake) einzubinden, kann ein conanfile.py verwendet werden.
Beispiel conanfile.py für meincms_parser
from conan import ConanFile
from conan.tools.files import copy
import os
class MeinCmsParserConan(ConanFile):
name = "meincms_parser"
version = "0.1.0"
license = "AGPL-3.0"
author = "Thorsten Klöhn"
url = "https://github.com/thorstenkloehn/wissen-ahrensburg.de"
description = "Rust-based Markdown & MediaWiki Parser C-FFI Library"
topics = ("markdown", "wikitext", "parser", "rust", "c-ffi")
settings = "os", "compiler", "build_type", "arch"
def build(self):
# Baut die Rust-Bibliothek via Cargo
self.run("cargo build --release -p meincms_parser")
def package(self):
# Kopiert C-Header und Binärdateien (.so / .dylib / .dll / .a)
copy(self, "meincms_parser.h", src=self.source_folder, dst=os.path.join(self.package_folder, "include"))
copy(self, "*.so", src=os.path.join(self.source_folder, "target", "release"), dst=os.path.join(self.package_folder, "lib"))
copy(self, "*.dylib", src=os.path.join(self.source_folder, "target", "release"), dst=os.path.join(self.package_folder, "lib"))
copy(self, "*.dll", src=os.path.join(self.source_folder, "target", "release"), dst=os.path.join(self.package_folder, "lib"))
def package_info(self):
self.cpp_info.libs = ["meincms_parser"]
Einbindung in C++ CMake-Projekten
cmake_minimum_required(VERSION 3.15)
project(MeinApp CXX)
find_package(meincms_parser REQUIRED)
add_executable(mein_app main.cpp)
target_link_libraries(mein_app PRIVATE meincms_parser::meincms_parser)
2.2 Alternativen zu Conan auf Linux Ubuntu
Falls Conan auf Ubuntu Linux nicht verwendet werden soll, stehen folgende professionelle Alternativen zur Verfügung:
1. Nativer Ubuntu System-Paketmanager (APT / .deb Paket via cargo-deb)
Unter Ubuntu kann aus dem Rust-Projekt direkt ein nativ installierbares Debian/Ubuntu-Paket (.deb) gebaut werden:
# Cargo DEB Tool installieren
cargo install cargo-deb
# .deb Paket für meincms_parser bauen
cargo deb -p meincms_parser
# Unter Ubuntu installieren
sudo dpkg -i target/debian/meincms_parser_0.1.0_amd64.deb
Dabei wird libmeincms_parser.so nach /usr/lib/ und meincms_parser.h nach /usr/include/ installiert. Jeder C/C++ Compiler unter Ubuntu (GCC/Clang) findet die Bibliothek nun systemweit ohne Konfiguration.
2. pkg-config Integration (meincms_parser.pc)
pkg-config ist der Standard auf Ubuntu Linux, um C/C++-Bibliothekspfade automatisch aufzulösen.
Erstelle die Datei /usr/lib/pkgconfig/meincms_parser.pc:
prefix=/usr
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include
Name: meincms_parser
Description: High-Performance Rust Markdown & MediaWiki Parser C-FFI
Version: 0.1.0
Libs: -L${libdir} -lmeincms_parser
Cflags: -I${includedir}
Kompilieren unter Ubuntu mit GCC / Clang:
gcc main.c $(pkg-config --cflags --libs meincms_parser) -o mein_programm
3. vcpkg (Microsoft C/C++ Package Manager for Linux/Ubuntu)
vcpkg ist eine weit verbreitete Conan-Alternative für Ubuntu Linux. Es lässt sich nahtlos in CMake integrieren:
# vcpkg unter Ubuntu installieren
git clone https://github.com/microsoft/vcpkg.git
./vcpkg/bootstrap-vcpkg.sh
# Einbinden in CMake
cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE=/pfad/zu/vcpkg/scripts/buildsystems/vcpkg.cmake
4. CMake ExternalProject / FetchContent (Ohne externen Paketmanager)
CMake kann unter Ubuntu direkt beim Konfigurieren den Rust Cargo Build anstoßen:
include(ExternalProject)
ExternalProject_Add(
meincms_parser_target
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/path/to/meincms_parser
BUILD_COMMAND cargo build --release
INSTALL_COMMAND ""
)
2.3 Ubuntu Security Portal & Prüfung einzelner C/C++ Pakete
Für die Verifizierung und Prüfung der Sicherheit einzelner C-Bibliotheken und Pakete unter Ubuntu stehen folgende offizielle Ressourcen und Werkzeuge bereit:
1. Offizielle Ubuntu Security Webseiten & CVE-Datenbanken
-
Ubuntu Security Notices (USN):
🔗 https://ubuntu.com/security/notices
Hier veröffentlicht Canonical alle offiziellen Sicherheits-Patches, Updates und Warnungen für einzelne C-Pakete und Systembibliotheken. -
Ubuntu CVE Tracker & Paketsuche:
🔗 https://ubuntu.com/security/cve
Ermöglicht die gezielte Suche nach Sicherheitslücken (CVEs) für einzelne C-Pakete (z. B.glibc,openssl,zlib,curl,libssl). -
Ubuntu Package Directory:
🔗 https://packages.ubuntu.com
Informationen zu allen Quell- und Binärpaketen und deren Zugehörigkeit zu Repositories (main,universe,security).
2. Befehle zur Sicherheitsprüfung auf lokalen Ubuntu-Systemen
# 1. Sicherheitsstatus von Ubuntu Pro & ESM (Security Patches) prüfen
pro status
# 2. Prüfen, aus welchem Security-Repository ein C-Paket bezogen wurde (z.B. noble-security)
apt-cache policy libssl3 libc6
# 3. Bekannte CVEs auf dem eigenen Ubuntu-System auswerten (benötigt debsecan)
sudo apt install debsecan
debsecan
3. Compiler-Härtung für C/C++ Pakete unter Ubuntu
Beim Kompilieren von C/C++ Anwendungen, die libmeincms_parser.so einbinden, sollten unter Ubuntu stets die offiziellen Canonical Hardening Flags verwendet werden:
gcc -O2 -fstack-protector-strong -D_FORTIFY_SOURCE=2 -fPIE -pie -Wl,-z,relro,-z,now main.c -lmeincms_parser -o main_app
3. NPM Paketmanager & Scripts
Für die Verwaltung, Generierung und Veröffentlichung der Handbuch-Dokumentation wird Node.js und npm eingesetzt.
package.json Übersicht
{
"name": "wissen-ahrensburg.de",
"version": "1.0.0",
"description": "Ein hochperformantes, mandantenfähiges (Multi-Tenancy) Wiki-CMS System, vollständig in Rust entwickelt.",
"directories": {
"doc": "docs"
},
"scripts": {
"build:docs": "node scripts/build_docs.js",
"ver": "npm run build:docs && npx -y gh-pages -d docs/book --nojekyll --cname handbuch.wissen-ahrensburg.de"
},
"dependencies": {
"github-pages": "^0.1.0"
}
}
Verwendete NPM Pakete
-
gh-pages:- Ein Utility-Paket zur automatischen Veröffentlichung des vom mdBook erzeugten HTML-Ordners (
docs/book) auf dengh-pages-Branch in GitHub. - Flag
--nojekyll: Deaktiviert Jekyll-Processing auf GitHub Pages für korrekte Auslieferung aller Unterordner. - Flag
--cname handbuch.wissen-ahrensburg.de: Setzt automatisch die Custom-Domain der Dokumentation.
- Ein Utility-Paket zur automatischen Veröffentlichung des vom mdBook erzeugten HTML-Ordners (
-
github-pages:- Unterstützendes Abhängigkeitspaket für GitHub-Pages Hilfsklassen und Konfiguration.
4. Python & PIP Ökosystem (Python FFI Bindings & PIP Paketierung)
Neben C und C++ kann der meincms_parser auch direkt in Python mittels des Standard-Moduls ctypes oder über ein mit pip installierbares Python-Paket eingebunden werden.
Einbindung in Python mit ctypes
Da meincms_parser eine C-ABI dynamische Bibliothek erzeugt (libmeincms_parser.so), kann Python sie ohne zusätzliche C-Extensions laden:
import ctypes
import json
import os
# Pfad zur kompilierten Shared Library (.so / .dylib / .dll)
lib_path = os.path.abspath("target/release/libmeincms_parser.so")
lib = ctypes.CDLL(lib_path)
# Signaturen definieren
lib.meincms_markdown_to_html.argtypes = [ctypes.c_char_p]
lib.meincms_markdown_to_html.restype = ctypes.c_char_p
lib.meincms_markdown_get_categories.argtypes = [ctypes.c_char_p]
lib.meincms_markdown_get_categories.restype = ctypes.c_char_p
lib.meincms_free_string.argtypes = [ctypes.c_char_p]
lib.meincms_free_string.restype = None
def render_markdown(text: str) -> str:
encoded = text.encode("utf-8")
raw_ptr = lib.meincms_markdown_to_html(encoded)
result = ctypes.cast(raw_ptr, ctypes.c_char_p).value.decode("utf-8")
lib.meincms_free_string(raw_ptr) # Speichergabe
return result
def get_categories(text: str) -> list:
encoded = text.encode("utf-8")
raw_ptr = lib.meincms_markdown_get_categories(encoded)
result_json = ctypes.cast(raw_ptr, ctypes.c_char_p).value.decode("utf-8")
lib.meincms_free_string(raw_ptr) # Speichergabe
return json.loads(result_json)
if __name__ == "__main__":
sample = "# Hallo aus Python\nInhalt mit [[kategorie:PythonTest]]."
print("HTML:", render_markdown(sample))
print("Kategorien:", get_categories(sample))
Python-Paketierung (pyproject.toml / pip install)
Um den Parser als pip-Paket zu verteilen, kann ein pyproject.toml in Kombination mit setuptools oder maturin (für native Rust-Python Bindings) genutzt werden:
[build-system]
requires = ["setuptools>=61.0", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "meincms_parser"
version = "0.1.0"
description = "Python Bindings for MeinCMS Rust Markdown & MediaWiki Parser"
authors = [{ name = "Thorsten Klöhn" }]
license = { text = "AGPL-3.0" }
dependencies = []
PIP Installation & Verwendung
- Installation im Entwicklungsmodus:
pip install -e . - Erstellen von Distribution-Wheels:
pip wheel .