One way to record an error, and a name that reads as a query

dpm_module_info_of becomes dpm_get_module_info, joining the other two
readers on the context in stating that a call fetches a value.

Recording an error had two entry points doing the same write: the
exported dpm_set_last_error and an internal dpm_core::set_last_error
taking a std::string. The internal one is gone and the loader calls the
exported function, so a reason reaches the context by one path whether a
module or the library records it.
This commit is contained in:
2026-08-19 02:34:28 -04:00
parent 50d71ca55f
commit 71d409b5c7
9 changed files with 21 additions and 44 deletions

View File

@@ -56,11 +56,11 @@ dpm_module* mod = dpm_require(ctx, "mymodule");
libdpm-core.so validates the module completely at load; a handle is returned only for a fully valid module. NULL means the module is absent or invalid — `dpm_get_last_error`(ctx) carries the precise reason. Modules load at most once per context; repeated calls return the same handle.
`dpm_module_info_of` reports what the library saw in the loaded module:
`dpm_get_module_info` reports what the library saw in the loaded module:
```
dpm_module_info info;
dpm_module_info_of(ctx, mod, &info);
dpm_get_module_info(ctx, mod, &info);
```
`info` carries `name`, `version`, and `description`.
@@ -91,7 +91,7 @@ The cursor covers every valid module in the module path; invalid candidates are
## Services
- `dpm_core_version`()** — the library version; callable without a context.
- `dpm_module_info_of`(ctx, mod, out)** — the name, version, and description read from a loaded module.
- `dpm_get_module_info`(ctx, mod, out)** — the name, version, and description read from a loaded module.
- `dpm_config_get`(ctx, module, section, key)** — a value from a module's configuration namespace, or NULL if unset.
- `dpm_log`(ctx, level, message)** — writes to the context's configured log targets; levels are `DPM_LOG_FATAL` through `DPM_LOG_DEBUG`.
- `dpm_get_resolved_module_path`(ctx)** — the resolved module directory.

View File

@@ -62,7 +62,7 @@ Releases the context: unloads every module handle it issued, closes log targets,
`dpm_module* dpm_require(dpm_ctx* ctx, const char* name)`
Resolves the module `name` in the module path and runs the full load-time validation sequence (see Load-Time Enforcement) if the module is not already loaded in this context. On success returns a module handle owned by the context (repeated calls return the same handle — modules are loaded at most once per context). On failure returns NULL and records the precise reason: not found, or validation step failed with the step and detail. No version criterion is applied here; compatibility is the caller's to determine from the reported version.
`int dpm_module_info_of(dpm_ctx* ctx, dpm_module* mod, dpm_module_info* out)`
`int dpm_get_module_info(dpm_ctx* ctx, dpm_module* mod, dpm_module_info* out)`
Fills `out` with the loaded module's name, version, and description exactly as they were read at load (string pointers valid until context close). This is how a consumer obtains the version it will judge. The library attaches no meaning to the values. Returns 0 on success, nonzero if the module cannot be reported on.
`int dpm_execute(dpm_ctx* ctx, dpm_module* mod, const char* command, int argc, char** argv)`

View File

@@ -60,7 +60,7 @@ The `ctx` is the one handed to your entry point. Nothing else is needed to reach
**Never link, include, or hardcode anything belonging to a peer.** No peer headers, no shared types, no peer symbols. Modules are loaded with `RTLD_LOCAL`, so a peer's symbols are not reachable from your module even if you tried — libdpm-core.so is the only path, and the only knowledge you hold about a peer is its name and the commands it documents.
A module that depends on a peer is the party that judges the peer's version. Require it, read its reported version with `dpm_module_info_of`, and decide whether it is suitable for the commands you intend to issue. libdpm-core.so reports; it does not rule.
A module that depends on a peer is the party that judges the peer's version. Require it, read its reported version with `dpm_get_module_info`, and decide whether it is suitable for the commands you intend to issue. libdpm-core.so reports; it does not rule.
## Validation at Load

View File

@@ -53,7 +53,7 @@ The context owns everything it hands out. Every string a caller receives stays v
**Acquiring a module.** `dpm_require` resolves a module by name, validates it completely, and returns a handle — or returns NULL, with `dpm_get_last_error` carrying the precise reason. Modules load at most once per context, and repeated calls return the same handle.
**Reading what the library saw.** `dpm_module_info_of` fills in a module's name, version, and description. Those values are reported, and no conclusion is drawn from them.
**Reading what the library saw.** `dpm_get_module_info` fills in a module's name, version, and description. Those values are reported, and no conclusion is drawn from them.
**Calling into a module.** `dpm_execute` passes a command name and an argument vector to the module's entry point and returns its result. This is the only path into module code, and it is the same one the `dpm` binary takes.