4.9 KiB
Code Generator (logos-cpp-generator)
Overview
logos-cpp-generator bridges pure C++ module implementations to the Logos runtime's Qt plugin system. Module authors write standard C++ and the generator produces all Qt boilerplate automatically.
The --from-header Pipeline
This is the primary mode for universal modules:
C++ impl header (your code)
│
▼
parseImplHeader() — extracts public methods, maps C++ types to LIDL types
│
▼
ModuleDecl (internal AST)
│
├──► <name>_qt_glue.h — Plugin class + ProviderObject with typed wrappers
│
└──► <name>_dispatch.cpp — callMethod() dispatch + getMethods() metadata
Command
logos-cpp-generator --from-header src/<name>_impl.h \
--backend qt \
--impl-class <ImplClassName> \
--impl-header <name>_impl.h \
--metadata metadata.json \
--output-dir ./generated_code
| Flag | Description |
|---|---|
--from-header <path> |
Path to the pure C++ impl header |
--backend qt |
Generate Qt plugin glue (currently the only backend) |
--impl-class <name> |
Name of the C++ implementation class (PascalCase + Impl) |
--impl-header <name> |
Header filename (for include directives in generated code) |
--metadata <path> |
Path to metadata.json (provides name, version, description) |
--output-dir <path> |
Directory for generated files |
Generated Files
<name>_qt_glue.h — Contains two classes:
- ProviderObject — Inherits
LogosProviderBase. Holdsm_impl(your impl class). Each public method gets a typed wrapper that converts Qt params to C++ std params, callsm_impl.method(...), and converts the return value back. ForLogosMap/LogosListreturns, annlohmannToQVariant()helper handles the conversion. If the impl declares a publicemitEventcallback, the constructor wires it toLogosProviderBase::emitEvent. - Plugin —
QObjectsubclass withQ_PLUGIN_METADATAandQ_INTERFACES. Factory methodcreateProviderObject()returns a new ProviderObject.
<name>_dispatch.cpp — Implements two methods on the ProviderObject:
callMethod(methodName, args)— String-based dispatch table mapping method names to typed callsgetMethods()— ReturnsQJsonArrayof method metadata (name, signature, returnType, parameters)
Type Mapping Table
| C++ type | LIDL type | Qt mapping |
|---|---|---|
std::string / const std::string& |
tstr |
QString |
bool |
bool |
bool |
int64_t |
int |
int |
uint64_t |
uint |
int |
double |
float64 |
double |
void |
void |
void |
std::vector<std::string> |
[tstr] |
QStringList |
std::vector<uint8_t> |
bstr |
QByteArray |
std::vector<int64_t> |
[int] |
QVariantList |
LogosMap |
{tstr: any} |
QVariantMap |
LogosList |
[any] |
QVariantList |
| Anything else | any |
QVariant |
LogosMap and LogosList (from <logos_json.h>) are nlohmann::json aliases for returning structured data without Qt. The generator sets a jsonReturn flag on these methods and emits an nlohmannToQVariant() conversion in the glue layer.
LIDL (Alternative Input Format)
LIDL is a lightweight Interface Definition Language. Instead of parsing a C++ header, you write a .lidl file:
module crypto_utils {
version "1.0.0"
description "Cryptographic utilities"
method hash(input: tstr) -> tstr
method verify(input: tstr, hash: tstr) -> bool
method generateKey(bits: int) -> tstr
method listAlgorithms() -> [tstr]
}
Both paths (C++ header and LIDL) produce identical generated output. Use --from-header for most modules; use LIDL when you want to define the interface before writing the implementation.
Common Issues
- Unknown type warning: If the generator encounters a C++ type not in the mapping table, it maps to
any(QVariant). Prefer explicit types from the table. - Class not found:
--impl-classmust exactly match the class name in the header (case-sensitive). - metadata.json mismatch: The
namein metadata.json must match the expected plugin binary name. - Generated files not found by CMake: Ensure
generated_code/files are listed inCMakeLists.txtSOURCES and the directory is in INCLUDE_DIRS.
In CMakeLists.txt
logos_module(
NAME my_module
SOURCES
src/my_module_impl.h
src/my_module_impl.cpp
generated_code/my_module_qt_glue.h
generated_code/my_module_dispatch.cpp
INCLUDE_DIRS
${CMAKE_CURRENT_SOURCE_DIR}/generated_code
)
In flake.nix
The generator runs in preConfigure, before CMake:
preConfigure = ''
logos-cpp-generator --from-header src/my_module_impl.h \
--backend qt --impl-class MyModuleImpl \
--impl-header my_module_impl.h \
--metadata metadata.json --output-dir ./generated_code
'';