# py2c **Repository Path**: foolish-shabby/py2c ## Basic Information - **Project Name**: py2c - **Description**: 一个把符合py2c标准的python代码转化成C代码的小工具(py2c标准见README) - **Primary Language**: Python - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2024-01-20 - **Last Updated**: 2024-01-20 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # py2c:Python Program To C! ### 0. 前言 py2c 是一个将 Python 代码转化为 C 代码的工具(反正都是C系语法),最终的目标是将一个目录下的 py 文件全部转化。 Python 代码虽然十分游标卡尺,但鉴于我本身能力有限,同时也是为了自身的能力着想,决定还是苦一苦使用者,我将会强制要求用户使用我最常用的码风(即:在每个 Python 代码的游标卡尺最后,必须有一个空行),以此来更好地区分段落。 同样,由于把空行当成了判断缩进的工具,所以在同一个函数之间不能有任何的空行,否则你就等着gcc报大括号不匹配吧。 至于翻译的 C 代码,能跑就行,看肯定没那么能看了。 (或许可以生成 AST 规避这种问题?但我不会读诶,还是算了) 不过,除此之外,想要使用 py2c 转化源码,Python 代码需遵守如下规则(虽然 py2c 还没开写): ### 1. class 相关规则 所有的 class 必须继承 StructBase 类(定义于 `supportlib.py`),并且内部只能有成员变量,不能有成员方法。 除 StructBase 类外,其他类不能相互继承。 例: ```python # test.py from supportlib import * # 后面的 u16 u32 CArray 也定义在 supportlib.py 中 class StructTest(StructBase): x: u16 y: u32 z: u32 member: CArray(u32, 9) ``` ### 2. 函数相关规则 函数方面,不能使用 keyword-only 参数,不能用关键字传参。 如果遇到 `_` 开头的函数,会自动去掉下划线并在函数前加上 `static`。 对于只声明的函数,应当在 `__doc__` 中标明 `Declaration` 字样。 所有的函数必须在参数列表中用 `__annotations__` 标明参数类型和返回值。 例: ```python # test2.py from supportlib import * from test import * def add(x: u32, y: u32) -> u32: """Declaration""" pass def handle_struct(s: StructTest) -> u32: return add(s.x, s.y) def add(x: u32, y: u32) -> u32: return x + y def _private_function() -> u32: return 114514 def sub(x, y): # illegal ``` ### 3. import 相关规则 只能使用 `from xxx import *` ,这些语句将被替换为 `#include`。 ### 4. if、while、for 等条件相关语句规则 条件中不得使用链式比较(py2c不会报错,转化成C之后的C编译器也不会报错,但是实际应用就寄啦)。for 的使用仅限于 `for i in range([start, ]end[, step]):`。 有关for的更多高级用法,通通地不支持,用你的破while去。 例: ```python # wtf.py if 5 < x < 7: # illegal but no errors if 5 < x and x < 7: # legal for i in range(10): for j in range(5): while True: pass ``` ### 5. 算术表达式相关规则 只支持两者都支持的部分,不包括++(C++自增)、--(C++自减)、**(Python的幂)等。 ### 6. 杂项 python 库函数基本不能使用,各种标准库基本都死了,包括 `list`、`dict` 等,实在不好翻译。 唯一能用的库函数是 `print`,由 `supportlib` 提供,需要实现 `put_int` 和 `put_str`。 由于个人时间精力有限,print各参数除非是字符串,否则不能有空格。 指针在 `supportlib.py` 中运用一堆函数和一个变量声明支持。 ### 7. `supportlib` 相关 `supportlib.h` 由 `py2c` 工具自动生成。 在调用py2c时,添加 `-runnable` 参数后,`put_str` 和 `put_int` 会被#define到 `printf`,否则啥也不干。 ### 8. 示例 一个合理合法的、支持被转成 C 的 py 代码示例: ```python from supportlib import * # 基本上是必不可少的,提供指针、C类型、StructBase等好东西 def main() -> int: print("In main") # 要求已经实现了 put_str 之类的东西 for i in range(1, 10): for j in range(1, 10): print(i, "*", j, "=", i*j, " ") # 同样 print("\n") while True: pass ``` 会被翻译为: ```c // C code auto generated by py2c. // py2c made by foolish-shabby <2276316223@qq.com> #include "supportlib.h" int main() { put_str("In main\n"); for (int i = 1; i < 10; i += 1) { for (int j = 1; j < 10; j += 1) { put_int((int) i); put_str("*"); put_int((int) j); put_str("="); put_int((int) i*j); put_str(" "); }; put_str("\n"); }; while (1) { };}; ``` 每一个代码块结尾都是 `};`,因为我偷懒了,不想区分struct和其他代码块。 注:循环变量默认使用 `int`。 ### 9.一些 C 有而 py 没有的特性 通通不支持,想用要么写C,要么写汇编。 总之,对于能用py的部分,按上面的标准用py;用不了的(自动生成满足不了的),用C/汇编。