- 文字版执行流程图
[main()]
│
├─> OcrManager.__init__(wechat_dir)
│ │
│ ├─> 输入:wechat_dir (微信安装目录)
│ ├─> 输出:初始化后的OcrManager实例
│ ├─> 内部流程:
│ │ ├─> platform.architecture() → 判断系统架构
│ │ ├─> os.path.join() → 构造mmmojo_dllpath
│ │ ├─> MmmojoDll.__init__(mmmojo_dllpath)
│ │ │ ├─> CDLL加载DLL文件
│ │ │ └─> init_funcs() 加载28个函数指针
│ │ ├─> Queue(OCR_MAX_TASK_ID) → 初始化任务队列
│ │ └─> m_id_path = {} 初始化任务字典
│ │
├─> SetExePath(wechat_ocr_dir)
│ │
│ ├─> 输入:exe_path (WeChatOCR.exe路径)
│ ├─> 输出:设置self.m_exe_path
│ ├─> 内部检查:
│ │ ├─ if not exe_path.endswith("WeChatOCR.exe") → 自动补全路径
│ │ └─ os.path.exists() 验证路径有效性
│ │
├─> SetUsrLibDir(wechat_dir)
│ │
│ ├─> 输入:usr_lib_dir (微信主程序目录)
│ ├─> 输出:设置self.m_usr_lib_dir
│ ├─> 调用链:
│ │ └─> AppendSwitchNativeCmdLine("user-lib-dir", usr_lib_dir)
│ │ ├─> 输入:arg="user-lib-dir", value=usr_lib_dir
│ │ └─> 输出:self.m_switch_native字典添加条目
│ │
├─> StartWeChatOCR()
│ │
│ ├─> 关键调用链:
│ │ ├─> InitMMMojoEnv()
│ │ │ ├─> self._dll.InitializeMMMojo(0, None)
│ │ │ │ ├─> 输入:argc=0, argv=None
│ │ │ │ └─> 输出:初始化Mojo底层环境
│ │ │ │
│ │ │ ├─> CreateMMMojoEnvironment()
│ │ │ │ ├─> 输入:无
│ │ │ │ └─> 输出:c_void_p环境指针
│ │ │ │
│ │ │ ├─> SetMMMojoEnvironmentCallbacks()
│ │ │ │ ├─> 输入:
│ │ │ │ │ - env_ptr: 环境指针
│ │ │ │ │ - callback_type: kMMUserData
│ │ │ │ │ - py_object(self)
│ │ │ │ └─> 输出:设置用户数据指针
│ │ │ │
│ │ │ ├─> SetDefaultCallbacks()
│ │ │ │ ├─> 遍历MMMojoEnvironmentCallbackType枚举
│ │ │ │ │ └─> 对每个类型设置回调:
│ │ │ │ │ ├─> 获取回调函数地址
│ │ │ │ │ └─> SetMMMojoEnvironmentCallbacks()
│ │ │ │ └─> 输出:完成4个核心回调注册
│ │ │ │
│ │ │ └─> StartMMMojoEnvironment()
│ │ │ ├─> 输入:env_ptr
│ │ │ └─> 输出:启动WeChatOCR.exe子进程
│ │ │
│ ├─> 状态变更:
│ │ └─> m_wechatocr_running = True
│ │
├─> DoOCRTask(pic_path)
│ │
│ ├─> 输入:pic_path (图片路径)
│ ├─> 输出:发送OCR任务到子进程
│ ├─> 详细流程:
│ │ ├─> os.path.abspath() 标准化路径
│ │ ├─> while循环等待m_connect_state.value变为True
│ │ ├─> GetIdleTaskId()
│ │ │ ├─> 从Queue获取可用ID (阻塞1秒)
│ │ │ └─> 返回task_id或None
│ │ ├─> SendOCRTask()
│ │ │ ├─> 构造ocr_protobuf_pb2.OcrRequest对象
│ │ │ │ ├─> task_id分配
│ │ │ │ └─> pic_path添加到pic_paths
│ │ │ ├─> SerializeToString() 序列化
│ │ │ └─> SendPbSerializedData()
│ │ │ ├─> 调用DLL函数:
│ │ │ │ ├─> CreateMMMojoWriteInfo()
│ │ │ │ │ ├─> 输入:method=kMMPush
│ │ │ │ │ └─> 输出:write_info指针
│ │ │ │ │
│ │ │ │ ├─> GetMMMojoWriteInfoRequest()
│ │ │ │ │ ├─> 输入:write_info, pb_size
│ │ │ │ │ └─> 输出:request内存指针
│ │ │ │ │
│ │ │ │ ├─> memmove() 数据拷贝
│ │ │ │ └─> SendMMMojoWriteInfo()
│ │ │ │ ├─> 输入:env_ptr, write_info
│ │ │ │ └─> 输出:发送成功状态
│ │ │ │
│ │ ├─> 记录任务ID到m_id_path字典
│ │
├─> [回调触发] OCRReadOnPush()
│ │
│ ├─> 输入参数:
│ │ - request_id: c_uint32
│ │ - request_info: c_void_p
│ │ - user_data: py_object
│ ├─> 处理流程:
│ │ ├─> GetPbSerializedData()
│ │ │ ├─> 调用DLL函数:
│ │ │ │ └─> GetMMMojoReadInfoRequest()
│ │ │ │ ├─> 输入:request_info指针
│ │ │ │ └─> 输出:pb_data指针和data_size
│ │ │ │
│ │ ├─> 构造ocr_response_ubyte数组
│ │ ├─> ParseFromString() 反序列化Protobuf
│ │ ├─> parse_json_response()
│ │ │ ├─> 输入:json_response_str
│ │ │ └─> 输出:结构化OCR结果字典
│ │ ├─> 调用用户回调ocr_result_callback()
│ │ └─> SetTaskIdIdle() 回收任务ID
│ │
└─> KillWeChatOCR()
│
├─> 关键调用链:
│ ├─> StopMMMojoEnvironment()
│ │ ├─> 输入:env_ptr
│ │ └─> 输出:停止消息循环
│ │
│ ├─> RemoveMMMojoEnvironment()
│ │ ├─> 输入:env_ptr
│ │ └─> 输出:释放环境资源
│ │
│ └─> 状态重置:
│ ├─> m_connect_state.value = False
│ └─> m_wechatocr_running = False