Skip to content

Commit 8d03f10

Browse files
committed
docs: 更新 chumod.h 新增 P3 API 声明
1 parent a33ce64 commit 8d03f10

7 files changed

Lines changed: 127 additions & 14 deletions

File tree

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "chumod-loader"
3-
version = "2.5.0"
3+
version = "3.0.0"
44
edition = "2021"
55

66
[lib]

docs/api-reference.md

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
# ChuModLoader API Reference (v2.5.0)
1+
# ChuModLoader API Reference (v3.0.0)
22

3-
This document describes the C ABI exposed by ChuModLoader v2.5.0. The ABI is intentionally append-only: older mods continue to work, and newer mods should check `ChuModAPI::struct_size` before using fields added after their target version.
3+
This document describes the C ABI exposed by ChuModLoader v3.0.0. The ABI is intentionally append-only: older mods continue to work, and newer mods should check `ChuModAPI::struct_size` before using fields added after their target version.
44

55
For C/C++ projects, include `include/chumod.h`. Rust or other languages should mirror the same `#[repr(C)]` layouts and `extern "C"` function signatures.
66

@@ -35,8 +35,8 @@ typedef struct {
3535

3636
| Field | Description |
3737
| --- | --- |
38-
| `api_version` | Loader ABI version. v2.5.0 reports `CHUMOD_API_VERSION` (`3`). |
39-
| `loader_version` | Loader package version string, e.g. `"2.5.0"`. |
38+
| `api_version` | Loader ABI version. v3.0.0 reports `CHUMOD_API_VERSION` (`3`). |
39+
| `loader_version` | Loader package version string, e.g. `"3.0.0"`. |
4040
| `game_module` | Game executable module name, usually `"chusanApp.exe"`; may be `NULL`. |
4141
| `game_base` | Base address of the game image, or `0` if the module was not found. |
4242
| `game_size` | Size of the game image in bytes. |
@@ -91,6 +91,9 @@ typedef struct {
9191
ChuModTomlGetFloatFunc toml_get_float;
9292
ChuModTomlGetStringFunc toml_get_string;
9393
ChuModGetManifestPathFunc get_manifest_path;
94+
95+
/* v3 */
96+
ChuModReloadModFunc reload_mod;
9497
} ChuModAPI;
9598
```
9699

@@ -403,6 +406,33 @@ if (manifest) {
403406
}
404407
```
405408

409+
## v3 API
410+
411+
### Hot reload
412+
413+
```c
414+
typedef int (*ChuModReloadModFunc)(const char* mod_name);
415+
int reload_mod(const char* mod_name);
416+
```
417+
418+
Reloads a currently loaded mod by display name, file name, or file stem. The loader calls the target mod's `chumod_shutdown`, unloads the DLL with `FreeLibrary`, loads it again, then calls `chumod_init` and `chumod_on_ready` if present. The whole flow is panic-guarded and logged.
419+
420+
Parameters:
421+
- `mod_name`: display name, DLL file name (`example.dll`), or file stem (`example`).
422+
423+
Return value: `0` on success, non-zero on failure.
424+
425+
Example:
426+
427+
```c
428+
if (api->reload_mod) {
429+
int ret = api->reload_mod("Example Mod");
430+
if (ret != 0) api->log_error("reload failed");
431+
}
432+
```
433+
434+
External trigger: create `mods/reload.flag` to reload all currently loaded mods. The loader monitor thread deletes the flag after processing.
435+
406436
## Mod exports
407437

408438
All exports are optional except that mods needing the API should export `chumod_init`. Plain DLLs with only `DllMain` are still loaded.
@@ -416,6 +446,7 @@ CHUMOD_API const char* chumod_version(void);
416446
CHUMOD_API const char* chumod_author(void);
417447
CHUMOD_API const char* chumod_min_loader_version(void);
418448
CHUMOD_API void chumod_on_ready(void);
449+
CHUMOD_API void chumod_on_frame(void);
419450
```
420451
421452
| Export | Loader behavior |
@@ -428,6 +459,7 @@ CHUMOD_API void chumod_on_ready(void);
428459
| `chumod_author` | Returns mod author metadata. |
429460
| `chumod_min_loader_version` | Returns minimum required loader version, e.g. `"2.1.0"`. |
430461
| `chumod_on_ready` | Called after all successful `chumod_init` calls finish. |
462+
| `chumod_on_frame` | Called by the loader fallback frame loop after `chumod_on_ready`; current implementation uses a 16 ms interval thread. |
431463
432464
Example:
433465

docs/api-reference_cn.md

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
# ChuModLoader API 参考(v2.5.0)
1+
# ChuModLoader API 参考(v3.0.0)
22

3-
本文档说明 ChuModLoader v2.5.0 暴露给 Mod 的 C ABI。ABI 采用只追加字段的兼容策略:旧 Mod 可以继续工作,新 Mod 使用较新字段前应检查 `ChuModAPI::struct_size`
3+
本文档说明 ChuModLoader v3.0.0 暴露给 Mod 的 C ABI。ABI 采用只追加字段的兼容策略:旧 Mod 可以继续工作,新 Mod 使用较新字段前应检查 `ChuModAPI::struct_size`
44

55
C/C++ 项目请包含 `include/chumod.h`。Rust 或其他语言需要镜像相同的 `#[repr(C)]` 布局和 `extern "C"` 函数签名。
66

@@ -35,8 +35,8 @@ typedef struct {
3535

3636
| 字段 | 说明 |
3737
| --- | --- |
38-
| `api_version` | Loader ABI 版本。v2.5.0 为 `CHUMOD_API_VERSION`(`3`)。 |
39-
| `loader_version` | Loader 包版本字符串,例如 `"2.5.0"`。 |
38+
| `api_version` | Loader ABI 版本。v3.0.0 为 `CHUMOD_API_VERSION`(`3`)。 |
39+
| `loader_version` | Loader 包版本字符串,例如 `"3.0.0"`。 |
4040
| `game_module` | 游戏主程序模块名,通常为 `"chusanApp.exe"`;可能为 `NULL`。 |
4141
| `game_base` | 游戏镜像基址,找不到模块时为 `0`。 |
4242
| `game_size` | 游戏镜像大小。 |
@@ -91,6 +91,9 @@ typedef struct {
9191
ChuModTomlGetFloatFunc toml_get_float;
9292
ChuModTomlGetStringFunc toml_get_string;
9393
ChuModGetManifestPathFunc get_manifest_path;
94+
95+
/* v3 */
96+
ChuModReloadModFunc reload_mod;
9497
} ChuModAPI;
9598
```
9699

@@ -104,6 +107,33 @@ if (api->struct_size >= offsetof(ChuModAPI, log_info) + sizeof(api->log_info) &&
104107
}
105108
```
106109

110+
## v3 API
111+
112+
### 热重载
113+
114+
```c
115+
typedef int (*ChuModReloadModFunc)(const char* mod_name);
116+
int reload_mod(const char* mod_name);
117+
```
118+
119+
按显示名、DLL 文件名或文件 stem 热重载一个当前已加载的 Mod。Loader 会调用目标 Mod 的 `chumod_shutdown`,用 `FreeLibrary` 卸载 DLL,再重新加载,并调用 `chumod_init` 和可选的 `chumod_on_ready`。整个流程会被 panic guard 包裹并记录日志。
120+
121+
参数:
122+
- `mod_name`:显示名、DLL 文件名(`example.dll`)或文件 stem(`example`)。
123+
124+
返回值:成功为 `0`,失败为非 `0`。
125+
126+
示例:
127+
128+
```c
129+
if (api->reload_mod) {
130+
int ret = api->reload_mod("Example Mod");
131+
if (ret != 0) api->log_error("reload failed");
132+
}
133+
```
134+
135+
外部触发:创建 `mods/reload.flag` 会热重载所有当前已加载 Mod。Loader 监视线程处理后会删除该 flag。
136+
107137
## v1 API
108138

109139
### 日志
@@ -416,6 +446,7 @@ CHUMOD_API const char* chumod_version(void);
416446
CHUMOD_API const char* chumod_author(void);
417447
CHUMOD_API const char* chumod_min_loader_version(void);
418448
CHUMOD_API void chumod_on_ready(void);
449+
CHUMOD_API void chumod_on_frame(void);
419450
```
420451
421452
| 导出 | Loader 行为 |
@@ -428,6 +459,7 @@ CHUMOD_API void chumod_on_ready(void);
428459
| `chumod_author` | 返回 Mod 作者元数据。 |
429460
| `chumod_min_loader_version` | 返回最低 Loader 版本要求,例如 `"2.1.0"`。 |
430461
| `chumod_on_ready` | 所有成功的 `chumod_init` 完成后调用。 |
462+
| `chumod_on_frame` | `chumod_on_ready` 之后由 Loader 兜底帧循环调用;当前实现使用 16ms 间隔线程。 |
431463
432464
示例:
433465

docs/mod-development.md

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# ChuModLoader Mod Development Guide (v2.5.0)
1+
# ChuModLoader Mod Development Guide (v3.0.0)
22

33
ChuModLoader is a `version.dll` proxy that loads mod DLLs from `mods/` when `chusanApp.exe` starts. Mods can be written in several ways and can opt into progressively richer APIs.
44

@@ -19,13 +19,16 @@ LoadLibrary(mod.dll)
1919
-> optional metadata/dependency exports are read
2020
-> chumod_init(info, api)
2121
-> after every successful mod init: chumod_on_ready()
22+
-> optional repeated frame event: chumod_on_frame()
2223
-> game keeps running
2324
-> chumod_shutdown()
2425
-> FreeLibrary(mod.dll)
2526
```
2627

2728
Use `chumod_init` for local setup and hook creation. Use `chumod_on_ready` when you need other mods' services to exist. Use `chumod_shutdown` to disable hooks and release resources.
2829

30+
`chumod_on_frame` is optional. v3.0.0 uses a 16 ms fallback frame loop after `chumod_on_ready` for mods that export it.
31+
2932
## Quick Start: Rust
3033

3134
```rust
@@ -80,6 +83,7 @@ pub struct ChuModAPI {
8083
pub toml_get_float: Option<unsafe extern "C" fn(*const c_char, *const c_char, f32) -> f32>,
8184
pub toml_get_string: usize,
8285
pub get_manifest_path: Option<unsafe extern "C" fn() -> *const c_char>,
86+
pub reload_mod: Option<unsafe extern "C" fn(*const c_char) -> i32>,
8387
}
8488

8589
static mut API: *const ChuModAPI = std::ptr::null();
@@ -176,6 +180,10 @@ CHUMOD_API void chumod_on_ready() {
176180
if (g_api) g_api->log_info("All mods are ready");
177181
}
178182

183+
CHUMOD_API void chumod_on_frame() {
184+
// called from the loader fallback frame loop
185+
}
186+
179187
CHUMOD_API void chumod_shutdown() {
180188
if (g_api) g_api->log_info("C++ mod shutdown");
181189
}
@@ -267,7 +275,7 @@ The loader sorts mods before calling `chumod_init`. If dependencies cannot be sa
267275

268276
## Crash protection
269277

270-
ChuModLoader wraps `chumod_init`, `chumod_on_ready`, and `chumod_shutdown` with Rust `catch_unwind`. This protects against Rust panics crossing the loader boundary. It does **not** make arbitrary memory faults safe: access violations in native code can still crash the process.
278+
ChuModLoader wraps `chumod_init`, `chumod_on_ready`, `chumod_on_frame`, and `chumod_shutdown` with Rust `catch_unwind`. v3.0.0 also installs a top-level SEH filter that writes minidumps and readable crash logs to `mods/crash/`. This does **not** make arbitrary memory faults safe: access violations in native code can still terminate the process after the dump is written.
271279

272280
Guidelines:
273281

@@ -321,3 +329,15 @@ CHUMOD_API const char* chumod_min_loader_version() {
321329
```
322330

323331
Also guard individual fields with `struct_size` and null checks when distributing binaries to users with unknown loader versions.
332+
333+
## Hot reload
334+
335+
v3.0.0 adds `api->reload_mod`. It reloads an already-loaded mod by display name, file name, or file stem.
336+
337+
```c
338+
if (api->reload_mod) {
339+
api->reload_mod("C++ Example");
340+
}
341+
```
342+
343+
You can also create `mods/reload.flag` to reload all currently loaded mods. The loader removes the flag after processing.

docs/mod-development_cn.md

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# ChuModLoader Mod 开发指南(v2.5.0)
1+
# ChuModLoader Mod 开发指南(v3.0.0)
22

33
ChuModLoader 是一个 `version.dll` 代理,会在 `chusanApp.exe` 启动时从 `mods/` 加载 Mod DLL。Mod 可以用多种方式编写,并按需接入更丰富的 API。
44

@@ -19,13 +19,16 @@ LoadLibrary(mod.dll)
1919
-> 读取可选 metadata/dependency 导出
2020
-> chumod_init(info, api)
2121
-> 所有成功初始化的 Mod 完成后:chumod_on_ready()
22+
-> 可选重复帧事件:chumod_on_frame()
2223
-> 游戏运行中
2324
-> chumod_shutdown()
2425
-> FreeLibrary(mod.dll)
2526
```
2627

2728
`chumod_init` 适合本地初始化和 hook 创建。需要等待其他 Mod 服务存在时,使用 `chumod_on_ready``chumod_shutdown` 中应禁用 hook 并释放资源。
2829

30+
`chumod_on_frame` 是可选导出。v3.0.0 会在 `chumod_on_ready` 之后,对导出它的 Mod 启动 16ms 间隔的兜底帧循环。
31+
2932
## Quick Start:Rust
3033

3134
```rust
@@ -80,6 +83,7 @@ pub struct ChuModAPI {
8083
pub toml_get_float: Option<unsafe extern "C" fn(*const c_char, *const c_char, f32) -> f32>,
8184
pub toml_get_string: usize,
8285
pub get_manifest_path: Option<unsafe extern "C" fn() -> *const c_char>,
86+
pub reload_mod: Option<unsafe extern "C" fn(*const c_char) -> i32>,
8387
}
8488

8589
static mut API: *const ChuModAPI = std::ptr::null();
@@ -176,6 +180,10 @@ CHUMOD_API void chumod_on_ready() {
176180
if (g_api) g_api->log_info("All mods are ready");
177181
}
178182

183+
CHUMOD_API void chumod_on_frame() {
184+
// 由 Loader 兜底帧循环调用
185+
}
186+
179187
CHUMOD_API void chumod_shutdown() {
180188
if (g_api) g_api->log_info("C++ mod shutdown");
181189
}
@@ -267,7 +275,7 @@ Loader 会在调用 `chumod_init` 前排序 Mod。如果依赖无法满足,Loa
267275

268276
## 崩溃保护
269277

270-
ChuModLoader 使用 Rust `catch_unwind` 包裹 `chumod_init``chumod_on_ready``chumod_shutdown`这能防止 Rust panic 跨越 Loader 边界,但**不能**保证任意内存错误安全:native 代码中的访问冲突仍可能导致进程崩溃
278+
ChuModLoader 使用 Rust `catch_unwind` 包裹 `chumod_init``chumod_on_ready``chumod_on_frame``chumod_shutdown`v3.0.0 还会安装顶层 SEH 过滤器,把 minidump 和可读 crash log 写到 `mods/crash/`。这**不能**保证任意内存错误安全:native 代码访问冲突仍可能在写出 dump 后终止进程
271279

272280
建议:
273281

@@ -321,3 +329,15 @@ CHUMOD_API const char* chumod_min_loader_version() {
321329
```
322330

323331
面向未知 Loader 版本用户分发二进制时,也要通过 `struct_size` 和空指针检查保护单个字段。
332+
333+
## 热重载
334+
335+
v3.0.0 新增 `api->reload_mod`。它可以按显示名、文件名或文件 stem 热重载一个已加载 Mod。
336+
337+
```c
338+
if (api->reload_mod) {
339+
api->reload_mod("C++ Example");
340+
}
341+
```
342+
343+
也可以创建 `mods/reload.flag` 触发所有当前已加载 Mod 热重载。Loader 处理完会删除该 flag。

include/chumod.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,9 @@ typedef int (*ChuModTomlGetStringFunc)(const char* section, const char* key, c
122122
/** @brief Return current mod manifest path, or NULL. / 返回当前 mod 的 manifest 路径,不存在则 NULL。 */
123123
typedef const char* (*ChuModGetManifestPathFunc)(void);
124124

125+
/** @brief Reload a loaded mod by display name, file name, or file stem. Returns 0 on success. / 按显示名、文件名或文件 stem 热重载已加载 mod,0 表示成功。 */
126+
typedef int (*ChuModReloadModFunc)(const char* mod_name);
127+
125128
/**
126129
* @brief API function table provided by loader.
127130
* @brief Loader 提供给 mod 的 API 函数表。
@@ -184,6 +187,9 @@ typedef struct {
184187

185188
/** v2.5: manifest path API / v2.5: manifest 路径 API。 */
186189
ChuModGetManifestPathFunc get_manifest_path;
190+
191+
/** v3: hot reload API / v3: 热重载 API。 */
192+
ChuModReloadModFunc reload_mod;
187193
} ChuModAPI;
188194

189195
/**
@@ -193,6 +199,8 @@ typedef struct {
193199
typedef int (*ChuModInitFunc)(const ChuModInfo* info, const ChuModAPI* api);
194200
/** @brief Optional ready event called after all chumod_init calls finish. / 所有 chumod_init 完成后调用的可选就绪事件。 */
195201
typedef void (*ChuModReadyFunc)(void);
202+
/** @brief Optional frame event, called from loader fallback frame loop. / 可选帧事件,由 Loader 兜底帧循环调用。 */
203+
typedef void (*ChuModFrameFunc)(void);
196204
/** @brief Shutdown function called during loader unload. / Loader 卸载时调用的清理函数。 */
197205
typedef void (*ChuModShutdownFunc)(void);
198206
/** @brief Optional display name export. / 可选显示名导出。 */
@@ -208,6 +216,7 @@ typedef const char* (*ChuModMinLoaderVersionFunc)(void);
208216

209217
#define CHUMOD_INIT_NAME "chumod_init"
210218
#define CHUMOD_ON_READY_NAME "chumod_on_ready"
219+
#define CHUMOD_ON_FRAME_NAME "chumod_on_frame"
211220
#define CHUMOD_SHUTDOWN_NAME "chumod_shutdown"
212221
#define CHUMOD_NAME_NAME "chumod_name"
213222
#define CHUMOD_DEPENDS_NAME "chumod_depends"

src/types.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::ffi::{c_char, c_void};
22

33
pub const CHUMOD_API_VERSION: u32 = 3;
4-
pub const LOADER_VERSION: &str = "2.5.0";
4+
pub const LOADER_VERSION: &str = "3.0.0";
55

66
#[repr(C)]
77
pub struct ChuModInfo {

0 commit comments

Comments
 (0)