Files
logos-cpp-sdk/cpp-generator/docs
Dario Lipicar b594d1a38c fix(generator): the Qt consumer must not flatten a rejection into an empty value (#129)
* fix(generator): the Qt consumer must not flatten a rejection into an empty value

A provider that REJECTS a call answers the canonical
{"code":"dispatch_failed", "message":..., "origin":...} object as its RESULT,
not as a transport error — the same object from every provider flavour
(logos-qt-sdk dispatchFailedVariant, the generated cdylib dispatch, the Rust
provider's args::dispatch_failed).

The generated Qt consumer wrapper converted it like any other value, which
ERASES it. `_result.toList()` on that map is `[]`, `.toString()` is "",
`.toLongLong()` is 0 — so `echoUintList([1, -1, 3])`, answered `dispatch_failed`
by the provider, reached the caller as `[]`: the whole list, not the bad
element, and indistinguishable from "the provider returned nothing". Losing the
error is a consumer bug whatever the provider did.

Reported through the channel this surface already uses for a failed call: the
`logos::CallError*` out-parameter every generated sync method carries (today
"object_unavailable" when the target cannot be acquired). No signature changes,
no return value changes — a caller that passes `err` now sees
code="dispatch_failed" with the provider's diagnostic and origin; a caller that
does not gets the same default it always got, plus the qWarning the wrapper
already emits for a failed call.

  * the detector is emitted once per wrapper, in an anonymous namespace, and
    matches EXACTLY (three string fields, that code) for the same reason
    logos_rpc_status.h's isUnauthorizedSentinel matches exactly: an `any` or map
    return carrying user data must never false-match.
  * the result is now captured for `void` returns too — a void method can be
    rejected, and the rejection object is the only place that says so.
  * the async overload's callback takes the value alone and has no error
    parameter; giving it one would change the generated public surface (which
    logos-qt-sdk's veneer mirrors 1:1), so an async rejection is logged rather
    than delivered. Recorded in cpp-generator/docs/project.md.

Scope: CONSUMER side only. The provider half of registry entry Q1 (a Qt-typed
provider cannot validate the ELEMENT of a typed numeric array, because a C++
signature spells [uint] and [any] alike as QVariantList) is explicitly out of
scope and unchanged. The lp wrapper is untouched — its generated output is
byte-identical before and after.

* fix(generator): guard the emitted detector — the umbrella is one translation unit

`logos_sdk.cpp` textually `#include`s every generated `<dep>_api.cpp`, so a
module with more than one dependency compiles several copies of the detector
into ONE translation unit:

    test_fullapi_rust_api.cpp:15:6: error: redefinition of 'logosDispatchRejection'

Internal linkage covers the separate-TU case; only the preprocessor covers this
one. Found by building test_fullapi_qtproxy (3 wrappers: two concrete deps plus
the bound `full_api` interface) against this generator — a single-wrapper
contract cannot reach it.
2026-08-03 09:41:55 -03:00
..