Files
oak-editor/docs/zh/plans/riir/M9-oakplugin.md
T
Mike-Solar 9b25772267 docs: module-split execution manuals for RIIR stage 1 (plans/riir/)
13 files: 00 overview, 01 two-layer adapter spec (init/free/func +
opaque handles + same-name adapter classes, frozen naming/ownership/
error/event rules), 02 dependency matrix + split order M1-M9 (from a
490-file include scan), 03 Google Test spec (per-C-API coverage,
roundtrip tests, leak counters), M1-M9 per-module manuals with frozen
C APIs (common/undo/node/timeline/codec/audio/render/task/plugin) and
the facade assembly-layer verdict.
2026-07-27 00:06:33 +08:00

4.0 KiB
Raw Blame History

M9 · oakplugin 拆分手册 + facade 装配层裁决

内容:engine/pluginSupport/OpenFX hostOliveHost、 OlivePluginInstance、PluginNode、PluginProgressReporter)。 依赖:node 6、render 6、common 6、core 2、undo 2、coreengine 2。 拆分顺序第 9 位(最后拆的实体模块)。文末 §4 是 liboakengine 装配层的最终裁决。

1. 目标形态

oakplugin/
  include/oakplugin/{host.h, instance.h, progress.h, types.h, export.h}
  src/
  tests/  # oakplugin_gtest

2. 冻结 C API

2.1 oakplugin/host.h

OAKPL_API int oakplugin_host_init(void);
OAKPL_API void oakplugin_host_shutdown(void);
OAKPL_API int oakplugin_host_scan(const char *const *bundle_dirs,
	int dir_count);
OAKPL_API int oakplugin_host_plugin_count(void);
OAKPL_API int oakplugin_host_plugin_id_at(int i, char *buf, int n);
OAKPL_API int oakplugin_host_plugin_label(const char *plugin_id,
	char *buf, int n);

2.2 oakplugin/instance.h

typedef struct OakPluginInstance OakPluginInstance;
OAKPL_API OakPluginInstance *oakplugin_instance_create(
	const char *plugin_id);
OAKPL_API void oakplugin_instance_free(OakPluginInstance *i);
OAKPL_API int oakplugin_instance_set_param(OakPluginInstance *i,
	const char *param_id, const oak_node_value *v);
OAKPL_API int oakplugin_instance_get_param(OakPluginInstance *i,
	const char *param_id, oak_node_value *out);
OAKPL_API int oakplugin_instance_render(OakPluginInstance *i,
	OakCodecFrame *dst, const OakCodecFrame *src, int64_t ts);
/* 进度事件(R6 已把 cancelled 信号改成 C 回调,沿用该机制) */
OAKPL_API void oakplugin_instance_set_progress_cb(OakPluginInstance *i,
	oakplugin_progress_fn fn, void *userdata);
OAKPL_API void oakplugin_instance_cancel(OakPluginInstance *i);

2.3 oakplugin/progress.h

typedef struct OakPluginProgress OakPluginProgress; /* 报告器句柄 */
OAKPL_API OakPluginProgress *oakplugin_progress_create_dialog(
	const char *message, const char *title);  /* UI 侧实现 */
OAKPL_API void oakplugin_progress_free(OakPluginProgress *p);

3. 切割点

现状 处理
plugin → node/ 6plugins/plugin.h 3 等) 经 oaknode C ABIPluginNode 是节点,留在 oaknodeoakplugin 只经 factory/host 接口交互)——PluginNode 归属裁决:PluginNode 类随 oaknode 走(它是节点体系成员),oakplugin 提供 host/instance
plugin → render/ 6videoparams 3 等) videoparams 已下沉;其余经 oakrender C ABI
plugin → undo/ 2 oakundo 适配类
plugin → coreengine.h 2 插件注册点内聚进 oakplugin_host_init

4. facade 装配层最终裁决(liboakengine 的终态)

M1-M9 全部完成后,engine/src/capi + coreengine + tool/ + ui/ 残余构成 liboakengine。裁决(选定):

facade 直链各模块,不绕 C ABI 自调。即:facade 的 oakengine_* 实现可以继续直接调用各模块的 C++ 内部(链接 oaknode/oakrender 等 的静态或共享库),不要求 facade 经各模块的公共 C ABI 兜圈。 理由:facade 与 app 的边界(oakengine_*)已经纯 C 且 nm=0,模块间 边界是给"模块互相调用"用的;facade 是装配层,自家人不绕远路。 coreengine.h 被 node/render/task/plugin 引用的 5+2+2+2 处必须内聚(各模块的初始化改由各自的 oak<mod>_init 完成, coreengine 只做编排调用)。

终态验证:

nm -D --defined-only liboakengine.so | grep -c " T _Z"      # 0R7-B
nm -D --defined-only liboaknode.so | grep -c " T _Z"        # 0(每模块同查)
ldd liboakengine.so | grep oak                               # 只见 oak* 模块库
全量构建 0 error;全量 ctest 绿

5. 测试(映射 03 §2/§3

  • hostinit/scan/枚举(照现有 OliveHost 测试的 bundle fixture)。
  • instanceShadertoy 类插件(CI 里可用的)创建/参数/渲染一帧非空。
  • progress:回调触发与 cancel。
  • oakplugin_debug_alive_count() 泄漏断言。