Open Stream Deck

ABI для WebAssembly

Один импорт и четыре экспорта: как написать SDK для любого языка, который собирается в WebAssembly.

Модуль WASM общается с хостом одним импортом и четырьмя экспортами. Этого достаточно, чтобы написать SDK на любом языке.

НаправлениеИмяСигнатура
Импортopensd.send(ptr: i32, len: i32) -> i32
Экспортopensd_abi() -> i32, возвращает 1
Экспортopensd_alloc(len: i32) -> i32
Экспортopensd_free(ptr: i32, len: i32)
Экспортopensd_event(ptr: i32, len: i32) -> i32
Экспортmemoryлинейная память
  • Хост выделяет буфер через opensd_alloc, записывает в него событие в UTF-8 JSON, вызывает opensd_event и освобождает буфер через opensd_free.
  • Модуль отправляет команду, вызывая opensd.send с указателем на UTF-8 JSON. Ответ 0 значит, что команда принята, отрицательное значение значит, что она отклонена.
  • Ненулевой результат opensd_event означает ошибку обработчика. Описание ошибки модуль сам отправляет командой log.
  • Других импортов быть не должно. Упаковщик проверяет это и устанавливает предел памяти 64 МиБ, если модуль его не задал.

Пример обмена

  1. Хост вызывает opensd_alloc(len) и получает указатель на буфер в линейной памяти модуля.
  2. Хост записывает в буфер событие, например {"type":"tap","context":"k1","action":"com.example.counter.counter","settings":{},"state":0,"now":1520}.
  3. Хост вызывает opensd_event(ptr, len). Модуль разбирает JSON и вызывает opensd.send с командой {"type":"setTitle","context":"k1","title":"1"}.
  4. opensd_event возвращает 0, хост вызывает opensd_free(ptr, len).

Обработка события синхронная: пока opensd_event не вернула результат, следующее событие модулю не придёт. Долгие операции делаются через брокеры и таймеры, ответы на них приходят следующими событиями.

Крейт opensd это эталонная реализация ABI. Его модуль runtime.rs занимает около 140 строк и подходит как образец для SDK на другом языке. Типы событий и команд описаны в разделе протокол.