2.9 KiB
Language bindings
src/gen/binding_schema.json describes handle families, constructors, methods,
arguments and operation/query mappings. build.rs derives it from
spec/entities.toml. Its layouts section is manually maintained vocabulary;
it does not contain everything needed to generate a bincode codec.
Generate and test the Python facade from the repository root:
python3 crates/ocs_doc_api/bindings/python/generate.py > /tmp/ocs_doc.py
python3 -m unittest discover -s crates/ocs_doc_api/bindings/python
The generated DocApi(transport, active_tab) expects a caller-supplied
transport.apply(envelope) -> Receipt. It does not open a plugin connection.
An envelope has version and a Python tuple ("Op", operation_dict) or
("Queries", [query_dict]). Enum payloads use externally tagged dictionaries,
for example {"CreateSolid": {"Sphere": {"centre": [0, 0, 0], "radius": 2}}}.
The bridge converts these objects to the Rust DTOs and bincode 1.3 wire format,
sends DocApiRequest { tab_id, bytes }, and decodes Result<Receipt, ApiError>.
Host plugin API version 6 and document envelope version 1 are required.
For Rust plugins compiled against ocs_doc_api with the doc_api_host feature,
use the doc_api_for_host helper to build a typed DocApi from any
ocs_plugin_api::host::HostApi that exposes a PluginRequestSender
(out-of-process / worker-thread hosts):
use ocs_doc_api::doc_api_for_host;
use ocs_plugin_api::host::HostApi;
fn on_dispatch(host: &mut dyn HostApi) -> Option<()> {
let doc_api = doc_api_for_host(host)?;
let doc = doc_api.document(host.tab_id());
let cube = doc.solids().create_cuboid([0.0; 3], [10.0; 3]).ok()?;
// ...
Some(())
}
In-process plugins should use DocApi::in_process(backend, tab_id) with a
concrete DocApiBackend; doc_api_for_host returns None for hosts that do not
expose a PluginRequestSender.
Decode receipt outcomes as {"NewId": 42} or {"NewIds": [42, 43]} and query
results as externally tagged dictionaries such as {"Volume": 12.5}. The facade
unwraps these into typed handles or values. Layer results use {"Layers": [...]}
and {"EntityLayer": "WALLS"}. Layer properties (LayerInfo, LayerFlags,
Color, LineWeight) appear as plain dictionaries in operation payloads, e.g.
{"CreateLayer": {"name": "Walls", "flags": {"frozen": false, "locked": false, "frozen_in_new_viewport": false, "off": false}, "color": {"Index": 7}, "line_type": "Continuous", "line_weight": {"Default": null}, "plot_style": "", "is_plottable": true}}.
XDATA and XRECORD payloads appear as nested externally tagged dictionaries
(e.g. {"XData": {"application_name": ..., "values": [...]}} or
{"XRecord": {"name": ..., "entries": [...]}}). The bridge must raise an
exception for an error response. Transport binding determines the tab; requesting
another tab or combining typed handles from different documents raises an error.