348 lines
11 KiB
Markdown
348 lines
11 KiB
Markdown
|
|
本文档深入解析 sunvpy 库的 C++ 扩展模块架构、SWIG 封装机制以及 Python 接口设计模式,帮助高级开发者理解系统的底层实现原理和技术架构。
|
|||
|
|
|
|||
|
|
Sources: [__init__.py](__init__.py#L1-L12)
|
|||
|
|
|
|||
|
|
## 架构概览
|
|||
|
|
|
|||
|
|
sunvpy 采用了**三层架构设计**,将底层 C++ 功能无缝集成到 Python 生态系统中。这种架构既保证了核心功能的高性能执行,又提供了灵活易用的 Python 接口。
|
|||
|
|
|
|||
|
|
Sources: [PySSCore.py](PySSCore.py#L1-L12), [PySSProcess.py](PySSProcess.py#L2-L22)
|
|||
|
|
|
|||
|
|
```mermaid
|
|||
|
|
graph TB
|
|||
|
|
subgraph "Python 应用层"
|
|||
|
|
A[SSProcessManager<br/>高级API]
|
|||
|
|
B[Mixin 类集合<br/>SelectionMixin, GeoEditMixin等]
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
subgraph "SWIG 封装层"
|
|||
|
|
C[PySSCore.py]
|
|||
|
|
D[PySSMap.py]
|
|||
|
|
E[PySSDatabase.py]
|
|||
|
|
F[其他 PySS*.py 模块]
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
subgraph "C++ 扩展层"
|
|||
|
|
G[_PySSCore.pyd]
|
|||
|
|
H[_PySSMap.pyd]
|
|||
|
|
I[_PySSDatabase.pyd]
|
|||
|
|
J[其他 _PySS*.pyd 模块]
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
subgraph "原生 C++ 核心"
|
|||
|
|
K[Core C++ 类库]
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
A --> B
|
|||
|
|
B --> C
|
|||
|
|
B --> D
|
|||
|
|
B --> E
|
|||
|
|
B --> F
|
|||
|
|
C --> G
|
|||
|
|
D --> H
|
|||
|
|
E --> I
|
|||
|
|
F --> J
|
|||
|
|
G --> K
|
|||
|
|
H --> K
|
|||
|
|
I --> K
|
|||
|
|
J --> K
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## SWIG 封装机制
|
|||
|
|
|
|||
|
|
sunvpy 使用 **SWIG 4.4.0** 作为 C++ 到 Python 的桥接工具,自动生成 Python 包装代码。每个功能模块对应两个文件:`.pyd` 二进制扩展和 `.py` 接口封装。
|
|||
|
|
|
|||
|
|
Sources: [PySSCore.py](PySSCore.py#L1-L5), [PySSDatabase.py](PySSDatabase.py#L1-L5)
|
|||
|
|
|
|||
|
|
### SWIG 自动生成特征
|
|||
|
|
|
|||
|
|
所有 SWIG 生成的 Python 模块都包含标准的头注释,明确标识其自动生成性质:
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
# This file was automatically generated by SWIG (https://www.swig.org).
|
|||
|
|
# Version 4.4.0
|
|||
|
|
#
|
|||
|
|
# Do not make changes to this file unless you know what you are doing - modify
|
|||
|
|
# the SWIG interface file instead.
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Sources: [PySSCore.py](PySSCore.py#L1-L5), [PySSDatabase.py](PySSDatabase.py#L1-L5)
|
|||
|
|
|
|||
|
|
### 模块导入机制
|
|||
|
|
|
|||
|
|
SWIG 生成的模块采用条件导入策略,确保在不同上下文中正确加载底层 C++ 扩展:
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
from sys import version_info as _swig_python_version_info
|
|||
|
|
# Import the low-level C/C++ module
|
|||
|
|
if getattr(globals().get("__spec__"), "parent", None) or __package__ or "." in __name__:
|
|||
|
|
from . import _PySSCore
|
|||
|
|
else:
|
|||
|
|
import _PySSCore
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Sources: [PySSCore.py](PySSCore.py#L7-L12)
|
|||
|
|
|
|||
|
|
这种设计支持模块的独立运行和包内导入两种场景。
|
|||
|
|
|
|||
|
|
## C++ 扩展模块清单
|
|||
|
|
|
|||
|
|
sunvpy 包含 10 个 C++ 扩展模块,每个模块负责特定的功能域:
|
|||
|
|
|
|||
|
|
| 模块名称 | C++ 扩展文件 | SWIG 封装文件 | 功能描述 |
|
|||
|
|
|---------|-------------|--------------|---------|
|
|||
|
|
| Core | _PySSCore.pyd | PySSCore.py | 核心数据结构、基础类型、字段约束 |
|
|||
|
|
| Map | _PySSMap.pyd | PySSMap.py | 地图操作、工作空间、SDL 接口 |
|
|||
|
|
| Database | _PySSDatabase.pyd | PySSDatabase.py | 数据库访问、事务管理 |
|
|||
|
|
| DataSource | _PySSDataSource.pyd | PySSDataSource.py | 数据源管理、数据集操作 |
|
|||
|
|
| Widget | _PySSWidget.pyd | PySSWidget.py | UI 组件、进度条、全局选项 |
|
|||
|
|
| Math | _PySSMath.pyd | PySSMath.py | 数学计算工具、几何运算 |
|
|||
|
|
| Check | _PySSCheck.pyd | PySSCheck.py | 数据检查、验证规则 |
|
|||
|
|
| DataX | _PySSDataX.pyd | PySSDataX.py | 数据导入导出、格式转换 |
|
|||
|
|
| GisDBUpdate | _PySSGisDBUpdate.pyd | PySSGisDBUpdate.py | GIS 数据库更新 |
|
|||
|
|
| View | _PySSView.pyd | PySSView.py | 视图控制、显示管理 |
|
|||
|
|
|
|||
|
|
Sources: [PySSProcess.py](PySSProcess.py#L2-L7)
|
|||
|
|
|
|||
|
|
## Python 类型封装
|
|||
|
|
|
|||
|
|
SWIG 自动生成 Python 类以包装 C++ 类型,并提供 Python 风格的接口。每个包装类都包含标准的属性和方法定义。
|
|||
|
|
|
|||
|
|
### 内存管理机制
|
|||
|
|
|
|||
|
|
SWIG 通过 `thisown` 属性实现 Python 端的内存所有权管理:
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
class StringArray(object):
|
|||
|
|
thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v),
|
|||
|
|
doc="The membership flag")
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Sources: [PySSCore.py](PySSCore.py#L122-L124)
|
|||
|
|
|
|||
|
|
这种机制允许开发者控制 C++ 对象的生命周期,避免内存泄漏。
|
|||
|
|
|
|||
|
|
### 动态属性控制
|
|||
|
|
|
|||
|
|
SWIG 使用元类和描述符模式限制动态属性的添加,确保类型安全:
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
class _SwigNonDynamicMeta(type):
|
|||
|
|
"""Meta class to enforce nondynamic attributes (no new attributes) for a class"""
|
|||
|
|
__setattr__ = _swig_setattr_nondynamic_class_variable(type.__setattr__)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Sources: [PySSCore.py](PySSCore.py#L56-L59)
|
|||
|
|
|
|||
|
|
### 迭代器支持
|
|||
|
|
|
|||
|
|
SWIG 为容器类型自动生成迭代器接口,支持 Python 的 `for` 循环语法:
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
def iterator(self):
|
|||
|
|
return _PySSCore.StringArray_iterator(self)
|
|||
|
|
def __iter__(self):
|
|||
|
|
return self.iterator()
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Sources: [PySSCore.py](PySSCore.py#L126-L129)
|
|||
|
|
|
|||
|
|
## 高层架构设计
|
|||
|
|
|
|||
|
|
在 SWIG 生成的底层封装之上,sunvpy 构建了高层 Python 类,采用 **Mixin 设计模式** 实现功能的模块化组合。
|
|||
|
|
|
|||
|
|
Sources: [PySSProcess.py](PySSProcess.py#L25-L50)
|
|||
|
|
|
|||
|
|
### SSProcessManager 类
|
|||
|
|
|
|||
|
|
`SSProcessManager` 是核心应用类,通过多重继承组合多个 Mixin 的功能:
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
class SSProcessManager(SelectionMixin, GeoEditMixin,
|
|||
|
|
ProjectMixin, LogMixin, ProgressMixin):
|
|||
|
|
"""SunvStation进程管理类。
|
|||
|
|
|
|||
|
|
该类提供了对SunvStation工作空间和地图的基本操作,包括几何对象的创建、
|
|||
|
|
管理和视图更新等功能,以及一些常用的辅助函数等
|
|||
|
|
"""
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Sources: [PySSProcess.py](PySSProcess.py#L25-L30)
|
|||
|
|
|
|||
|
|
### Mixin 类层次
|
|||
|
|
|
|||
|
|
Mixin 类提供了功能的横向组合,每个 Mixin 负责特定的功能域:
|
|||
|
|
|
|||
|
|
| Mixin 类 | 功能域 | 导入模块 |
|
|||
|
|
|---------|-------|---------|
|
|||
|
|
| SelectionMixin | 选择集管理 | PySSCore, PySSMap, PySSDataSource |
|
|||
|
|
| GeoEditMixin | 地理对象编辑 | PySSCore, PySSMap |
|
|||
|
|
| ProjectMixin | 项目管理 | PySSCore, PySSMap |
|
|||
|
|
| LogMixin | 日志记录 | logging |
|
|||
|
|
| ProgressMixin | 进度显示 | PySSWidget |
|
|||
|
|
|
|||
|
|
Sources: [ssprocess_mixins/selection_mixin.py](ssprocess_mixins/selection_mixin.py#L25-L26), [PySSProcess.py](PySSProcess.py#L18-L22)
|
|||
|
|
|
|||
|
|
### 全局单例模式
|
|||
|
|
|
|||
|
|
SSProcessManager 通过模块级变量导出全局单例,简化使用:
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
# @export: SSProcess为模块导出的全局单例
|
|||
|
|
SSProcess = SSProcessManager()
|
|||
|
|
__all__ = ["SSProcess"]
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Sources: [PySSProcess.py](PySSProcess.py#L88-L90)
|
|||
|
|
|
|||
|
|
## 数据类型映射
|
|||
|
|
|
|||
|
|
SWIG 自动处理 C++ 和 Python 之间的类型转换,提供以下常用类型映射:
|
|||
|
|
|
|||
|
|
| C++ 类型 | Python 类型 | 示例 |
|
|||
|
|
|---------|------------|------|
|
|||
|
|
| `std::string` | `str` | 字符串属性 |
|
|||
|
|
| `std::vector<T>` | `List[T]` | StringArray, FloatArray |
|
|||
|
|
| `std::map<K,V>` | `Dict[K,V]` | 字段映射 |
|
|||
|
|
| `bool` | `bool` | BoolArray |
|
|||
|
|
| `int8/16/32/64` | `int` | 整数类型 |
|
|||
|
|
| `float/double` | `float` | 浮点类型 |
|
|||
|
|
|
|||
|
|
Sources: [PySSCore.py](PySSCore.py#L122-L126), [PySSCore.py](PySSCore.py#L232-L246)
|
|||
|
|
|
|||
|
|
### 变体类型系统
|
|||
|
|
|
|||
|
|
SWIG 封装了 C++ 的变体类型系统,提供类型安全的动态类型支持:
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
VT_NONE = _PySSCore.VT_NONE
|
|||
|
|
VT_BOOL = _PySSCore.VT_BOOL
|
|||
|
|
VT_FLOAT = _PySSCore.VT_FLOAT
|
|||
|
|
VT_DOUBLE = _PySSCore.VT_DOUBLE
|
|||
|
|
VT_INT8 = _PySSCore.VT_INT8
|
|||
|
|
VT_STRING = _PySSCore.VT_STRING
|
|||
|
|
VT_BINARY = _PySSCore.VT_BINARY
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Sources: [PySSCore.py](PySSCore.py#L232-L246)
|
|||
|
|
|
|||
|
|
## 调用路径分析
|
|||
|
|
|
|||
|
|
从 Python 应用到 C++ 核心的典型调用路径如下:
|
|||
|
|
|
|||
|
|
```mermaid
|
|||
|
|
sequenceDiagram
|
|||
|
|
participant App as Python 应用
|
|||
|
|
participant SPM as SSProcessManager
|
|||
|
|
participant Mixin as Mixin 方法
|
|||
|
|
participant SWIG as SWIG 封装
|
|||
|
|
participant PYD as C++ 扩展
|
|||
|
|
participant CPP as C++ 核心
|
|||
|
|
|
|||
|
|
App->>SPM: SSProcess.selectFilter()
|
|||
|
|
SPM->>Mixin: 调用 Mixin 方法
|
|||
|
|
Mixin->>SWIG: GeoBaseList 对象操作
|
|||
|
|
SWIG->>PYD: _PySSCore.*()
|
|||
|
|
PYD->>CPP: C++ 类方法执行
|
|||
|
|
CPP-->>PYD: 返回结果
|
|||
|
|
PYD-->>SWIG: 类型转换
|
|||
|
|
SWIG-->>Mixin: Python 对象
|
|||
|
|
Mixin-->>SPM: 返回结果
|
|||
|
|
SPM-->>App: 返回给应用
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Sources: [PySSProcess.py](PySSProcess.py#L93-L98), [ssprocess_mixins/selection_mixin.py](ssprocess_mixins/selection_mixin.py#L49-L55)
|
|||
|
|
|
|||
|
|
## 错误处理与异常机制
|
|||
|
|
|
|||
|
|
SWIG 生成的 Python 模块支持 C++ 异常到 Python 异常的自动转换:
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
try:
|
|||
|
|
import builtins as __builtin__
|
|||
|
|
except ImportError:
|
|||
|
|
import __builtin__
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Sources: [PySSCore.py](PySSCore.py#L14-L17)
|
|||
|
|
|
|||
|
|
SWIG 在封装 C++ 方法时自动添加异常处理逻辑,将 C++ 异常转换为 Python 的 `RuntimeError` 或其他适当的异常类型。
|
|||
|
|
|
|||
|
|
## 性能优化策略
|
|||
|
|
|
|||
|
|
### 延迟加载设计
|
|||
|
|
|
|||
|
|
SSProcessManager 在初始化时仅获取关键实例的引用,避免不必要的资源加载:
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
def __init__(self):
|
|||
|
|
"""初始化SSProcess实例。
|
|||
|
|
|
|||
|
|
获取当前工作空间和地图实例,为后续操作做准备。
|
|||
|
|
"""
|
|||
|
|
self.workspace = WorkSpace.getInstance()
|
|||
|
|
self.map = self.workspace.getCurrentScaleMap()
|
|||
|
|
self.global_options = GlobalOptions.getInstance()
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Sources: [PySSProcess.py](PySSProcess.py#L53-L59)
|
|||
|
|
|
|||
|
|
### 对象缓存机制
|
|||
|
|
|
|||
|
|
SSProcessManager 维护多个对象缓存列表,减少重复创建和数据库访问:
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
self.bufferObjList = GeoBaseList() # 缓存对象列表
|
|||
|
|
self.bufferNoteList = GeoBaseList() # 缓存注记列表
|
|||
|
|
self.newBufferObjList = [] # 新创建对象缓存列表
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Sources: [PySSProcess.py](PySSProcess.py#L74-L78)
|
|||
|
|
|
|||
|
|
## 扩展开发指南
|
|||
|
|
|
|||
|
|
### 理解模块依赖关系
|
|||
|
|
|
|||
|
|
开发新的 Mixin 类时,需要正确导入依赖的 SWIG 模块:
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
from sunvpy.PySSMath import *
|
|||
|
|
from sunvpy.PySSCore import *
|
|||
|
|
from sunvpy.PySSMap import *
|
|||
|
|
from sunvpy.PySSDataSource import *
|
|||
|
|
from sunvpy.PySSWidget import Progress, GlobalOptions
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Sources: [ssprocess_mixins/selection_mixin.py](ssprocess_mixins/selection_mixin.py#L4-L9)
|
|||
|
|
|
|||
|
|
### 类型注解规范
|
|||
|
|
|
|||
|
|
在 Mixin 类中使用显式类型注解,提高代码可读性和 IDE 支持:
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
class SelectionMixin(GeoEditAware, LogAware, ProgressAware, ABC):
|
|||
|
|
# 显式声明成员变量类型
|
|||
|
|
workspace: WorkSpace
|
|||
|
|
map: ScaleMap
|
|||
|
|
global_options: GlobalOptions
|
|||
|
|
selGeoList: GeoBaseList
|
|||
|
|
searchHelper: SSearchHelper
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Sources: [ssprocess_mixins/selection_mixin.py](ssprocess_mixins/selection_mixin.py#L27-L35)
|
|||
|
|
|
|||
|
|
## 学习路径建议
|
|||
|
|
|
|||
|
|
要深入理解 sunvpy 的 C++ 扩展架构,建议按照以下路径学习:
|
|||
|
|
|
|||
|
|
1. **基础理解**:先阅读 [库概述](1-ku-gai-shu) 了解整体架构
|
|||
|
|
2. **SWIG 机制**:学习 [SWIG 封装机制说明](7-swig-feng-zhuang-ji-zhi-shuo-ming) 掌握封装原理
|
|||
|
|
3. **工作空间概念**:理解 [工作空间与地图概念](8-gong-zuo-kong-jian-yu-di-tu-gai-nian)
|
|||
|
|
4. **Mixin 模式**:深入研究 [Mixin 设计模式](9-mixin-she-ji-mo-shi)
|
|||
|
|
5. **实战应用**:通过 [第一个脚本:查询地物属性](3-di-ge-jiao-ben-cha-xun-di-wu-shu-xing) 实践使用接口
|
|||
|
|
|
|||
|
|
Sources: [__init__.py](__init__.py#L1-L12)
|
|||
|
|
|
|||
|
|
## 总结
|
|||
|
|
|
|||
|
|
sunvpy 的 C++ 扩展模块与 Python 接口设计展现了优秀的混合编程实践:通过 SWIG 实现了 C++ 高性能核心与 Python 灵活生态的无缝集成,采用 Mixin 模式实现了功能的模块化和可组合性,通过单例模式简化了全局访问。这种架构既保证了核心功能的执行效率,又提供了开发者友好的 Python 接口。
|