mirror of
https://github.com/logos-co/logos-cpp-sdk.git
synced 2026-08-31 09:41:06 +00:00
fix/integral-float-accept
8
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
182d850e72 |
docs: update project.md for the logos-lidl frontend split (#90)
The embedded LIDL frontend (lidl_ast/lexer/parser/serializer/validator) was deleted — it now lives in the logos-lidl repo, linked via find_package and bridged onto the Qt backends by experimental/lidl_compat.h. Update the project doc to match: describe the consumed logos-lidl frontend + the compat shim, list the backends cpp-generator actually keeps (lidl_emit_common, lidl_gen_client, lidl_gen_cdylib, impl_header_parser), drop the deleted frontend files and their (removed) tests, and note the qt provider glue lives in logos-qt-generator and the Rust backend in logos-rust-sdk. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
87abcd8044 |
Cdylib authoring: --backend cdylib emits the common C ABI wrapper + uniform Qt glue (#84)
* Extract the protocol layer into logos-protocol; consume it as a flake input
The transport/token/IPC layer (transports incl. QRO + plain TCP/TLS,
consumer core LogosAPIClient/LogosAPIConsumer with the capability
auto-requestModule flow, ModuleProxy, token manager, QVariant<->JSON
conversion, the abstract LogosProviderObject interface) now lives in the
logos-protocol repo behind the versioned lp_* C ABI.
This SDK keeps the typed C++ developer layer (LogosAPI, provider base
classes + Qt provider glue, module context, code generator) and still
compiles the protocol sources INTO liblogos_sdk.a from the flake input,
so the installed artifact (archive symbols, include/ + include/cpp
layouts, cmake config) stays byte-compatible: existing consumers need
no changes. Public headers are unchanged; logos_provider_object.h keeps
its name and now re-exports the abstract interface from
logos_provider_interface.h.
Transport/protocol component tests moved to logos-protocol with the
code; the remaining sdk/generator/experimental suites are unchanged
(432/432 green against the local protocol checkout).
* lock: add logos-protocol input
* Make the base SDK Qt-free: move the Qt developer layer to logos-qt-sdk
LogosAPI, LogosAPIProvider, LogosProviderBase/LOGOS_PROVIDER macros, the
QObject provider glue (QtProviderObject) and the legacy PluginInterface
(core/interface.h) move to the new logos-qt-sdk repo. The protocol
sources are no longer compiled into a monolithic archive — consumers
link logos-qt-sdk (which layers on logos-protocol) instead.
What remains here is header-only std C++: logos_module_context.h,
logos_result.h (StdLogosResult), logos_json.h — exported as the CMake
INTERFACE target logos-cpp-sdk::logos_headers — plus the code generator
(a build-time tool; its introspection mode now includes
logos_provider_interface.h from logos-protocol, where
LogosProviderPlugin moved).
Mechanically verified Qt-free: the logos-cpp-lib / logos-cpp-include
closures contain only nlohmann_json. Tests: 245/245 (module-context std
suite + generator + experimental).
* Cdylib authoring backend: --backend cdylib emits the common C ABI wrapper + uniform Qt glue
From a module's LIDL contract the generator now emits:
- <name>_module_impl.cpp — the Qt-FREE logos_module_impl.h export
wrapper (dispatch/get_methods/set_context/set_emit_callback/
accept_token/get_protocol_version/string_free) around the universal
impl class; compiled into the module's cdylib. Tagged {"_bytes"}
bytes, StdLogosResult -> {success,value,error}, context via the
existing _logos_codegen_::maybeSet* SFINAE helpers.
- <name>_events_cdylib.cpp — typed logos_events: bodies marshalling
into nlohmann::json (the cdylib flavor of the events sidecar).
- <name>_cdylib_glue.{h,cpp} — the UNIFORM Qt-plugin glue forwarding
LogosProviderObject to the C symbols; identical regardless of the
module's source language (the Rust SDK emits the same exports).
- the .lidl sidecar.
Qt-container types are rejected at generation time (a cdylib impl is
Qt-free by definition). Verified end-to-end by dlopen smoke: typed
dispatch, typed events through the emit callback, result returns,
introspection, and the protocol-version handshake — and the SAME C
harness passes against a Rust cdylib generated by logos-lidl-gen
--provider.
* fix: accept the installed source-export layout in the protocol-root check
The fail-fast only tested <root>/cpp/logos_protocol.h, but the LP_SRC
selection right below (and the error message itself) support the
installed export layout <root>/include/cpp as well. Pointing
LOGOS_PROTOCOL_ROOT at an installed export tripped the FATAL_ERROR
before that fallback could apply.
Caught by Copilot review on #82.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* lock: pin logos-protocol to the qt-free-split branch head
The Qt-free SDK (and the cdylib backend stacked on it) reference
LogosProviderPlugin from protocol's logos_provider_interface.h, which
lands on feat/qt-free-split — the P1-branch pin no longer compiles
standalone. Temporary — drop when the chain PRs merge.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* lock: pin logos-protocol to the qt-free-split branch head
The Qt-free SDK (and the cdylib backend stacked on it) reference
LogosProviderPlugin from protocol's logos_provider_interface.h, which
lands on feat/qt-free-split — the P1-branch pin no longer compiles
standalone. Temporary — drop when the chain PRs merge.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* doctest: pin the logoscore runtime via its {release} placeholder
The spec built logoscore-cli at bare master with only the cpp-sdk inputs
overridden — master's stack cannot compile against the qt-free SDK, so
the suite failed on the chain branches. With the placeholder, CI's
--release-for pins expand it to the workspace's logoscore commit (and
local runs without a pin still fall back to master, unchanged).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* doctest: override the nested module builders to {release} too
capability_module (via logoscore's lock) and the cloned accounts module
resolve module-builder from their own locks — pre-split revs whose
LogosModule.cmake still detects the SDK by logos_api.h, which the
qt-free SDK no longer ships ('logos-cpp-sdk not found'). Overriding the
builder itself to the workspace-pinned chain rev (keeping the nested
cpp-sdk override) builds both modules with the split-aware builder.
Verified end-to-end locally with the exact doctest command.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* doctest: apply the {release} + nested-builder overrides to all three specs
The runtime spec got the treatment in 210eea1; the composition and
worker-thread specs have the same logoscore/module build commands and
failed identically (pre-split builders from the modules' own locks).
All executed run: blocks now pin logoscore-cli{release} and override
the nested module builders to logos-module-builder{release}; the
displayed code_block: variants stay in their generic master form.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* generator: glue-only cdylib mode for non-C++ impls
--lidl x.lidl --backend cdylib (no --impl-class) emits just the uniform
Qt-plugin glue; the C exports come from the module's own language
backend (e.g. the Rust SDK's lidl-gen --provider). This is the entry
point logos-module-builder's cdylib interface uses for Rust modules.
* cdylib glue: root plugin implements PluginInterface
logos_host's module_initializer hard-requires PluginInterface on the
root plugin before any provider detection — same bases as the qt glue
(QObject, PluginInterface, LogosProviderPlugin). Caught by the first
host-loaded run of a cdylib-authored module; the dlopen smoke harness
exercised only the C seam.
* cdylib glue: seed the cdylib's protocol stack with the host auth token
The glue's init() reads the authToken property module_initializer now
surfaces on the LogosAPI object and forwards it across
logos_module_accept_token under the initializer's own keys
(core / capability_module). Without it the cdylib's TokenManager (a
separate static copy of the singleton) is empty and every outbound
call — including the capability requestModule bootstrap — is rejected
as unauthorized.
* cdylib glue: provider derives LogosProviderBase; tokens land in BOTH stacks
informModuleToken = base save (host-stack TokenManager — what ModuleProxy
validates inbound calls against, incl. the grant the daemon pushes after
a capability requestModule) + C-ABI forward (the cdylib's own stack, for
outbound auth). init folds into onInit; the authToken property seeding
stays.
* lock: protocol integer-fidelity fix
* codegen: typed wrappers throw on call failure; dispatch catches escapes
Generated sync client wrappers call the new err-out invokeRemoteMethod
overload and throw logos::LogosCallError when the call fails (e.g. the
bound module is missing) — previously the empty QVariant silently
degraded to the return type's default and a caller could not tell
failure from a legitimate 0 / "". Both generators (legacy + LIDL),
both API styles. Async paths unchanged.
Generated provider dispatch (universal qt glue + LOGOS_PROVIDER) wraps
the method body in a catch-all that logs and returns an invalid QVariant
— an escaped exception becomes an ordinary METHOD_FAILED instead of
unwinding through Qt event dispatch and killing the module process.
* fix: restore a clean flake.lock after the merge conflict (protocol 176fbc8)
* codegen: CallError out-param instead of throwing wrappers
Per review, the generated sync wrappers expose the error channel as an
optional trailing parameter — add(a, b, &err) — rather than throwing:
explicit, stateless, works on temporaries, and existing call sites
compile unchanged (they keep default-on-failure, now with a qWarning so
failures are visible in the module log). The dispatch catch-all from the
previous commit stays: it contains author exceptions, it doesn't
introduce any.
* generator: contract-first C++ cdylib modules from --lidl
--lidl x.lidl --backend cdylib with --impl-class/--impl-header now emits
the FULL set (C-ABI export wrapper + events + uniform glue) around the
named hand-written Qt-free impl class — the C++ mirror of declaring the
contract in .lidl and implementing the Rust trait. Without --impl-class
the glue-only mode is unchanged.
* glue: fire onContextReady AFTER modules()/event wiring
The generated onInit set the context (which fires the impl's
onContextReady hook) before constructing the LogosModules aggregate and
wiring typed event emission — so an impl doing its documented one-time
setup there (typed dependency calls, event subscriptions) dereferenced
a null aggregate and crashed the module process (signal 11). Found by
the first module to subscribe to a dependency's typed event from
onContextReady. Context now goes last.
* cdylib: fire the context-ready hook at module LOAD, not first dispatch
The impl-exports wrapper used to fire maybeSetContext (stamp + hook)
immediately inside logos_module_set_context — which the glue calls during
onInit, BEFORE the auth token is seeded and BEFORE ModuleProxy wires the
emit callback. A hook that made outbound calls or emitted events ran
half-wired; and the Rust scaffold deferred its hook to first dispatch
entirely, so a Rust module couldn't subscribe/emit/act until someone
called it — a capability gap vs the universal C++ path.
Two changes, applied uniformly:
- The glue's onInit now seeds the auth token FIRST and forwards the
context LAST (the same context-last convention as the universal onInit
ordering fix).
- The impl-exports gained a ready-latch (lidlTryFireContext): the context
is stored on set_context and the hook fires ONCE as soon as both the
context AND the emit callback have been delivered — during module
registration, before the module is published for inbound calls. Hosts
that never wire an emit callback still get the hook before the first
dispatch (requireEmit=false fallback in logos_module_dispatch).
The Rust scaffold (logos-rust-sdk lidl-gen) implements the same latch, so
on_context_ready now matches C++ onContextReady semantics: subscriptions,
authenticated outbound calls and typed emission all work from the hook at
load time.
* ci: run workflows on stacked PRs + workflow_dispatch
Both workflows filtered pull_request to master-based PRs, so stacked PRs
(feat/qt-free-sdk -> feat/extract-logos-protocol, feat/cdylib-authoring
-> feat/qt-free-sdk) ran NO checks at all. Drop the base-branch filter
for pull_request and add workflow_dispatch for manual runs. Same fix as
logos-module-builder 232b8a2.
* generator: --backend ui — universal authoring for UI plugin backends
New emitters (lidl_gen_ui.{h,cpp}) for type=ui_qml + interface=universal
modules: from the author's single clean impl class (optionally deriving
LogosModuleContext), generate
<name>.rep — the view contract, one SLOT per public method
(framework hooks like onContextReady excluded)
<name>_ui_interface.h — PluginInterface subclass + IID
<name>_ui_glue.{h,cpp}— plugin deriving <Cls>SimpleSource +
<Cls>Interface + <Cls>ViewPluginBase; slots
forward to the impl (std<->Qt at the boundary);
Q_INVOKABLE initLogos(LogosAPI*) builds
LogosModules, wires modules(), stamps context
(fires onContextReady — same order as the
universal core glue), then setBackend(this).
Typed dependency callers, typed event subscriptions and bind_<interface>
binders come from the existing umbrella pass (logos_sdk.h), which already
runs for UI modules. ui-host's reflection-based initLogos call site is
unchanged; legacy LogosAPI*-based UI plugins are untouched. v1 view API
types: void/int/uint/float64/bool/string; logos_events: rejected for ui
backends (views talk to QML via .rep, not module events).
* generator: distribute the LIDL frontend for external generators
First step of moving ALL Qt glue emission out of this repo into
logos-qt-sdk's logos-qt-generator (cpp-sdk's generator keeps only the
Qt-free outputs: std typed wrappers, logos_sdk umbrella, cdylib
impl-exports, LIDL derivation).
- Shared emit helpers (lidlToPascalCase, lidlTypeToQt, lidlTypeToStd,
lidlIsStdConvertible) move to a new lidl_emit_common.{h,cpp} unit, used
by both generators.
- The frontend set (AST, lexer, parser, serializer, validator,
impl-header parser, emit-common) is installed under
share/lidl-frontend/ — the qt generator compiles these sources in
directly, so the two tools share one frontend without a binary ABI.
* generator: Qt glue emission removed — logos-qt-generator owns it
The deletion half of the generator split (counterpart: logos-qt-sdk
3b37474, builder d7a2272). This tool now emits ONLY Qt-free outputs:
kept std typed wrappers + logos_sdk umbrella (--general-only),
cdylib C-ABI impl-exports + typed event emitters
(--lidl/--from-header --backend cdylib --impl-class),
LIDL derivation/serialization (--header-to-lidl), client stubs
removed universal Qt glue (--backend qt), the uniform cdylib Qt glue,
the ui backend emitters — all relocated verbatim (byte-identical
output verified) to logos-qt-generator; invocations here now
fail with a pointer to the right tool
The provider-glue golden tests travel with the emitters (to be re-homed
in logos-qt-sdk's test suite); test_lidl_type_mapping stays — it covers
lidl_emit_common, which both generators compile.
* lock: protocol at the typed-requestModule port (3de5398)
* lock: protocol at the typed-requestModule port (3de5398)
* ci: chain pins for the doc-tests (drop at merge)
In repo CI only cpp-sdk's {release} is the commit under test —
logoscore-cli and module-builder expanded to master, which doesn't link
against the chain SDK the specs override in ('Build the CLI with the SDK
override' failed on every run since the stacked-PR triggers were
enabled). Pin both to the extraction-chain heads; the workspace pipeline
is unaffected (it pins every repo itself).
* generator: distribute the LIDL frontend for external generators
First step of moving ALL Qt glue emission out of this repo into
logos-qt-sdk's logos-qt-generator (cpp-sdk's generator keeps only the
Qt-free outputs: std typed wrappers, logos_sdk umbrella, cdylib
impl-exports, LIDL derivation).
- Shared emit helpers (lidlToPascalCase, lidlTypeToQt, lidlTypeToStd,
lidlIsStdConvertible) move to a new lidl_emit_common.{h,cpp} unit, used
by both generators.
- The frontend set (AST, lexer, parser, serializer, validator,
impl-header parser, emit-common) is installed under
share/lidl-frontend/ — the qt generator compiles these sources in
directly, so the two tools share one frontend without a binary ABI.
* docs: note the generator split (Qt glue emission lives in logos-qt-sdk)
* lock: protocol#3 merged — pin advances to protocol master
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||
|
|
7b62ac2017 |
Per-event documentation + getPluginEvents introspection (#71)
* Add per-event documentation + getPluginEvents introspection Mirror the per-method documentation pipeline for events. Events (declared in a universal module's logos_events: section) now carry a description parsed from their /// doc comments, and are introspectable at runtime via a new getPluginEvents framework call. - lidl_ast: EventDecl gains a description field. - impl_header_parser: capture the event's doc comment (previously discarded) and an optional metadata.json events[].description. - lidl_gen_provider: generated universal provider emits getEvents() override, mirroring getMethods() (name/signature/ parameters/description; no returnType/isInvokable — events are void). - logos_provider_object: default-empty virtual getEvents() so the legacy provider path and QtProviderObject inherit empty. - module_proxy / qt_provider_object: intercept getPluginEvents next to the getPluginMethods special-case. - docs: spec + README event-documentation notes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Add unit tests for event documentation + getEvents generation Address review feedback (#71): cover the event-introspection paths that previously only had method-side tests. - impl_header_parser test: assert metadata.json events[].description is parsed; new documented_events fixture asserts `///` doc-comment capture on a logos_events: block (multi-line joined with \n, adjacent-only, plain // ignored). - lidl_gen_provider test: assert the generated dispatch contains getEvents() emitting each event's name/signature/parameters and an escaped description, and that events carry no returnType/isInvokable. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Fold event introspection into getMethods() to keep the provider ABI stable The previous approach added a getEvents() virtual to LogosProviderObject, which inserted a new vtable slot and shifted every later slot — an ABI break that would misdispatch virtual calls whenever an old and new host/module were mixed across the in-process plugin boundary. Instead, report events INSIDE the existing getMethods() call: it now returns the module's whole interface, with each entry tagged type "method" or "event" (events omit returnType/isInvokable). The provider vtable is therefore byte-for-byte unchanged, so old/new hosts and modules stay binary-compatible — a new host reading an old module sees no event entries (zero events), and an old host reading a new module just ignores the "type" field (cosmetic). An entry with no "type" is treated as a method. - logos_provider_object.h: remove the getEvents() virtual; document that getMethods() carries both, and why. - generator (lidl_gen_provider): emit events as type "event" entries inside getMethods(); tag methods type "method"; no getEvents() output. - module_proxy / qt_provider_object: getPluginMethods()/getPluginEvents() are now type-filtered views of getMethods(), plus a new getPluginInterface() returning the whole list. (These are name- dispatched Q_INVOKABLEs, not vtable surface — adding them is safe.) - tests: generator asserts events fold into getMethods() tagged "event"; ModuleProxy asserts the three filtered views; parser tests unchanged. - docs: spec/project/docs/README updated, incl. an ABI rationale note. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
760916e97b |
Parse method doc comments into per-method description (#70)
* parse adjacent method comments to populate description * preserve line breaks in method descriptions Join doc-comment lines with newlines instead of spaces (markers stripped, leading/trailing blank lines dropped, interior blanks kept), and escape \n when emitting the description into the generated getMethods(). Both codegen paths updated; docs corrected. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * don't count braces inside comment lines (impl-header parser) A brace in a doc/line comment (e.g. `/// returns { ... }`) no longer affects class-scope tracking, which previously could make the parser think the class ended early and drop later declarations. Addresses review feedback on #70. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
c71089abe9 | remove legacy emitEvent (#69) | ||
|
|
8bdbd13848 |
Extend universal modules with module context (#61)
* extend universal modules with module context * implement module calls and events for universal modules * pr comments |
||
|
|
1468180b25 | add support for new types (#50) | ||
|
|
d633575677 |
add IDL parser & generator (wip) (#33)
* add IDL parser & generator (wip) * fix fixtures issues affecting tests * fix fixtures issues affecting tests |