wx-ocr 0.1.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- wx_ocr/__init__.py +139 -0
- wx_ocr/cli.py +296 -0
- wx_ocr/default_callback.py +45 -0
- wx_ocr/mmmojo_dll.py +175 -0
- wx_ocr/ocr_manager.py +160 -0
- wx_ocr/ocr_protobuf_pb2.py +39 -0
- wx_ocr/simple_api.py +303 -0
- wx_ocr/utility_protobuf_pb2.py +39 -0
- wx_ocr/utils.py +161 -0
- wx_ocr/wco_data/Model/FPOCRRecog.xnet +0 -0
- wx_ocr/wco_data/Model/OCRDetFP32.xnet.nas +0 -0
- wx_ocr/wco_data/Model/OCRParaDetV1.1.0.26.xnet +0 -0
- wx_ocr/wco_data/Model/OCRRecogFP32V1.1.0.26.xnet +0 -0
- wx_ocr/wco_data/Model/RecDict +12043 -0
- wx_ocr/wco_data/Model/sohu_simp.txt +5031 -0
- wx_ocr/wco_data/WeChatOCR.exe +0 -0
- wx_ocr/wco_data/mmmojo.dll +0 -0
- wx_ocr/wco_data/mmmojo_64.dll +0 -0
- wx_ocr/wco_data/x64.config +1 -0
- wx_ocr/winapi.py +195 -0
- wx_ocr/xplugin_manager.py +194 -0
- wx_ocr-0.1.3.dist-info/METADATA +84 -0
- wx_ocr-0.1.3.dist-info/RECORD +27 -0
- wx_ocr-0.1.3.dist-info/WHEEL +5 -0
- wx_ocr-0.1.3.dist-info/entry_points.txt +2 -0
- wx_ocr-0.1.3.dist-info/licenses/LICENSE +21 -0
- wx_ocr-0.1.3.dist-info/top_level.txt +1 -0
wx_ocr/__init__.py
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
"""
|
|
2
|
+
WeChat OCR - Python wrapper for WeChat's local OCR model
|
|
3
|
+
|
|
4
|
+
This package provides a Python interface to call WeChat's local OCR model
|
|
5
|
+
for text recognition in images.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from .ocr_manager import OcrManager, OCR_MAX_TASK_ID
|
|
9
|
+
from .utils import (
|
|
10
|
+
find_wechat_install_path,
|
|
11
|
+
find_wechat_ocr_path,
|
|
12
|
+
auto_find_wechat,
|
|
13
|
+
list_available_ocr_versions,
|
|
14
|
+
)
|
|
15
|
+
from .simple_api import ocr, ocr_batch
|
|
16
|
+
|
|
17
|
+
__version__ = "0.1.0"
|
|
18
|
+
__all__ = [
|
|
19
|
+
"ocr", # 最简单的接口
|
|
20
|
+
"ocr_batch", # 批量处理接口
|
|
21
|
+
"OcrManager",
|
|
22
|
+
"OCR_MAX_TASK_ID",
|
|
23
|
+
"WeChatOCR",
|
|
24
|
+
"find_wechat_install_path",
|
|
25
|
+
"find_wechat_ocr_path",
|
|
26
|
+
"auto_find_wechat",
|
|
27
|
+
"list_available_ocr_versions",
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class WeChatOCR:
|
|
32
|
+
"""
|
|
33
|
+
Simplified interface for WeChat OCR.
|
|
34
|
+
|
|
35
|
+
Example:
|
|
36
|
+
>>> from wx_ocr import WeChatOCR
|
|
37
|
+
>>>
|
|
38
|
+
>>> ocr = WeChatOCR(wechat_dir="D:\\WeChat\\3.9.6.32")
|
|
39
|
+
>>> ocr.init_ocr(wechat_ocr_dir="C:\\...\\WeChatOCR.exe")
|
|
40
|
+
>>>
|
|
41
|
+
>>> results = []
|
|
42
|
+
>>> def callback(img_path, result):
|
|
43
|
+
... results.append(result)
|
|
44
|
+
>>>
|
|
45
|
+
>>> ocr.ocr("image.png", callback=callback)
|
|
46
|
+
>>> ocr.wait_for_completion()
|
|
47
|
+
>>> print(results)
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
def __init__(self, wechat_dir: str):
|
|
51
|
+
"""
|
|
52
|
+
Initialize WeChat OCR.
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
wechat_dir: Path to WeChat installation directory (contains mmmojo.dll)
|
|
56
|
+
"""
|
|
57
|
+
self._manager = OcrManager(wechat_dir)
|
|
58
|
+
self._started = False
|
|
59
|
+
|
|
60
|
+
def init_ocr(self, wechat_ocr_dir: str, wechat_dir: str = None) -> None:
|
|
61
|
+
"""
|
|
62
|
+
Initialize OCR service.
|
|
63
|
+
|
|
64
|
+
Args:
|
|
65
|
+
wechat_ocr_dir: Path to WeChatOCR.exe or its directory
|
|
66
|
+
wechat_dir: Path to directory containing mmmojo.dll (optional, uses __init__ value if not provided)
|
|
67
|
+
"""
|
|
68
|
+
import os
|
|
69
|
+
from pathlib import Path
|
|
70
|
+
|
|
71
|
+
# 设置 WeChatOCR.exe 路径
|
|
72
|
+
self._manager.SetExePath(wechat_ocr_dir)
|
|
73
|
+
|
|
74
|
+
# 设置 user-lib-dir (包含 mmmojo.dll 的目录)
|
|
75
|
+
if wechat_dir:
|
|
76
|
+
usr_lib_dir = wechat_dir
|
|
77
|
+
elif self._manager.m_usr_lib_dir:
|
|
78
|
+
usr_lib_dir = self._manager.m_usr_lib_dir
|
|
79
|
+
else:
|
|
80
|
+
# 如果 wechat_ocr_dir 是文件,使用其父目录
|
|
81
|
+
ocr_path = Path(wechat_ocr_dir)
|
|
82
|
+
if ocr_path.is_file():
|
|
83
|
+
usr_lib_dir = str(ocr_path.parent)
|
|
84
|
+
else:
|
|
85
|
+
usr_lib_dir = wechat_ocr_dir
|
|
86
|
+
|
|
87
|
+
self._manager.SetUsrLibDir(usr_lib_dir)
|
|
88
|
+
|
|
89
|
+
def start(self) -> None:
|
|
90
|
+
"""Start the OCR service."""
|
|
91
|
+
if not self._started:
|
|
92
|
+
self._manager.StartWeChatOCR()
|
|
93
|
+
self._started = True
|
|
94
|
+
|
|
95
|
+
def stop(self) -> None:
|
|
96
|
+
"""Stop the OCR service."""
|
|
97
|
+
if self._started:
|
|
98
|
+
self._manager.KillWeChatOCR()
|
|
99
|
+
self._started = False
|
|
100
|
+
|
|
101
|
+
def ocr(self, image_path: str, callback=None) -> None:
|
|
102
|
+
"""
|
|
103
|
+
Perform OCR on an image.
|
|
104
|
+
|
|
105
|
+
Args:
|
|
106
|
+
image_path: Path to the image file
|
|
107
|
+
callback: Optional callback function(img_path: str, result: dict)
|
|
108
|
+
"""
|
|
109
|
+
if not self._started:
|
|
110
|
+
self.start()
|
|
111
|
+
|
|
112
|
+
if callback:
|
|
113
|
+
self._manager.SetOcrResultCallback(callback)
|
|
114
|
+
|
|
115
|
+
self._manager.DoOCRTask(image_path)
|
|
116
|
+
|
|
117
|
+
def wait_for_completion(self, timeout: float = None) -> None:
|
|
118
|
+
"""
|
|
119
|
+
Wait for all OCR tasks to complete.
|
|
120
|
+
|
|
121
|
+
Args:
|
|
122
|
+
timeout: Maximum time to wait in seconds (None for no timeout)
|
|
123
|
+
"""
|
|
124
|
+
import time
|
|
125
|
+
start_time = time.time()
|
|
126
|
+
|
|
127
|
+
while self._manager.m_task_id.qsize() != OCR_MAX_TASK_ID:
|
|
128
|
+
if timeout and (time.time() - start_time) > timeout:
|
|
129
|
+
raise TimeoutError("OCR tasks did not complete within timeout")
|
|
130
|
+
time.sleep(0.1)
|
|
131
|
+
|
|
132
|
+
def __enter__(self):
|
|
133
|
+
"""Context manager entry."""
|
|
134
|
+
return self
|
|
135
|
+
|
|
136
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
137
|
+
"""Context manager exit."""
|
|
138
|
+
self.stop()
|
|
139
|
+
return False
|
wx_ocr/cli.py
ADDED
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Command-line interface for WeChat OCR.
|
|
3
|
+
"""
|
|
4
|
+
import sys
|
|
5
|
+
import json
|
|
6
|
+
import argparse
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from typing import List
|
|
9
|
+
|
|
10
|
+
from . import WeChatOCR, auto_find_wechat
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def main():
|
|
14
|
+
"""Main CLI entry point."""
|
|
15
|
+
parser = argparse.ArgumentParser(
|
|
16
|
+
description="WeChat OCR - Command Line Interface",
|
|
17
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
18
|
+
epilog="""
|
|
19
|
+
Examples:
|
|
20
|
+
# Process an image and output text to console
|
|
21
|
+
wx-ocr image.png
|
|
22
|
+
|
|
23
|
+
# Output as JSON
|
|
24
|
+
wx-ocr --format json image.png
|
|
25
|
+
|
|
26
|
+
# Process multiple images
|
|
27
|
+
wx-ocr image1.png image2.png image3.png
|
|
28
|
+
|
|
29
|
+
# Save results to files
|
|
30
|
+
wx-ocr --save image.png
|
|
31
|
+
wx-ocr --save --output results/ image.png
|
|
32
|
+
|
|
33
|
+
# Find WeChat paths
|
|
34
|
+
wx-ocr --find-paths
|
|
35
|
+
|
|
36
|
+
# Specify WeChat paths manually
|
|
37
|
+
wx-ocr --wechat-dir "D:\\WeChat" --ocr-dir "C:\\...\\WeChatOCR.exe" image.png
|
|
38
|
+
"""
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
parser.add_argument(
|
|
42
|
+
"images",
|
|
43
|
+
nargs="*",
|
|
44
|
+
help="Image files to process"
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
parser.add_argument(
|
|
48
|
+
"--wechat-dir",
|
|
49
|
+
help="WeChat installation directory"
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
parser.add_argument(
|
|
53
|
+
"--ocr-dir",
|
|
54
|
+
help="WeChatOCR.exe path or directory"
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
parser.add_argument(
|
|
58
|
+
"--format", "-f",
|
|
59
|
+
choices=["text", "json"],
|
|
60
|
+
default="text",
|
|
61
|
+
help="Output format: text (default) or json"
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
parser.add_argument(
|
|
65
|
+
"--save", "-s",
|
|
66
|
+
action="store_true",
|
|
67
|
+
help="Save results to files (default: output to console)"
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
parser.add_argument(
|
|
71
|
+
"--output", "-o",
|
|
72
|
+
default="./ocr_output",
|
|
73
|
+
help="Output directory when using --save (default: ./ocr_output)"
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
parser.add_argument(
|
|
77
|
+
"--find-paths",
|
|
78
|
+
action="store_true",
|
|
79
|
+
help="Find and display WeChat paths"
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
parser.add_argument(
|
|
83
|
+
"--quiet", "-q",
|
|
84
|
+
action="store_true",
|
|
85
|
+
help="Suppress progress messages (only show results)"
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
parser.add_argument(
|
|
89
|
+
"--version", "-v",
|
|
90
|
+
action="version",
|
|
91
|
+
version="wx-ocr 0.1.3"
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
args = parser.parse_args()
|
|
95
|
+
|
|
96
|
+
# Handle --find-paths
|
|
97
|
+
if args.find_paths:
|
|
98
|
+
find_paths_command()
|
|
99
|
+
return 0
|
|
100
|
+
|
|
101
|
+
# Validate images
|
|
102
|
+
if not args.images:
|
|
103
|
+
parser.print_help()
|
|
104
|
+
return 1
|
|
105
|
+
|
|
106
|
+
# Get WeChat paths - 优先使用项目自带的 wco_data
|
|
107
|
+
wechat_dir = args.wechat_dir
|
|
108
|
+
ocr_dir = args.ocr_dir
|
|
109
|
+
|
|
110
|
+
if not wechat_dir or not ocr_dir:
|
|
111
|
+
# 首先尝试使用项目自带的 wco_data
|
|
112
|
+
from pathlib import Path
|
|
113
|
+
package_dir = Path(__file__).parent
|
|
114
|
+
wco_data_dir = package_dir / "wco_data"
|
|
115
|
+
|
|
116
|
+
if wco_data_dir.exists() and (wco_data_dir / "WeChatOCR.exe").exists():
|
|
117
|
+
# 使用项目自带的
|
|
118
|
+
wechat_dir = wechat_dir or str(wco_data_dir)
|
|
119
|
+
ocr_dir = ocr_dir or str(wco_data_dir / "WeChatOCR.exe")
|
|
120
|
+
if not args.quiet:
|
|
121
|
+
print("使用项目自带的 OCR 文件", file=sys.stderr)
|
|
122
|
+
else:
|
|
123
|
+
# 如果项目自带的不存在,尝试查找系统安装的微信
|
|
124
|
+
if not args.quiet:
|
|
125
|
+
print("正在自动检测 WeChat 路径...", file=sys.stderr)
|
|
126
|
+
paths = auto_find_wechat()
|
|
127
|
+
wechat_dir = wechat_dir or paths.get("wechat_dir")
|
|
128
|
+
ocr_dir = ocr_dir or paths.get("wechat_ocr_dir")
|
|
129
|
+
|
|
130
|
+
if not wechat_dir or not ocr_dir:
|
|
131
|
+
print("错误: 无法找到 OCR 文件", file=sys.stderr)
|
|
132
|
+
print("", file=sys.stderr)
|
|
133
|
+
print("请确保:", file=sys.stderr)
|
|
134
|
+
print(" 1. 项目包含 wco_data 目录,或", file=sys.stderr)
|
|
135
|
+
print(" 2. 系统已安装微信,或", file=sys.stderr)
|
|
136
|
+
print(" 3. 使用 --wechat-dir 和 --ocr-dir 手动指定路径", file=sys.stderr)
|
|
137
|
+
return 1
|
|
138
|
+
|
|
139
|
+
# Process images
|
|
140
|
+
return process_images(
|
|
141
|
+
args.images,
|
|
142
|
+
wechat_dir,
|
|
143
|
+
ocr_dir,
|
|
144
|
+
output_format=args.format,
|
|
145
|
+
save_to_file=args.save,
|
|
146
|
+
output_dir=args.output,
|
|
147
|
+
quiet=args.quiet
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def find_paths_command():
|
|
152
|
+
"""Find and display WeChat paths."""
|
|
153
|
+
from pathlib import Path
|
|
154
|
+
|
|
155
|
+
print("正在查找 OCR 文件...\n")
|
|
156
|
+
|
|
157
|
+
# 首先检查项目自带的 wco_data
|
|
158
|
+
package_dir = Path(__file__).parent
|
|
159
|
+
wco_data_dir = package_dir / "wco_data"
|
|
160
|
+
|
|
161
|
+
if wco_data_dir.exists() and (wco_data_dir / "WeChatOCR.exe").exists():
|
|
162
|
+
print("✓ 找到项目自带的 OCR 文件:")
|
|
163
|
+
print(f" 目录: {wco_data_dir}")
|
|
164
|
+
print(f" WeChatOCR.exe: {wco_data_dir / 'WeChatOCR.exe'}")
|
|
165
|
+
print(f" mmmojo.dll: {wco_data_dir / 'mmmojo_64.dll'}")
|
|
166
|
+
print("\n这是推荐使用的方式,无需安装微信!")
|
|
167
|
+
else:
|
|
168
|
+
print("✗ 未找到项目自带的 OCR 文件")
|
|
169
|
+
|
|
170
|
+
# 然后查找系统安装的微信
|
|
171
|
+
print("\n正在查找系统安装的微信...")
|
|
172
|
+
paths = auto_find_wechat()
|
|
173
|
+
|
|
174
|
+
print("\n检测到的系统路径:")
|
|
175
|
+
print(f" WeChat 目录: {paths.get('wechat_dir') or '未找到'}")
|
|
176
|
+
print(f" WeChatOCR 目录: {paths.get('wechat_ocr_dir') or '未找到'}")
|
|
177
|
+
|
|
178
|
+
# List available versions
|
|
179
|
+
from .utils import list_available_ocr_versions
|
|
180
|
+
versions = list_available_ocr_versions()
|
|
181
|
+
|
|
182
|
+
if versions:
|
|
183
|
+
print(f"\n可用的 WeChatOCR 版本 ({len(versions)} 个):")
|
|
184
|
+
for i, version in enumerate(versions, 1):
|
|
185
|
+
print(f" {i}. {version}")
|
|
186
|
+
|
|
187
|
+
# 总结
|
|
188
|
+
print("\n" + "="*60)
|
|
189
|
+
if wco_data_dir.exists():
|
|
190
|
+
print("推荐:使用项目自带的 OCR 文件(无需安装微信)")
|
|
191
|
+
elif paths.get('wechat_dir') and paths.get('wechat_ocr_dir'):
|
|
192
|
+
print("可以使用系统安装的微信 OCR")
|
|
193
|
+
else:
|
|
194
|
+
print("未找到可用的 OCR 文件")
|
|
195
|
+
print("请确保项目包含 wco_data 目录或安装微信")
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
def process_images(
|
|
199
|
+
image_paths: List[str],
|
|
200
|
+
wechat_dir: str,
|
|
201
|
+
ocr_dir: str,
|
|
202
|
+
output_format: str = "text",
|
|
203
|
+
save_to_file: bool = False,
|
|
204
|
+
output_dir: str = "./ocr_output",
|
|
205
|
+
quiet: bool = False
|
|
206
|
+
) -> int:
|
|
207
|
+
"""Process images with OCR."""
|
|
208
|
+
# Filter valid images
|
|
209
|
+
valid_images = []
|
|
210
|
+
for img_path in image_paths:
|
|
211
|
+
if Path(img_path).exists():
|
|
212
|
+
valid_images.append(img_path)
|
|
213
|
+
else:
|
|
214
|
+
print(f"警告: 图片不存在: {img_path}", file=sys.stderr)
|
|
215
|
+
|
|
216
|
+
if not valid_images:
|
|
217
|
+
print("错误: 没有有效的图片可处理", file=sys.stderr)
|
|
218
|
+
return 1
|
|
219
|
+
|
|
220
|
+
# Create output directory if saving to file
|
|
221
|
+
if save_to_file:
|
|
222
|
+
output_path = Path(output_dir)
|
|
223
|
+
output_path.mkdir(parents=True, exist_ok=True)
|
|
224
|
+
|
|
225
|
+
if not quiet:
|
|
226
|
+
print(f"正在处理 {len(valid_images)} 张图片...\n", file=sys.stderr)
|
|
227
|
+
|
|
228
|
+
# Store results
|
|
229
|
+
all_results = []
|
|
230
|
+
processed = 0
|
|
231
|
+
|
|
232
|
+
try:
|
|
233
|
+
with WeChatOCR(wechat_dir=wechat_dir) as ocr:
|
|
234
|
+
ocr.init_ocr(wechat_ocr_dir=ocr_dir)
|
|
235
|
+
|
|
236
|
+
def callback(img_path: str, result: dict):
|
|
237
|
+
nonlocal processed
|
|
238
|
+
processed += 1
|
|
239
|
+
all_results.append((img_path, result))
|
|
240
|
+
|
|
241
|
+
# Submit all tasks
|
|
242
|
+
for img_path in valid_images:
|
|
243
|
+
ocr.ocr(img_path, callback=callback)
|
|
244
|
+
|
|
245
|
+
# Wait for completion
|
|
246
|
+
ocr.wait_for_completion(timeout=60)
|
|
247
|
+
|
|
248
|
+
# Output results
|
|
249
|
+
for img_path, result in all_results:
|
|
250
|
+
ocr_result = result.get("ocrResult", [])
|
|
251
|
+
|
|
252
|
+
if save_to_file:
|
|
253
|
+
# Save to file
|
|
254
|
+
result_file = output_path / f"{Path(img_path).name}.json"
|
|
255
|
+
with open(result_file, 'w', encoding='utf-8') as f:
|
|
256
|
+
json.dump(result, f, ensure_ascii=False, indent=2)
|
|
257
|
+
|
|
258
|
+
if not quiet:
|
|
259
|
+
print(f"✓ 已保存: {result_file}", file=sys.stderr)
|
|
260
|
+
else:
|
|
261
|
+
# Output to console
|
|
262
|
+
if len(valid_images) > 1:
|
|
263
|
+
# Multiple images: show filename
|
|
264
|
+
print(f"\n{'='*60}")
|
|
265
|
+
print(f"文件: {Path(img_path).name}")
|
|
266
|
+
print('='*60)
|
|
267
|
+
|
|
268
|
+
if output_format == "json":
|
|
269
|
+
# JSON format
|
|
270
|
+
print(json.dumps(result, ensure_ascii=False, indent=2))
|
|
271
|
+
else:
|
|
272
|
+
# Text format (default)
|
|
273
|
+
if ocr_result:
|
|
274
|
+
for item in ocr_result:
|
|
275
|
+
print(item['text'])
|
|
276
|
+
else:
|
|
277
|
+
print("(未识别到文字)")
|
|
278
|
+
|
|
279
|
+
if not quiet:
|
|
280
|
+
if save_to_file:
|
|
281
|
+
print(f"\n✓ 成功处理 {processed} 张图片", file=sys.stderr)
|
|
282
|
+
print(f"✓ 结果已保存到: {output_path.absolute()}", file=sys.stderr)
|
|
283
|
+
else:
|
|
284
|
+
print(f"\n✓ 成功处理 {processed} 张图片", file=sys.stderr)
|
|
285
|
+
|
|
286
|
+
return 0
|
|
287
|
+
|
|
288
|
+
except Exception as e:
|
|
289
|
+
print(f"错误: {e}", file=sys.stderr)
|
|
290
|
+
import traceback
|
|
291
|
+
traceback.print_exc()
|
|
292
|
+
return 1
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
if __name__ == "__main__":
|
|
296
|
+
sys.exit(main())
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
from .winapi import *
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
callbacks_def = {
|
|
5
|
+
# static void DefaultReadOnPush(uint32_t request_id, const void* request_info, void* user_data);
|
|
6
|
+
'kMMReadPush': CFUNCTYPE(void, c_uint32, c_void_p, c_void_p),
|
|
7
|
+
# static void DefaultReadOnPull(uint32_t request_id, const void* request_info, void* user_data);
|
|
8
|
+
'kMMReadPull': CFUNCTYPE(void, c_uint32, c_void_p, c_void_p),
|
|
9
|
+
# static void DefaultReadOnShared(uint32_t request_id, const void* request_info, void* user_data);
|
|
10
|
+
'kMMReadShared': CFUNCTYPE(void, c_uint32, c_void_p, c_void_p),
|
|
11
|
+
# static void DefaultRemoteOnConnect(bool is_connected, void* user_data);
|
|
12
|
+
'kMMRemoteConnect': CFUNCTYPE(void, c_bool, c_void_p),
|
|
13
|
+
# static void DefaultRemoteOnDisConnect(void* user_data);
|
|
14
|
+
'kMMRemoteDisconnect': CFUNCTYPE(void, c_void_p),
|
|
15
|
+
# static void DefaultRemoteOnProcessLaunched(void* user_data);
|
|
16
|
+
'kMMRemoteProcessLaunched': CFUNCTYPE(void, c_void_p),
|
|
17
|
+
# static void DefaultRemoteOnProcessLaunchFailed(int error_code, void* user_data);
|
|
18
|
+
'kMMRemoteProcessLaunchFailed': CFUNCTYPE(void, c_int, c_void_p),
|
|
19
|
+
# static void DefaultRemoteOnMojoError(const void* errorbuf, int errorsize, void* user_data);
|
|
20
|
+
'kMMRemoteMojoError': CFUNCTYPE(void, c_void_p, c_int, c_void_p)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
def DefaultReadPush(request_id:c_uint32, request_info:c_void_p, user_data: py_object):
|
|
24
|
+
pass
|
|
25
|
+
|
|
26
|
+
def DefaultReadPull(request_id:c_uint32, request_info:c_void_p, user_data: py_object):
|
|
27
|
+
pass
|
|
28
|
+
|
|
29
|
+
def DefaultReadShared(request_id:c_uint32, request_info:c_void_p, user_data: py_object):
|
|
30
|
+
pass
|
|
31
|
+
|
|
32
|
+
def DefaultRemoteConnect(is_connected:c_bool, user_data:py_object):
|
|
33
|
+
pass
|
|
34
|
+
|
|
35
|
+
def DefaultRemoteDisConnect(user_data:py_object):
|
|
36
|
+
pass
|
|
37
|
+
|
|
38
|
+
def DefaultRemoteProcessLaunched(user_data:py_object):
|
|
39
|
+
pass
|
|
40
|
+
|
|
41
|
+
def DefaultRemoteProcessLaunchFailed(error_code:c_int, user_data:py_object):
|
|
42
|
+
pass
|
|
43
|
+
|
|
44
|
+
def DefaultRemoteMojoError(errorbuf:c_void_p, errorsize:c_int, user_data:py_object):
|
|
45
|
+
pass
|
wx_ocr/mmmojo_dll.py
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
from enum import Enum,auto
|
|
2
|
+
from .winapi import *
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class MMMojoInfoMethod(Enum):
|
|
6
|
+
'''
|
|
7
|
+
typedef enum {
|
|
8
|
+
kMMNone = 0,
|
|
9
|
+
kMMPush,
|
|
10
|
+
kMMPullReq,
|
|
11
|
+
kMMPullResp,
|
|
12
|
+
kMMShared,
|
|
13
|
+
} MMMojoInfoMethod;
|
|
14
|
+
'''
|
|
15
|
+
kMMNone = 0
|
|
16
|
+
kMMPush = auto()
|
|
17
|
+
kMMPullReq = auto()
|
|
18
|
+
kMMPullResp = auto()
|
|
19
|
+
kMMShared = auto()
|
|
20
|
+
|
|
21
|
+
class MMMojoEnvironmentCallbackType(Enum):
|
|
22
|
+
'''
|
|
23
|
+
typedef enum {
|
|
24
|
+
kMMUserData = 0,
|
|
25
|
+
kMMReadPush,
|
|
26
|
+
kMMReadPull,
|
|
27
|
+
kMMReadShared,
|
|
28
|
+
kMMRemoteConnect,
|
|
29
|
+
kMMRemoteDisconnect,
|
|
30
|
+
kMMRemoteProcessLaunched,
|
|
31
|
+
kMMRemoteProcessLaunchFailed,
|
|
32
|
+
kMMRemoteMojoError,
|
|
33
|
+
} MMMojoEnvironmentCallbackType;
|
|
34
|
+
'''
|
|
35
|
+
kMMUserData = 0
|
|
36
|
+
kMMReadPush = auto()
|
|
37
|
+
kMMReadPull = auto()
|
|
38
|
+
kMMReadShared = auto()
|
|
39
|
+
kMMRemoteConnect = auto()
|
|
40
|
+
kMMRemoteDisconnect = auto()
|
|
41
|
+
kMMRemoteProcessLaunched = auto()
|
|
42
|
+
kMMRemoteProcessLaunchFailed = auto()
|
|
43
|
+
kMMRemoteMojoError = auto()
|
|
44
|
+
|
|
45
|
+
class MMMojoEnvironmentInitParamType(Enum):
|
|
46
|
+
'''
|
|
47
|
+
typedef enum {
|
|
48
|
+
kMMHostProcess = 0,
|
|
49
|
+
kMMLoopStartThread,
|
|
50
|
+
kMMExePath,
|
|
51
|
+
kMMLogPath,
|
|
52
|
+
kMMLogToStderr,
|
|
53
|
+
kMMAddNumMessagepipe,
|
|
54
|
+
kMMSetDisconnectHandlers,
|
|
55
|
+
#if defined(WIN32)
|
|
56
|
+
kMMDisableDefaultPolicy = 1000,
|
|
57
|
+
kMMElevated,
|
|
58
|
+
kMMCompatible,
|
|
59
|
+
#endif // defined(WIN32)
|
|
60
|
+
} MMMojoEnvironmentInitParamType;
|
|
61
|
+
'''
|
|
62
|
+
kMMHostProcess = 0
|
|
63
|
+
kMMLoopStartThread = auto()
|
|
64
|
+
kMMExePath = auto()
|
|
65
|
+
kMMLogPath = auto()
|
|
66
|
+
kMMLogToStderr = auto()
|
|
67
|
+
kMMAddNumMessagepipe = auto()
|
|
68
|
+
kMMSetDisconnectHandlers = auto()
|
|
69
|
+
kMMDisableDefaultPolicy = 1000
|
|
70
|
+
kMMElevated = auto()
|
|
71
|
+
kMMCompatible = auto()
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
class MmmojoDll(object):
|
|
75
|
+
def __init__(self, mmmojo_dllpath) -> None:
|
|
76
|
+
self._dll = CDLL(mmmojo_dllpath)
|
|
77
|
+
self._funcs_dict = self.init_funcs()
|
|
78
|
+
|
|
79
|
+
def func_def(self, *args):
|
|
80
|
+
return func_def(*args, dll=self._dll)
|
|
81
|
+
|
|
82
|
+
def init_funcs(self):
|
|
83
|
+
# void InitializeMMMojo(int argc, char* argv[])
|
|
84
|
+
# argv = (c_char_p * 3)(b'abc', b'def', b'ghi')
|
|
85
|
+
InitializeMMMojo = self.func_def("InitializeMMMojo", void, *(c_int, POINTER(c_char_p)))
|
|
86
|
+
# void ShutdownMMMojo()
|
|
87
|
+
ShutdownMMMojo = self.func_def("ShutdownMMMojo", void)
|
|
88
|
+
# void* CreateMMMojoEnvironment()
|
|
89
|
+
CreateMMMojoEnvironment = self.func_def("CreateMMMojoEnvironment", c_void_p)
|
|
90
|
+
# void SetMMMojoEnvironmentCallbacks(void* mmmojo_env,int type, ...)
|
|
91
|
+
SetMMMojoEnvironmentCallbacks = self.func_def("SetMMMojoEnvironmentCallbacks", void, *(c_void_p, c_int, py_object))
|
|
92
|
+
# void SetMMMojoEnvironmentInitParams(void* mmmojo_env,int type, ...);
|
|
93
|
+
SetMMMojoEnvironmentInitParams = self.func_def("SetMMMojoEnvironmentInitParams", void, *(c_void_p, c_int, c_void_p))
|
|
94
|
+
# void AppendMMSubProcessSwitchNative(void* mmmojo_env, const char* switch_string, const wchar_t* value);
|
|
95
|
+
AppendMMSubProcessSwitchNative = self.func_def("AppendMMSubProcessSwitchNative", void, *(c_void_p, c_char_p, c_wchar_p))
|
|
96
|
+
# void StartMMMojoEnvironment(void* mmmojo_env);
|
|
97
|
+
StartMMMojoEnvironment = self.func_def("StartMMMojoEnvironment", void, *(c_void_p,))
|
|
98
|
+
# void StopMMMojoEnvironment(void* mmmojo_env);
|
|
99
|
+
StopMMMojoEnvironment = self.func_def("StopMMMojoEnvironment", void, *(c_void_p,))
|
|
100
|
+
# void RemoveMMMojoEnvironment(void* mmmojo_env);
|
|
101
|
+
RemoveMMMojoEnvironment = self.func_def("RemoveMMMojoEnvironment", void, *(c_void_p,))
|
|
102
|
+
# const void* GetMMMojoReadInfoRequest(const void* mmmojo_readinfo, uint32_t* request_data_size);
|
|
103
|
+
GetMMMojoReadInfoRequest = self.func_def("GetMMMojoReadInfoRequest", c_void_p, *(c_void_p, POINTER(c_uint32)))
|
|
104
|
+
# const void* GetMMMojoReadInfoAttach(const void* mmmojo_readinfo, uint32_t* attach_data_size);
|
|
105
|
+
GetMMMojoReadInfoAttach = self.func_def("GetMMMojoReadInfoAttach", c_void_p, *(c_void_p, POINTER(c_uint32)))
|
|
106
|
+
# void RemoveMMMojoReadInfo(void* mmmojo_readinfo);
|
|
107
|
+
RemoveMMMojoReadInfo = self.func_def("RemoveMMMojoReadInfo", void, *(c_void_p,))
|
|
108
|
+
# int GetMMMojoReadInfoMethod(const void* mmmojo_readinfo);
|
|
109
|
+
GetMMMojoReadInfoMethod = self.func_def("GetMMMojoReadInfoMethod", c_int, *(c_void_p,))
|
|
110
|
+
# bool GetMMMojoReadInfoSync(const void* mmmojo_readinfo);
|
|
111
|
+
GetMMMojoReadInfoSync = self.func_def("GetMMMojoReadInfoSync", c_bool, *(c_void_p,))
|
|
112
|
+
# void* CreateMMMojoWriteInfo(int method, bool sync, uint32_t request_id);
|
|
113
|
+
CreateMMMojoWriteInfo = self.func_def("CreateMMMojoWriteInfo",c_void_p, *(c_int, c_bool, c_uint32))
|
|
114
|
+
# void* GetMMMojoWriteInfoRequest(void* mmmojo_writeinfo, uint32_t request_data_size);
|
|
115
|
+
GetMMMojoWriteInfoRequest = self.func_def("GetMMMojoWriteInfoRequest", c_void_p, *(c_void_p, c_uint32))
|
|
116
|
+
# void RemoveMMMojoWriteInfo(void* mmmojo_writeinfo);
|
|
117
|
+
RemoveMMMojoWriteInfo = self.func_def("RemoveMMMojoWriteInfo", void, *(c_void_p,))
|
|
118
|
+
# void* GetMMMojoWriteInfoAttach(void* mmmojo_writeinfo,uint32_t attach_data_size);
|
|
119
|
+
GetMMMojoWriteInfoAttach = self.func_def("GetMMMojoWriteInfoAttach", c_void_p, *(c_void_p, c_uint32))
|
|
120
|
+
# void SetMMMojoWriteInfoMessagePipe(void* mmmojo_writeinfo,int num_of_message_pipe);
|
|
121
|
+
SetMMMojoWriteInfoMessagePipe = self.func_def("SetMMMojoWriteInfoMessagePipe", void, *(c_void_p, c_int))
|
|
122
|
+
# void SetMMMojoWriteInfoResponseSync(void* mmmojo_writeinfo, void** mmmojo_readinfo);
|
|
123
|
+
SetMMMojoWriteInfoResponseSync = self.func_def("SetMMMojoWriteInfoResponseSync", void, *(c_void_p, POINTER(c_void_p)))
|
|
124
|
+
# bool SendMMMojoWriteInfo(void* mmmojo_env,void* mmmojo_writeinfo);
|
|
125
|
+
SendMMMojoWriteInfo = self.func_def("SendMMMojoWriteInfo", c_bool, *(c_void_p,c_void_p))
|
|
126
|
+
# bool SwapMMMojoWriteInfoCallback(void* mmmojo_writeinfo,void* mmmojo_readinfo);
|
|
127
|
+
SwapMMMojoWriteInfoCallback = self.func_def("SwapMMMojoWriteInfoCallback", c_bool, *(c_void_p,c_void_p))
|
|
128
|
+
# bool SwapMMMojoWriteInfoMessage(void* mmmojo_writeinfo, void* mmmojo_readinfo);
|
|
129
|
+
SwapMMMojoWriteInfoMessage = self.func_def("SwapMMMojoWriteInfoMessage", c_bool, *(c_void_p,c_void_p))
|
|
130
|
+
return locals()
|
|
131
|
+
|
|
132
|
+
def __getattr__(self, key):
|
|
133
|
+
_funcs_dict = getattr(self, "_funcs_dict")
|
|
134
|
+
if _funcs_dict.get(key):
|
|
135
|
+
return _funcs_dict[key]
|
|
136
|
+
|
|
137
|
+
def __getitem__(self, key):
|
|
138
|
+
return self._funcs_dict[key]
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
|