fix: use _wfopen for non-ASCII log paths on Windows#1326
Conversation
Tasker.set_log_dir encoded the path as UTF-8 but passed the character count to MaaGlobalSetOption. Non-ASCII paths were truncated before native path conversion on Windows, which could surface as an uncaught C++ filesystem exception. Use the encoded byte length and cover set_log_dir with a non-ASCII path in the binding test.
When the log directory path contains non-ASCII characters (e.g. CJK), path.string() converts the internal wstring to narrow using the system active code page (ACP), not UTF-8. On Chinese Windows (ACP=936/GBK), this produces garbled bytes that cause fopen to throw an exception. Using _wfopen with the wide string path directly preserves the characters regardless of ACP setting. Fixes Python binding test crash when set_log_dir is called with a path containing CJK characters on Windows.
There was a problem hiding this comment.
Hey - 我发现了 1 个问题
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location path="source/binding/Python/maa/tasker.py" line_range="648-653" />
<code_context>
bool: 是否成功 / Whether successful
"""
- strpath = str(path)
+ encoded_path_bytes = str(path).encode("utf-8")
return bool(
Library.framework().MaaGlobalSetOption(
MaaOption(MaaGlobalOptionEnum.LogDir),
- strpath.encode(),
- len(strpath),
+ encoded_path_bytes,
+ len(encoded_path_bytes),
)
)
</code_context>
<issue_to_address>
**suggestion:** 建议在编码之前使用 `os.fspath(path)` 而不是 `str(path)`,以更好地支持所有类路径对象。
`str(path)` 适用于 `str` 和 `Path`,但 `os.fspath(path)` 是处理任意类路径对象(包括实现了 `__fspath__` 的对象)的标准方式。例如:
```python
from os import fspath
encoded_path_bytes = fspath(path).encode("utf-8")
```
建议的实现:
```python
Returns:
bool: 是否成功 / Whether successful
"""
encoded_path_bytes = fspath(path).encode("utf-8")
return bool(
Library.framework().MaaGlobalSetOption(
MaaOption(MaaGlobalOptionEnum.LogDir),
encoded_path_bytes,
len(encoded_path_bytes),
)
)
```
你还需要确保在 `source/binding/Python/maa/tasker.py` 文件顶部导入 `fspath`,例如:
```python
from os import fspath
```
把它加在其他导入语句旁边(如果已经存在则避免重复导入)。
</issue_to_address>帮我变得更有用!请在每条评论上点 👍 或 👎,我会根据你的反馈改进后续评审。
Original comment in English
Hey - I've found 1 issue
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location path="source/binding/Python/maa/tasker.py" line_range="648-653" />
<code_context>
bool: 是否成功 / Whether successful
"""
- strpath = str(path)
+ encoded_path_bytes = str(path).encode("utf-8")
return bool(
Library.framework().MaaGlobalSetOption(
MaaOption(MaaGlobalOptionEnum.LogDir),
- strpath.encode(),
- len(strpath),
+ encoded_path_bytes,
+ len(encoded_path_bytes),
)
)
</code_context>
<issue_to_address>
**suggestion:** Consider using `os.fspath(path)` instead of `str(path)` before encoding to better support all path-like objects.
`str(path)` covers `str` and `Path`, but `os.fspath(path)` is the standard way to handle any path-like object (including those with `__fspath__`). For example:
```python
from os import fspath
encoded_path_bytes = fspath(path).encode("utf-8")
```
Suggested implementation:
```python
Returns:
bool: 是否成功 / Whether successful
"""
encoded_path_bytes = fspath(path).encode("utf-8")
return bool(
Library.framework().MaaGlobalSetOption(
MaaOption(MaaGlobalOptionEnum.LogDir),
encoded_path_bytes,
len(encoded_path_bytes),
)
)
```
You also need to ensure `fspath` is imported at the top of `source/binding/Python/maa/tasker.py`, for example:
```python
from os import fspath
```
Add this alongside the other imports (and avoid duplicating it if it's already present).
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
| encoded_path_bytes = str(path).encode("utf-8") | ||
| return bool( | ||
| Library.framework().MaaGlobalSetOption( | ||
| MaaOption(MaaGlobalOptionEnum.LogDir), | ||
| strpath.encode(), | ||
| len(strpath), | ||
| encoded_path_bytes, | ||
| len(encoded_path_bytes), |
There was a problem hiding this comment.
suggestion: 建议在编码之前使用 os.fspath(path) 而不是 str(path),以更好地支持所有类路径对象。
str(path) 适用于 str 和 Path,但 os.fspath(path) 是处理任意类路径对象(包括实现了 __fspath__ 的对象)的标准方式。例如:
from os import fspath
encoded_path_bytes = fspath(path).encode("utf-8")建议的实现:
Returns:
bool: 是否成功 / Whether successful
"""
encoded_path_bytes = fspath(path).encode("utf-8")
return bool(
Library.framework().MaaGlobalSetOption(
MaaOption(MaaGlobalOptionEnum.LogDir),
encoded_path_bytes,
len(encoded_path_bytes),
)
)你还需要确保在 source/binding/Python/maa/tasker.py 文件顶部导入 fspath,例如:
from os import fspath把它加在其他导入语句旁边(如果已经存在则避免重复导入)。
Original comment in English
suggestion: Consider using os.fspath(path) instead of str(path) before encoding to better support all path-like objects.
str(path) covers str and Path, but os.fspath(path) is the standard way to handle any path-like object (including those with __fspath__). For example:
from os import fspath
encoded_path_bytes = fspath(path).encode("utf-8")Suggested implementation:
Returns:
bool: 是否成功 / Whether successful
"""
encoded_path_bytes = fspath(path).encode("utf-8")
return bool(
Library.framework().MaaGlobalSetOption(
MaaOption(MaaGlobalOptionEnum.LogDir),
encoded_path_bytes,
len(encoded_path_bytes),
)
)You also need to ensure fspath is imported at the top of source/binding/Python/maa/tasker.py, for example:
from os import fspathAdd this alongside the other imports (and avoid duplicating it if it's already present).
- Use os.fspath(path) instead of str(path) in Python binding to support any path-like object (including those with __fspath__) - Add null check after _wfopen in Logger::open() to avoid undefined behavior when file open fails
|
Closing in favor of #1310 |
问题
在 Windows 上,当
set_log_dir的路径包含非 ASCII 字符(如中文新建文件夹)时,Python 绑定测试会崩溃,抛出OSError: 0xe06d7363。原因
Logger::open()中使用fopen打开日志文件时,通过path.string()将内部std::wstring转换为窄字符串。在 Windows 上,这个转换使用的是系统活动代码页(ACP),而非 UTF-8。在中文 Windows(ACP=936/GBK)上,UTF-8 导出的宽字符串再通过 GBK 转回窄字符串会产生乱码,导致
fopen失败并抛出 C++ 异常。日志也印证了这一点:
log_dir_=C:/MaaFramework/install/bin/debug/?????修复
将
fopen改为_wfopen,直接使用宽字符串路径,绕过有损的.string()转换:相关
Summary by Sourcery
确保 Python 绑定正确传递 UTF-8 编码的日志目录路径,并扩展测试以覆盖包含非 ASCII 字符的 Windows 路径。
Bug Fixes:
Tasker.set_log_dir,使其向底层框架发送 UTF-8 编码的路径,避免在使用含非 ASCII 字符的目录时发生崩溃。Tests:
Chores:
Original summary in English
Summary by Sourcery
Ensure Python bindings correctly pass UTF-8 encoded log directory paths and extend tests to cover non-ASCII Windows paths.
Bug Fixes:
Tests:
Chores: