Files
TransPyC/wiki/10-imports.md
2026-06-16 16:09:42 +08:00

5.0 KiB
Raw Blame History

10 - 模块与导入系统

Viper 的模块系统基于 Python 的 import 语法,但编译时通过 TransPyC 的符号表和类型系统实现跨模块的类型解析。

导入语法

标准导入

import t, c                              # Viper 内置类型和操作模块
import asm                               # 汇编辅助模块
import string                            # 字符串操作模块

模块导入

import bootinfo
import intr
import platform.pch as pch
import drivers.serial.uart.serial as serial

from 导入

from stdint import *                     # 导入所有 stdint 类型别名
from drivers.video.vesafb.vga import _VGAScreenDriver

相对导入

from . import submodule
from .. import parent_module

特殊模块

t 模块

类型定义模块,提供所有 C 类型对应的 Viper 类型。每个 Viper 文件通常都需要导入:

import t

c 模块

C 语言操作模块,提供指针操作、内联汇编、预处理指令等:

import c

asm 模块

汇编辅助模块,提供常用汇编指令的封装:

import asm

asm.sti()          # __asm__ __volatile__("sti");
asm.hlt()          # __asm__ __volatile__("hlt");
asm.cli()          # __asm__ __volatile__("cli");
asm.nop()          # __asm__ __volatile__("nop");
asm.BSSClean()     # 清零 BSS 段

string 模块

字符串/内存操作模块,对应 C 标准库的 string.h

string 部分使用 x86_64 专有汇编进行加速,因此某些函数在其它架构可能需要手动重新编写。

import string

string.memset(c.Addr(buf), 0, 64)        # memset(&buf, 0, 64);
string.memcpy(dst, src, size)            # memcpy(dst, src, size);
string.memmove(dst, src, size)           # memmove(dst, src, size);
string.memcmp(a, b, size)                # memcmp(a, b, size);
string.strcmp(a, b)                      # strcmp(a, b);
string.strcpy(dst, src)                  # strcpy(dst, src);

stdint 模块

提供 C stdint.h 中的类型别名:

from stdint import *

# 提供以下类型别名:
# UINT8PTR, UINT16PTR, UINT32PTR, UINT64PTR
# INT8PTR, INT16PTR, INT32PTR, INT64PTR
# 等等

viperlib 模块

ViperOS 标准库,提供常用 C 库函数:

import viperlib

viperlib.snprintf(c.Addr(buf), 64, "value=%d", 42)    # snprintf(&buf, 64, "value=%d", 42);

vpsdk 模块

vpsdk 模块 专供于基于 Viper 开发的示例操作系统 ViperOS不可用于其它平台且需要特殊配置。

ViperOS 应用 SDK提供系统调用和窗口管理

import vpsdk.window as window
import vpsdk.process as process
import vpsdk.dynlib as dynlib
import vpsdk.syscall as syscall

模块解析流程

编译时模块加载

Viper 的 import 是编译时操作,不涉及运行时模块加载。完整的模块解析流程与两阶段编译紧密耦合:

  1. 阶段一:从入口文件出发,通过 import 语句递归发现所有可达的源文件
  2. 阶段一:对每个源文件生成 <SHA1>.pyi 签名存根和 <SHA1>.stub.ll LLVM IR 声明
  3. 阶段二:加载所有 .pyi.stub.ll,构建共享符号表
  4. 阶段二:翻译源文件时,通过符号表解析跨模块的类型和函数引用
  5. 阶段二:将被引用模块的 .stub.ll 声明嵌入到生成的 .ll 文件头部

类型存根文件(.pyi

.pyi 文件是模块的声明接口,由 PythonToStubConverter 在阶段一生成。存根文件的内容规则:

元素 存根表示
t.CDefine 常量 保留完整定义(含赋值)
t.CDefine 函数 保留完整函数体
普通函数 仅签名 + c.State
全局变量 添加 t.CExtern
类定义 保留成员类型注解和方法签名

存根文件还自动添加宏守卫(c.CIfndef/c.CEndif()),防止重复包含。

SHA1 命名空间与导入

每个模块的函数和结构体在 LLVM IR 中自动加上 SHA1 前缀,消除跨模块符号冲突。只有标记为 t.CExport 的函数保持原始名称。详见 01-overview.md 中 SHA1 命名空间机制

符号表

所有模块的类型信息统一存储在 SymbolTable 中,包含:

  • 结构体/联合体/枚举定义
  • 函数签名
  • 全局变量
  • typedef 别名
  • t.CDefine 常量

跨模块类型引用

# 在 fat32_types.py 中定义
class fat32_fileinfo:
    fname: list[t.CChar, 13]
    attr: t.CUInt8T
    file_size: t.CUInt32T

# 在其他模块中引用
import fat32_types
info: fat32_types.fat32_fileinfo

跨模块引用的结构体在 LLVM IR 中使用 SHA1 前缀的类型名:

%"<SHA1_of_fat32_types>.fat32_fileinfo" = type { [13 x i8], i8, i32 }

项目 includes 配置

project.json 中配置模块搜索路径:

{
    "includes": ["../.."],
    "source_dir": "./Kernel"
}

编译器会在 includes 指定的目录中搜索导入的模块。