docs: the widened Qt consumer surface (#84)

* test(doctests): `lm` publishes the LIDL contract vocabulary, not Qt names

A universal module's `getMethods()` comes from the cdylib backend's
`lidlInterfaceJson()` (logos-plugin-qt's glue forwards
`logos_module_get_methods` verbatim), and that now answers in the LIDL
contract spelling. `lm methods`, `lm events` and `logoscore module-info`
print those strings straight through, so every listing in Part 1 changed:

    qlonglong add(qlonglong a, qlonglong b)   ->  int add(int a, int b)
    QString libVersion()                      ->  tstr libVersion()
    void versionReady(QString version)        ->  void versionReady(tstr version)

Six `expect_contains` in tutorial-wrapping-c-library.test.yaml were pinned
to the Qt spellings and now fail.

HOW THIS WAS ALMOST MISSED, because the trap will recur. The hand-pinned
`outputs/tutorial-wrapping-c-library.md` already showed `int add(int a, int b)`
and `add(int,int)` — a stale snapshot from an earlier era that happened to
read as "already LIDL, nothing to do". CI runs the ASSERTIONS in
`tests/*.test.yaml`; it never diffs the outputs tree. Clearing a file by
reading `outputs/` proves nothing.

Every replacement string is derived mechanically rather than by hand: the
tutorial's own `src/calc_module_impl.h` + `metadata.json` were run through
`logos-cpp-generator --from-header --backend cdylib`, the emitted
`lidlInterfaceJson()` was parsed back into JSON, and that JSON was rendered
through logos-module's own printer (`cmd/main.cpp`) and logoscore's
(`src/client/output.cpp`). The displayed blocks in BOTH trees now compare
byte-identical to that render.

Two accuracy fixes fall out of doing that, both pre-existing drift in the
blocks being rewritten:

  * the derived identity methods `name()` / `version()` DO appear in every
    listing (nothing filters `derived` on the read side) and were missing
    from the shown output;
  * the `module-info` block said `libVersion() -> QString` and
    `versionReady(version: QString)`.

The C++-type table gains a column. "On the wire (Qt)" conflated two
different questions; it is now "LIDL contract type" — what the module
publishes, what Step 5 prints, what a Rust or Nim binding sees — and "A Qt
consumer sees", which is only the C++/Qt caller's spelling.

Also here, same cause:
  * tutorial-composing-modules and tutorial-interface-dependencies had the
    same "shows up as QString ... the wire types the generated glue exposes"
    prose. Their assertions are name-only, so they did not fail — but they
    described the listing wrongly. `LogosMap` publishes as `{tstr: any}`,
    verified by generating calc_aggregator's glue.
  * logos-developer-guide.md's `lm methods --json` example was a
    handwritten-Qt listing (`initLogos(LogosAPI*)`) presented as the general
    case. It now shows both publishers and says which is which: a universal
    module publishes its contract, a handwritten Qt plugin publishes what its
    QMetaObject says.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* docs(guide): the plugin path needs the module's contract, not just its plugin

`logos-cpp-generator <plugin> [--module-only]` is documented here as a way to
generate a module's consumer wrapper, and the examples pass only the plugin.
That is now a trap for any module built with `interface: "universal"` or
`"cdylib"`: its published `getMethods()` answers in the LIDL contract
vocabulary — the same change d963871 pinned in the `lm` listings — while the
wrapper emitter reads Qt type names and falls back to QVariant / LogosMap for
anything else. The wrapper would compile and have lost every type.

The generator now takes the METHODS from the `.lidl` contract named by
`--events-from` (the flag keeps its name; the file always was the whole
contract), and REFUSES a LIDL-spelled listing when no contract was given rather
than emitting the untyped wrapper. Nix builds already pass the flag —
buildHeaders.nix finds `<module>/share/logos/<name>.lidl` — so only hand-run
invocations, which is what this section documents, had to change.

Both examples gain the flag, a second example shows the handcrafted-Qt case
that legitimately omits it, and the synopsis in the CLI reference lists it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Dario Lipicar
2026-08-22 21:04:54 -03:00
committed by GitHub
co-authored by Claude Opus 5
parent dc4635d3c4
commit 24d8aea7d3
7 changed files with 170 additions and 73 deletions
+60 -9
View File
@@ -442,17 +442,49 @@ Example JSON output:
./lm/bin/lm methods ./result/lib/my_module_plugin.so --json
```
Example JSON output:
**The type names depend on which kind of module you are inspecting**, because
two different things publish this JSON:
- A **universal / cdylib module** (`"interface": "universal"`, the style used
throughout this guide and in the tutorials) publishes its **LIDL contract**
types — `tstr`, `int`, `uint`, `bstr`, `[tstr]`, `{tstr: any}`, `? uint`,
`result`, and a record's declared name. The module is Qt-free, so the
contract is the only vocabulary in which the question has one answer, and
a Rust module implementing the same contract answers identically.
- A **handwritten Qt plugin** publishes what its `QMetaObject` says — `QString`,
`QVariantList`, `QVariantMap` — because there the metaobject *is* the
contract.
Example JSON output, for a universal module with
`method doSomething(input: tstr) -> tstr`:
```json
[
{
"name": "initLogos",
"signature": "initLogos(LogosAPI*)",
"returnType": "void",
"name": "doSomething",
"signature": "doSomething(tstr)",
"returnType": "tstr",
"isInvokable": true,
"parameters": [{ "name": "logosAPIInstance", "type": "LogosAPI*" }]
"parameters": [{ "name": "input", "type": "tstr" }]
},
{
"name": "name",
"signature": "name()",
"returnType": "tstr",
"isInvokable": true,
"description": "The module's name, as declared in its metadata."
}
]
```
`name` and `version` are **derived**: the generator emits them from
`metadata.json`, so every module answers them without the author writing them,
and they appear in every listing.
The same listing from a handwritten Qt plugin would instead read:
```json
[
{
"name": "doSomething",
"signature": "doSomething(QString)",
@@ -1030,20 +1062,39 @@ The generator is bundled with `logos-cpp-sdk`. It is automatically available:
#### Generating Wrappers
```bash
# Generate wrappers for a single module
logos-cpp-generator /path/to/my_module_plugin.so --output-dir ./generated
# Generate wrappers for a single module, from the CONTRACT it ships beside its
# plugin. `--events-from` names that contract, and the wrapper's typed methods,
# record structs and typed on<Event>() accessors all come from it.
logos-cpp-generator /path/to/my_module_plugin.so --output-dir ./generated \
--events-from /path/to/share/logos/my_module.lidl
# A handcrafted Qt module publishes no contract; omit the flag and the wrapper
# comes from the plugin's Qt metaobject, which is then the only description of
# its API that exists.
logos-cpp-generator /path/to/handcrafted_plugin.so --output-dir ./generated
# Generate a wrapper per dependency, each from that dependency's LIDL contract
logos-cpp-generator --metadata metadata.json --general-only --output-dir ./generated \
--dep waku_module=/path/to/waku_module.lidl
# Generate only module files (no umbrella headers)
logos-cpp-generator /path/to/plugin.so --module-only --output-dir ./generated
logos-cpp-generator /path/to/plugin.so --module-only --output-dir ./generated \
--events-from /path/to/share/logos/my_module.lidl
# Generate only umbrella SDK files (assumes module files exist)
logos-cpp-generator --metadata metadata.json --general-only --output-dir ./generated
```
> **Why `--events-from` is not optional for a module that has a contract.** A
> module built with `interface: "universal"` or `"cdylib"` publishes its
> `getMethods()` metadata in the LIDL contract vocabulary (`tstr`, `[uint]`,
> `result`) — that listing is what `lm` and `logoscore` show a human, and Qt
> type names would be the wrong answer for a Qt-free module. The wrapper
> emitter reads Qt type names, so generating from that listing would silently
> produce a wrapper of `QVariant` / `LogosMap`. It refuses instead, naming the
> contract to pass. Nix builds pass it for you: `buildHeaders.nix` finds
> `<module>/share/logos/<name>.lidl`, which `buildPlugin.nix` installed.
#### Using Generated Wrappers
After generation, you get typed wrapper classes with both synchronous and asynchronous methods:
@@ -1363,7 +1414,7 @@ logoscore stop # Stop daemon
### `logos-cpp-generator` -- SDK Code Generator
```bash
logos-cpp-generator <plugin-file> [--output-dir <dir>] [--module-only]
logos-cpp-generator <plugin-file> [--output-dir <dir>] [--module-only] [--events-from <name>.lidl]
logos-cpp-generator --metadata <metadata.json> --general-only --dep <name>=<name>.lidl [--output-dir <dir>]
logos-cpp-generator --metadata <metadata.json> --general-only [--output-dir <dir>]
```
+1 -1
View File
@@ -485,7 +485,7 @@ Dependencies: calc_module
./lm/bin/lm methods result/lib/calc_aggregator_plugin.dylib # macOS
```
Every `public` method on the impl is here `int64_t` shows up as `int`, `std::string` as `QString`, and `LogosMap` (from `computeReport`) as `QVariantMap`, because `lm` reports the wire types the generated glue exposes.
Every `public` method on the impl is here, published in the **LIDL contract** vocabulary rather than in C++ or Qt names: `int64_t` shows up as `int`, `std::string` as `tstr`, and `LogosMap` (from `computeReport`) as `{tstr: any}`. `lm` is reporting what the module says about itself, and what a module publishes is its contract — the same words the generated `.lidl` uses, and the same words a Rust or Nim module implementing this contract would answer with.
---
+1 -1
View File
@@ -413,7 +413,7 @@ Dependencies:
./lm/bin/lm methods result/lib/calc_via_interface_plugin.dylib # macOS
```
Every `public` method is here. `int64_t` shows up as `int` and `std::string` as `QString` — the wire types the generated glue exposes.
Every `public` method is here, published in the **LIDL contract** vocabulary rather than in C++ or Qt names: `int64_t` shows up as `int` and `std::string` as `tstr`. `lm` is reporting what the module says about itself, and what a module publishes is its contract.
---
+46 -23
View File
@@ -368,8 +368,8 @@ public:
~CalcModuleImpl() = default;
// ── Public API — every method here is callable over IPC ──────────
// The generator maps C++ types onto the wire automatically:
// int64_t ↔ int std::string ↔ QString bool ↔ bool
// The generator maps C++ types onto the contract automatically:
// int64_t ↔ int std::string ↔ tstr bool ↔ bool
//
// A doc comment directly above a method becomes that method's
// `description` in the module's method introspection — surfaced
@@ -424,18 +424,24 @@ logos_events:
- It's a normal C++ class. Any `public` method is exposed; `private` members and helpers are not.
- **Supported parameter/return types** (what the generator can translate):
| C++ type | On the wire (Qt) |
| --------------------------- | ------------------ |
| `void` | `void` |
| `bool` | `bool` |
| `int64_t` | `int` |
| `uint64_t` | `uint` |
| `double` | `double` |
| `std::string` | `QString` |
| `std::vector<std::string>` | `QStringList` |
| `std::vector<uint8_t>` | `QByteArray` |
| `LogosMap` / `LogosList` | `QVariantMap` / `QVariantList` (from `<logos_json.h>`) |
| `StdLogosResult` | `LogosResult` (from `<logos_result.h>`) — `{ success, value, error }` |
| C++ type | LIDL contract type | A Qt consumer sees |
| --------------------------- | ------------------ | ------------------ |
| `void` | `void` | `void` |
| `bool` | `bool` | `bool` |
| `int64_t` | `int` | `qlonglong` |
| `uint64_t` | `uint` | `qulonglong` |
| `double` | `float64` | `double` |
| `std::string` | `tstr` | `QString` |
| `std::vector<std::string>` | `[tstr]` | `QStringList` |
| `std::vector<uint8_t>` | `bstr` | `QByteArray` |
| `LogosMap` / `LogosList` | `{tstr: any}` / `[any]` (from `<logos_json.h>`) | `QVariantMap` / `QVariantList` |
| `StdLogosResult` | `result` | `LogosResult` (from `<logos_result.h>`) — `{ success, value, error }` |
The **middle** column is the one your module publishes about itself —
it is what `lm` prints in Step 5, and what any other language's
binding of this contract sees. The right column is what a *C++/Qt*
caller of this module compiles against; a Rust or Nim caller gets
that language's spelling of the same middle column.
- Use `int64_t` for integers (not `int`) — that's the type the parser recognizes.
- **Document methods with `///`.** A doc comment (`///` or `/** … */`) directly above a method becomes its `description` in the module's introspection, surfaced by `lm`, `logoscore module-info`, and Basecamp. Plain `//` comments are ignored, so only intentional docs are exposed — you'll see this in action in Step 5.
@@ -616,9 +622,12 @@ Dependencies: (none)
```
Output — each method you declared, with its doc comment as a
`Description`. A single-line comment renders inline; a multi-line
comment (`factorial`'s two `///` lines, `libVersion`'s `/** ... */`
block, and `libVersionNotify`'s two `///` lines) keeps its line breaks:
`Description`, plus the two identity methods (`name`, `version`) the
generator derives from `metadata.json` so every module answers them
without you writing them. A single-line comment renders inline; a
multi-line comment (`factorial`'s two `///` lines, `libVersion`'s
`/** ... */` block, and `libVersionNotify`'s two `///` lines) keeps
its line breaks:
```
Plugin Methods:
@@ -646,7 +655,7 @@ int fibonacci(int n)
Invokable: yes
Description: Returns the nth Fibonacci number (0-indexed).
QString libVersion()
tstr libVersion()
Signature: libVersion()
Invokable: yes
Description:
@@ -659,11 +668,21 @@ void libVersionNotify()
Description:
Looks up the library version and emits it as a `versionReady`
event instead of returning it. Used by the QML tutorial (Part 2).
tstr name()
Signature: name()
Invokable: yes
Description: The module's name, as declared in its metadata.
tstr version()
Signature: version()
Invokable: yes
Description: The module's version, as declared in its metadata.
```
Three things to notice:
- **Signatures are Qt-typed** (`int`, `QString`) even though you wrote `int64_t` / `std::string`. That's the generated glue: `lm` reports the wire types the synthesized Qt plugin exposes, so `int64_t add(int64_t, int64_t)` shows up as `add(int,int)`.
- **Signatures are in LIDL, not C++** (`int`, `tstr`) even though you wrote `int64_t` / `std::string`. `lm` reports what the module *publishes about itself*, and a module publishes its **contract** — so `int64_t add(int64_t, int64_t)` shows up as `add(int,int)`. That is the same vocabulary as the `.lidl` the build derived from your header, and it is the only vocabulary in which this question has one right answer: your module is Qt-free, and a reader in Rust or Nim asking the same module the same question gets the same words back. Note `int` here is LIDL's `int`, which is **64-bit** — each type in the contract maps to exactly one type per language, and integers are 64-bit throughout, so a value that fits your `int64_t` cannot be silently truncated on the way across.
- **Each `Description` is your doc comment**, carried through the module's method introspection. Plain `//` comments (like the type-mapping note in the header) are deliberately ignored, so only intentional docs surface; an undocumented method simply omits it.
- **Line breaks are preserved** — a single-line comment renders inline; a multi-line comment (`factorial`, `libVersion`, `libVersionNotify`) keeps its breaks. The same descriptions appear in `logoscore module-info` and Basecamp's Methods list.
@@ -720,8 +739,8 @@ signature and `///` description:
Plugin Events:
==============
void versionReady(QString version)
Signature: versionReady(QString)
void versionReady(tstr version)
Signature: versionReady(tstr)
Description:
Emitted by libVersionNotify() once the library version is known.
Carries the version string read from libcalc.
@@ -813,15 +832,19 @@ Methods:
Defined as n * (n-1) * ... * 1, with 0! = 1.
fibonacci(n: int) -> int
Returns the nth Fibonacci number (0-indexed).
libVersion() -> QString
libVersion() -> tstr
Returns the version string of the wrapped libcalc C library.
Read straight from the linked native library, not metadata.json.
libVersionNotify() -> void
Looks up the library version and emits it as a `versionReady`
event instead of returning it. Used by the QML tutorial (Part 2).
name() -> tstr
The module's name, as declared in its metadata.
version() -> tstr
The module's version, as declared in its metadata.
Events:
versionReady(version: QString)
versionReady(version: tstr)
Emitted by libVersionNotify() once the library version is known.
Carries the version string read from libcalc.
```
+1 -1
View File
@@ -482,7 +482,7 @@ sections:
- "bumpRunCount"
- "persistenceDir"
post_text: |
Every `public` method on the impl is here `int64_t` shows up as `int`, `std::string` as `QString`, and `LogosMap` (from `computeReport`) as `QVariantMap`, because `lm` reports the wire types the generated glue exposes.
Every `public` method on the impl is here, published in the **LIDL contract** vocabulary rather than in C++ or Qt names: `int64_t` shows up as `int`, `std::string` as `tstr`, and `LogosMap` (from `computeReport`) as `{tstr: any}`. `lm` is reporting what the module says about itself, and what a module publishes is its contract — the same words the generated `.lidl` uses, and the same words a Rust or Nim module implementing this contract would answer with.
# ── Step 6: Run it with logoscore ───────────────────────────────────────────
- title: "Run it with `logoscore`"
@@ -416,7 +416,7 @@ sections:
- "startFibVia"
- "watchVersion"
post_text: |
Every `public` method is here. `int64_t` shows up as `int` and `std::string` as `QString` — the wire types the generated glue exposes.
Every `public` method is here, published in the **LIDL contract** vocabulary rather than in C++ or Qt names: `int64_t` shows up as `int` and `std::string` as `tstr`. `lm` is reporting what the module says about itself, and what a module publishes is its contract.
# ── Step 7: Run it with logoscore ───────────────────────────────────────────
- title: "Run it with `logoscore`"
+60 -37
View File
@@ -367,8 +367,8 @@ sections:
~CalcModuleImpl() = default;
// ── Public API — every method here is callable over IPC ──────────
// The generator maps C++ types onto the wire automatically:
// int64_t ↔ int std::string ↔ QString bool ↔ bool
// The generator maps C++ types onto the contract automatically:
// int64_t ↔ int std::string ↔ tstr bool ↔ bool
//
// A doc comment directly above a method becomes that method's
// `description` in the module's method introspection — surfaced
@@ -422,18 +422,24 @@ sections:
- It's a normal C++ class. Any `public` method is exposed; `private` members and helpers are not.
- **Supported parameter/return types** (what the generator can translate):
| C++ type | On the wire (Qt) |
| --------------------------- | ------------------ |
| `void` | `void` |
| `bool` | `bool` |
| `int64_t` | `int` |
| `uint64_t` | `uint` |
| `double` | `double` |
| `std::string` | `QString` |
| `std::vector<std::string>` | `QStringList` |
| `std::vector<uint8_t>` | `QByteArray` |
| `LogosMap` / `LogosList` | `QVariantMap` / `QVariantList` (from `<logos_json.h>`) |
| `StdLogosResult` | `LogosResult` (from `<logos_result.h>`) — `{ success, value, error }` |
| C++ type | LIDL contract type | A Qt consumer sees |
| --------------------------- | ------------------ | ------------------ |
| `void` | `void` | `void` |
| `bool` | `bool` | `bool` |
| `int64_t` | `int` | `qlonglong` |
| `uint64_t` | `uint` | `qulonglong` |
| `double` | `float64` | `double` |
| `std::string` | `tstr` | `QString` |
| `std::vector<std::string>` | `[tstr]` | `QStringList` |
| `std::vector<uint8_t>` | `bstr` | `QByteArray` |
| `LogosMap` / `LogosList` | `{tstr: any}` / `[any]` (from `<logos_json.h>`) | `QVariantMap` / `QVariantList` |
| `StdLogosResult` | `result` | `LogosResult` (from `<logos_result.h>`) — `{ success, value, error }` |
The **middle** column is the one your module publishes about itself —
it is what `lm` prints in Step 5, and what any other language's
binding of this contract sees. The right column is what a *C++/Qt*
caller of this module compiles against; a Rust or Nim caller gets
that language's spelling of the same middle column.
- Use `int64_t` for integers (not `int`) — that's the type the parser recognizes.
- **Document methods with `///`.** A doc comment (`///` or `/** … */`) directly above a method becomes its `description` in the module's introspection, surfaced by `lm`, `logoscore module-info`, and Basecamp. Plain `//` comments are ignored, so only intentional docs are exposed — you'll see this in action in Step 5.
@@ -595,47 +601,50 @@ sections:
# macOS
./lm/bin/lm methods result/lib/calc_module_plugin.dylib
expect_contains:
- "qlonglong add(qlonglong a, qlonglong b)"
- "qlonglong multiply(qlonglong a, qlonglong b)"
- "qlonglong factorial(qlonglong n)"
- "qlonglong fibonacci(qlonglong n)"
- "QString libVersion()"
- "int add(int a, int b)"
- "int multiply(int a, int b)"
- "int factorial(int n)"
- "int fibonacci(int n)"
- "tstr libVersion()"
- "Description: Adds two integers and returns the sum."
- "Defined as n * (n-1) * ... * 1, with 0! = 1."
- "Read straight from the linked native library, not metadata.json."
post_text: |
Output — each method you declared, with its doc comment as a
`Description`. A single-line comment renders inline; a multi-line
comment (`factorial`'s two `///` lines, `libVersion`'s `/** ... */`
block, and `libVersionNotify`'s two `///` lines) keeps its line breaks:
`Description`, plus the two identity methods (`name`, `version`) the
generator derives from `metadata.json` so every module answers them
without you writing them. A single-line comment renders inline; a
multi-line comment (`factorial`'s two `///` lines, `libVersion`'s
`/** ... */` block, and `libVersionNotify`'s two `///` lines) keeps
its line breaks:
```
Plugin Methods:
===============
qlonglong add(qlonglong a, qlonglong b)
Signature: add(qlonglong,qlonglong)
int add(int a, int b)
Signature: add(int,int)
Invokable: yes
Description: Adds two integers and returns the sum.
qlonglong multiply(qlonglong a, qlonglong b)
Signature: multiply(qlonglong,qlonglong)
int multiply(int a, int b)
Signature: multiply(int,int)
Invokable: yes
Description: Multiplies two integers and returns the product.
qlonglong factorial(qlonglong n)
Signature: factorial(qlonglong)
int factorial(int n)
Signature: factorial(int)
Invokable: yes
Description:
Computes the factorial n! of a non-negative integer.
Defined as n * (n-1) * ... * 1, with 0! = 1.
qlonglong fibonacci(qlonglong n)
Signature: fibonacci(qlonglong)
int fibonacci(int n)
Signature: fibonacci(int)
Invokable: yes
Description: Returns the nth Fibonacci number (0-indexed).
QString libVersion()
tstr libVersion()
Signature: libVersion()
Invokable: yes
Description:
@@ -648,11 +657,21 @@ sections:
Description:
Looks up the library version and emits it as a `versionReady`
event instead of returning it. Used by the QML tutorial (Part 2).
tstr name()
Signature: name()
Invokable: yes
Description: The module's name, as declared in its metadata.
tstr version()
Signature: version()
Invokable: yes
Description: The module's version, as declared in its metadata.
```
Three things to notice:
- **Signatures are Qt-typed** (`qlonglong`, `QString`) even though you wrote `int64_t` / `std::string`. That's the generated glue: `lm` reports the wire types the synthesized Qt plugin exposes, so `int64_t add(int64_t, int64_t)` shows up as `add(qlonglong,qlonglong)`. Note the width is **preserved** — `qlonglong` is Qt's 64-bit integer, not `int`. Each type in the contract maps to exactly one type per language, and integers are 64-bit throughout, so a value that fits your `int64_t` cannot be silently truncated on the way across.
- **Signatures are in LIDL, not C++** (`int`, `tstr`) even though you wrote `int64_t` / `std::string`. `lm` reports what the module *publishes about itself*, and a module publishes its **contract** — so `int64_t add(int64_t, int64_t)` shows up as `add(int,int)`. That is the same vocabulary as the `.lidl` the build derived from your header, and it is the only vocabulary in which this question has one right answer: your module is Qt-free, and a reader in Rust or Nim asking the same module the same question gets the same words back. Note `int` here is LIDL's `int`, which is **64-bit** — each type in the contract maps to exactly one type per language, and integers are 64-bit throughout, so a value that fits your `int64_t` cannot be silently truncated on the way across.
- **Each `Description` is your doc comment**, carried through the module's method introspection. Plain `//` comments (like the type-mapping note in the header) are deliberately ignored, so only intentional docs surface; an undocumented method simply omits it.
- **Line breaks are preserved** — a single-line comment renders inline; a multi-line comment (`factorial`, `libVersion`, `libVersionNotify`) keeps its breaks. The same descriptions appear in `logoscore module-info` and Basecamp's Methods list.
@@ -705,7 +724,7 @@ sections:
# macOS
./lm/bin/lm events result/lib/calc_module_plugin.dylib
expect_contains:
- "void versionReady(QString version)"
- "void versionReady(tstr version)"
- "Emitted by libVersionNotify() once the library version is known."
- "Carries the version string read from libcalc."
post_text: |
@@ -713,8 +732,8 @@ sections:
Plugin Events:
==============
void versionReady(QString version)
Signature: versionReady(QString)
void versionReady(tstr version)
Signature: versionReady(tstr)
Description:
Emitted by libVersionNotify() once the library version is known.
Carries the version string read from libcalc.
@@ -786,15 +805,19 @@ sections:
Defined as n * (n-1) * ... * 1, with 0! = 1.
fibonacci(n: int) -> int
Returns the nth Fibonacci number (0-indexed).
libVersion() -> QString
libVersion() -> tstr
Returns the version string of the wrapped libcalc C library.
Read straight from the linked native library, not metadata.json.
libVersionNotify() -> void
Looks up the library version and emits it as a `versionReady`
event instead of returning it. Used by the QML tutorial (Part 2).
name() -> tstr
The module's name, as declared in its metadata.
version() -> tstr
The module's version, as declared in its metadata.
Events:
versionReady(version: QString)
versionReady(version: tstr)
Emitted by libVersionNotify() once the library version is known.
Carries the version string read from libcalc.
```