Skip to content

Commit e7d7236

Browse files
authored
Merge pull request #162 from Taoxuan-168/main
修改了一点点bug,已在本地编译通过
2 parents fa058e8 + 1edd34c commit e7d7236

File tree

3 files changed

+205
-70
lines changed

3 files changed

+205
-70
lines changed

docs/doc/zh/source_code/add_c_module.md

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,9 @@ namespace maix::test
5050

5151
* 首先[编译 MaixPy 源码](./build.md) 通过,保证我们的编译环境没问题。
5252
* 复制一份 [MaixPy/tools/maix_module](https://github.com/sipeed/MaixPy/tree/main/tools/maix_module) 工程模板到一个新的目录,可以和`MaixPy`放在同一个目录。比如将所有文件和目录复制到了`maix_xxx` 目录下。
53-
*`maix_xxx`目录下,终端执行`python init_files.py`来初始化项目文件。
5453
* 修改项目名:修改`module_name.txt` 文件,改成你要的模块名称,必须以`maix_`开头,这样方便其它用户能在 [pypi.org](https://pypi.org) 或者 [github.com](https://github.com) 搜索到你的项目。
54+
*`maix_xxx`目录下,终端执行`python init_files.py`来初始化项目文件。
55+
* 设置MaixCDK目录:`export MAIXCDK_PATH=/home/yourname/MaixCDK`
5556
* 和 MaixPy 一样执行`python setup.py bdist_wheel linux` 就可以开始为电脑构建。
5657
* 构建完成后可以直接在项目根目录执行`python -c "import maix_xxx;maix_xxx.basic.print('Li Hua')"`就能运行你的模块函数了。
5758
* 执行`python setup.py bdist_wheel maixcam` 就可以为`MaixCAM` 构建软件包了。需要注意的是,构建过程种的代码提示文件(pyi文件)只能在给`linux` 平台构建的时候生成,所以在正式发布的时候需要先执行上一步的`linux`平台构建生成代码提示文件,然后再执行本步的命令生成`MaixCAM`平台的软件包。
@@ -60,9 +61,19 @@ namespace maix::test
6061
* 当你调试好代码后,可以考虑将代码开源到[github.com](https://github.com),并且上传到[pypi.org](https://pypi.org)(具体上传方法可以看官方文档或者搜索教程,大概就是`pip install twine`然后 `twine upload dist/maix_xxx***.whl`就可以了。),写好后欢迎到[maixhub.com/share](https://maixhub.com/share)来分享告诉大家你的成果!
6162

6263
修改代码:
63-
正如 [查看 MaixPy API 源码](../basic/view_src_code.md) 问种所描述的查看和修改源码的方式,在`components/maix/include``components/maix/src` 下增加源文件,增加 C++ 函数,并且填加注释,然后编译后就直接能调用了,非常简单。
64-
比如:
65-
64+
正如 [查看 MaixPy API 源码](../basic/view_src_code.md) 问种所描述的查看和修改源码的方式,在`components/maix/include``components/maix/src` 下增加源文件,增加 C++ 函数,并且在对应的.hpp填加注释,然后编译后就直接能调用了,非常简单。(注意不要改main的文件)
65+
比如,
66+
cpp例子:
67+
```cpp
68+
namespace maix_xxx::test
69+
{//直接在下面写对应的C++函数即可
70+
int add(int a, int b)
71+
{
72+
return a + b;
73+
}
74+
} // namespace maix_xxx
75+
```
76+
.hpp头文件例子:
6677
```cpp
6778
namespace maix_xxx::test
6879
{

tools/maix_module/init_files.py

Lines changed: 187 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,91 @@
11
import os
2+
import sys
23

3-
with open("module_name.txt", "r") as f:
4-
module_name = f.readline().strip()
4+
def main():
5+
# ===================== 1. Read and validate module name =====================
6+
try:
7+
with open("module_name.txt", "r", encoding="utf-8") as f:
8+
module_name = f.readline().strip()
9+
except FileNotFoundError:
10+
raise Exception("Error: module_name.txt file not found. Please create it first and fill in the module name (e.g., maix_kkk)")
11+
except Exception as e:
12+
raise Exception(f"Failed to read module_name.txt: {e}")
513

6-
if not module_name.startswith("maix_"):
7-
raise Exception("module name must starts with maix_")
14+
# Validate module name must start with maix_
15+
if not module_name.startswith("maix_"):
16+
raise Exception("Error: Module name must start with 'maix_' (e.g., maix_kkk)")
817

18+
# Optional: Specify initial version number from command line (Example: python init_files.py 1.0.1)
19+
init_version = sys.argv[1] if len(sys.argv) > 1 else "1.0.0"
20+
try:
21+
version_major, version_minor, version_patch = init_version.split(".")
22+
# Verify version number is numeric
23+
int(version_major), int(version_minor), int(version_patch)
24+
except ValueError:
25+
raise Exception(f"Error: Invalid version number format (Please use format like 1.0.0, current: {init_version})")
926

10-
# Create test dir, and test_import.py
11-
def write_test_dir():
12-
if os.path.exists("test/test_import.py"):
13-
return
14-
content = f"import {module_name}"
15-
os.makedirs("test", exist_ok=True)
16-
with open("test/test_import.py", "w", encoding="utf-8") as f:
17-
f.write(content)
18-
write_test_dir()
27+
# ===================== 2. Generate test file (test/test_import.py) =====================
28+
def write_test_import_file():
29+
test_file = "test/test_import.py"
30+
if os.path.exists(test_file):
31+
print(f"Note: {test_file} already exists, skip generation")
32+
return
33+
try:
34+
os.makedirs("test", exist_ok=True)
35+
content = f"import {module_name}\nprint(f'Successfully imported module: {module_name}')"
36+
with open(test_file, "w", encoding="utf-8") as f:
37+
f.write(content)
38+
print(f"Successfully generated: {test_file}")
39+
except PermissionError:
40+
raise Exception(f"Error: Insufficient permissions to create {test_file}")
41+
except Exception as e:
42+
raise Exception(f"Failed to generate test file: {e}")
1943

20-
# Create maix_xxx dir, write __init__.py and version.py
21-
def write_module_dir():
22-
init_content = f'''from .version import __version__
23-
from ._maix_xxx import *
44+
# ===================== 3. Generate core module files (__init__.py / version.py) =====================
45+
def write_module_dir():
46+
# Generate __init__.py content (Fix hardcoded extension module name)
47+
init_content = f'''from .version import __version__
48+
from ._{module_name} import *
2449
'''
25-
version_content = '''# Versions should comply with PEP440: https://peps.python.org/pep-0440/
50+
# Generate version.py content (Dynamic version number)
51+
version_content = f'''# Versions should comply with PEP440: https://peps.python.org/pep-0440/
2652
27-
version_major = 1
28-
version_minor = 0
29-
version_patch = 0
53+
version_major = {version_major}
54+
version_minor = {version_minor}
55+
version_patch = {version_patch}
3056
31-
__version__ = "{}.{}.{}".format(version_major, version_minor, version_patch)
57+
__version__ = "{version_major}.{version_minor}.{version_patch}"
3258
'''
33-
os.makedirs(module_name, exist_ok=True)
34-
if not os.path.exists(f"{module_name}/__init__.py"):
35-
with open(f"{module_name}/__init__.py", "w", encoding="utf-8") as f:
36-
f.write(init_content)
37-
if not os.path.exists(f"{module_name}/version.py"):
38-
with open(f"{module_name}/version.py", "w", encoding="utf-8") as f:
39-
f.write(version_content)
40-
write_module_dir()
59+
try:
60+
# Create module directory
61+
os.makedirs(module_name, exist_ok=True)
4162

63+
# Generate __init__.py
64+
init_file = f"{module_name}/__init__.py"
65+
if not os.path.exists(init_file):
66+
with open(init_file, "w", encoding="utf-8") as f:
67+
f.write(init_content)
68+
print(f"Successfully generated: {init_file}")
69+
else:
70+
print(f"Note: {init_file} already exists, skip generation")
4271

43-
# Create compent dir and files
44-
def write_component_dir():
45-
cpp_content = f'''#include "{module_name}.hpp"
72+
# Generate version.py
73+
version_file = f"{module_name}/version.py"
74+
if not os.path.exists(version_file):
75+
with open(version_file, "w", encoding="utf-8") as f:
76+
f.write(version_content)
77+
print(f"Successfully generated: {version_file}")
78+
else:
79+
print(f"Note: {version_file} already exists, skip generation")
80+
except PermissionError:
81+
raise Exception(f"Error: Insufficient permissions to create {module_name} directory/files")
82+
except Exception as e:
83+
raise Exception(f"Failed to generate core module files: {e}")
4684

47-
namespace {module_name}::basic
48-
{{
49-
void hello(const std::string &name)
50-
{{
51-
maix::log::info(("hello: " + name).c_str());
52-
}}
53-
}} // namespace {module_name}
54-
'''
55-
hpp_content = f'''
85+
# ===================== 4. Generate C++ extension module files (hpp/cpp) =====================
86+
def write_component_dir():
87+
# Generate .hpp header file content
88+
hpp_content = f'''
5689
#include "maix_basic.hpp"
5790
5891
namespace {module_name}::basic
@@ -66,25 +99,116 @@ def write_component_dir():
6699
67100
}} // namespace {module_name}
68101
'''
69-
os.makedirs("components/maix/include", exist_ok=True)
70-
os.makedirs("components/maix/src", exist_ok=True)
71-
if not os.path.exists(f"components/maix/include/{module_name}.hpp"):
72-
with open(f"components/maix/include/{module_name}.hpp", "w", encoding="utf-8") as f:
73-
f.write(hpp_content)
74-
if not os.path.exists(f"components/maix/src/{module_name}.cpp"):
75-
with open(f"components/maix/src/{module_name}.cpp", "w", encoding="utf-8") as f:
76-
f.write(cpp_content)
77-
write_component_dir()
78-
79-
# Create readme
80-
def write_test_dir():
81-
if os.path.exists("README.md"):
82-
return
83-
content = f"MaixPy module {module_name}\n====\n\nTODO: Add readme\n"
84-
with open("README.md", "w", encoding="utf-8") as f:
85-
f.write(content)
86-
content = f"MaixPy 模块 {module_name}\n====\n\nTODO: 增加 readme\n"
87-
with open("README_ZH.md", "w", encoding="utf-8") as f:
88-
f.write(content)
89-
write_test_dir()
102+
# Generate .cpp source file content
103+
cpp_content = f'''#include "{module_name}.hpp"
104+
105+
namespace {module_name}::basic
106+
{{
107+
void hello(const std::string &name)
108+
{{
109+
maix::log::info(("hello: " + name).c_str());
110+
}}
111+
}} // namespace {module_name}
112+
'''
113+
try:
114+
# Create directories
115+
include_dir = "components/maix/include"
116+
src_dir = "components/maix/src"
117+
os.makedirs(include_dir, exist_ok=True)
118+
os.makedirs(src_dir, exist_ok=True)
119+
120+
# Generate .hpp file
121+
hpp_file = f"{include_dir}/{module_name}.hpp"
122+
if not os.path.exists(hpp_file):
123+
with open(hpp_file, "w", encoding="utf-8") as f:
124+
f.write(hpp_content)
125+
print(f"Successfully generated: {hpp_file}")
126+
else:
127+
print(f"Note: {hpp_file} already exists, skip generation")
128+
129+
# Generate .cpp file
130+
cpp_file = f"{src_dir}/{module_name}.cpp"
131+
if not os.path.exists(cpp_file):
132+
with open(cpp_file, "w", encoding="utf-8") as f:
133+
f.write(cpp_content)
134+
print(f"Successfully generated: {cpp_file}")
135+
else:
136+
print(f"Note: {cpp_file} already exists, skip generation")
137+
except PermissionError:
138+
raise Exception("Error: Insufficient permissions to create components directory/files")
139+
except Exception as e:
140+
raise Exception(f"Failed to generate C++ extension files: {e}")
141+
142+
# ===================== 5. Generate README documentation =====================
143+
def write_readme_files():
144+
# English README
145+
readme_en = "README.md"
146+
if not os.path.exists(readme_en):
147+
en_content = f"""# MaixPy Module: {module_name}
148+
149+
## Quick Start
150+
1. Compile module: `python setup.py bdist_wheel maixcam`
151+
2. Install module: `pip install dist/{module_name}*.whl`
152+
3. Test import: `python test/test_import.py`
153+
154+
## Development Guide
155+
- Python module root: `{module_name}/`
156+
- C++ source code: `components/maix/src/{module_name}.cpp`
157+
- C++ header file: `components/maix/include/{module_name}.hpp`
158+
- Version management: `{module_name}/version.py`
159+
160+
## TODO
161+
- Add detailed API documentation
162+
- Add unit tests for core functions
163+
"""
164+
with open(readme_en, "w", encoding="utf-8") as f:
165+
f.write(en_content)
166+
print(f"Successfully generated: {readme_en}")
167+
else:
168+
print(f"Note: {readme_en} already exists, skip generation")
169+
170+
# Chinese README (renamed to README_CN.md for consistency)
171+
readme_cn = "README_CN.md"
172+
if not os.path.exists(readme_cn):
173+
cn_content = f"""# MaixPy Module: {module_name}
174+
175+
## Quick Start
176+
1. Compile module: `python setup.py bdist_wheel 'platform'`
177+
2. Install module: `pip install dist/{module_name}*.whl`
178+
3. Test import: `python test/test_import.py`
179+
180+
## Development Guide
181+
- Python module root directory: `{module_name}/`
182+
- C++ source file: `components/maix/src/{module_name}.cpp`
183+
- C++ header file: `components/maix/include/{module_name}.hpp`
184+
- Version management file: `{module_name}/version.py`
185+
186+
## TODO
187+
- Add detailed API documentation
188+
- Add unit tests for core functions
189+
"""
190+
with open(readme_cn, "w", encoding="utf-8") as f:
191+
f.write(cn_content)
192+
print(f"Successfully generated: {readme_cn}")
193+
else:
194+
print(f"Note: {readme_cn} already exists, skip generation")
195+
196+
# ===================== Execute all generation logic =====================
197+
write_test_import_file()
198+
write_module_dir()
199+
write_component_dir()
200+
write_readme_files()
201+
202+
print(f"\n✅ Module project skeleton generation completed! Module name: {module_name}")
203+
print(f"📌 Next steps:")
204+
print(f" 1. Modify {module_name}/__init__.py to add custom interfaces")
205+
print(f" 2. Improve components/maix/src/{module_name}.cpp to implement business logic")
206+
print(f" 3. Execute python setup.py bdist_wheel 'platform' to compile the module")
207+
print(f" 4. Modify whl package version: in {module_name}/version.py file")
90208

209+
if __name__ == "__main__":
210+
try:
211+
main()
212+
except Exception as e:
213+
print(f"\n❌ Generation failed: {e}")
214+
sys.exit(1)

tools/maix_module/setup.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import os
44
import platform
55
import shutil
6+
import zipfile
67

78
####################################################################
89
# supported platforms
@@ -272,7 +273,7 @@ def has_ext_modules(foo):
272273
# os.rename(os.path.join("dist", name), os.path.join("dist",
273274
# "MaixPy-{}-{}-{}-{}.whl".format(__version__, py_tag, py_tag, platform_names[board]))
274275
# )
275-
if name.find("linux_riscv64") != -1:
276+
if name.find("linux_riscv64") != -1 or name.find("manylinux2014_") != -1:# 增加linux平台判断,使linux平台和maixcam平台执行相同的whl打包逻辑
276277
# pypi not support riscv64 yet, so we have to change to py3-none-any pkg
277278
# unzip to dist/temp, change dist-info/WHEEL file
278279
# zip back and rename
@@ -294,5 +295,4 @@ def has_ext_modules(foo):
294295
shutil.rmtree("dist/temp")
295296
os.rename(os.path.join("dist", name), os.path.join("dist",
296297
"{}-{}-py3-none-any.whl".format(module_name, __version__))
297-
)
298-
298+
)

0 commit comments

Comments
 (0)