You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Cython技术问询:如何从Geometry包顶层直接导入多个类?

问题描述

当前文件结构

CPP Folder
Cython Folder
├── setup.py
└── Geometry
    ├── Circle
    │   ├── __init__.py
    │   ├── Circle.pyx
    │   ├── Circle.pyi
    │   └── Circle.pxd
    └── Point
        ├── __init__.py
        ├── Point.pyx
        ├── Point.pyi
        └── Point.pxd 

当前setup.py内容

from setuptools import setup, Extension, find_packages
from Cython.Build import cythonize


point_extension = Extension(
    "Geometry.Point.Point",
    [
        "src/Geometry/Point/Point.pyx",
        "../cpp/lib/src/Point.cpp"
    ],
    include_dirs=[
        "../cpp/lib/include"
    ],
    libraries=["Some Library"],
    library_dirs=[
        "src/Geometry"
    ],
    extra_compile_args=["-std=c++17", "-O3"],
    language="c++"
)

circle_extension = Extension(
    "Geometry.Circle.Circle",
    [
        "../cpp/lib/src/Circle.cpp",
        "src/Geometry/Circle/Circle.pyx",
        "../cpp/lib/src/Point.cpp"
    ],
    include_dirs=[
        "../cpp/lib/include"
    ],
    libraries=["Some Library"],
    library_dirs=[
        "src/Geometry"
    ],
    extra_compile_args=["-std=c++17", "-O3"],
    language="c++"
)



setup(
    name="Geometry",
    version="0.1",
    packages=find_packages(where="src"),
    package_dir={"": "src"},
    package_data={
        "Geometry.Circle": ["*.so", "*.pyi"],
        "Geometry.Point": ["*.so", "*.pyi"]
    },
    ext_modules=cythonize([point_extension, circle_extension],
                          compiler_directives={"language_level": 3},
                          include_path=[
                                "../../Expression/cython/src/Some Library",
                                "src/Geometry",
                          ],
                          annotate=True),
    zip_safe=False,
)

当前导入方式

from Geometry.Point import Point
from Geometry.Circle import Circle

目标与设想文件结构

目标是实现from Geometry import Circle, Point的导入方式,调整后的文件结构如下:

CPP Folder
Cython Folder
├── setup.py
└── Geometry
    ├── __init__.py
    ├── Geometry.pyx
    ├── Geometry.pyi
    ├── Geometry.pxd
    ├── Circle
    │   ├── __init__.py
    │   ├── Circle.pyx
    │   ├── Circle.pyi
    │   └── Circle.pxd
    └── Point
        ├── __init__.py
        ├── Point.pyx
        ├── Point.pyi
        └── Point.pxd 

提问

如何重写setup.py,以及编写Geometry.pxd、.pyx和.pyi文件?

附Point示例文件

Point.pxd

from libcpp.memory cimport shared_ptr, weak_ptr, make_shared
from Bryan cimport _Bryan, Bryan

cdef extern from "Point.h":
    cdef cppclass _Point:
        _Point(shared_ptr[_Bryan] x, shared_ptr[_Bryan] y, shared_ptr[_Bryan] z)
        shared_ptr[_Bryan] get_x()
        shared_ptr[_Bryan] get_y()
        shared_ptr[_Bryan] get_z()


cdef class Point:
    cdef shared_ptr[_Point] c_point

Point.pyx

from Point cimport *

cdef class Point:
    def __cinit__(self, Bryan x=Bryan("0", None), Bryan y=Bryan("0", None), Bryan z=Bryan("0", None)):
        self.c_point = make_shared[_Point](x.thisptr, y.thisptr, z.thisptr)

    def __dealloc(self):
        self.c_point.reset()

    def get_x(self) -> Bryan:
        cdef shared_ptr[_Bryan] result = self.c_point.get().get_x()
        cdef Bryan coord = Bryan("", None, make_with_pointer = True)
        coord.thisptr = result
        return coord

    def get_y(self) -> Bryan:
        cdef shared_ptr[_Bryan] result = self.c_point.get().get_y()
        cdef Bryan coord = Bryan("", None, make_with_pointer = True)
        coord.thisptr = result
        return coord

    def get_z(self) -> Bryan:
        cdef shared_ptr[_Bryan] result = self.c_point.get().get_z()
        cdef Bryan coord = Bryan("", None, make_with_pointer = True)
        coord.thisptr = result
        return coord

    property x:
        def __get__(self):
            return self.get_x()

    property y:
        def __get__(self):
            return self.get_y()

    property z:
        def __get__(self):
            return self.get_z()

解决方案

1. 重写setup.py

新增Geometry.Geometry扩展模块,同时保留原有子模块扩展,调整包数据和路径配置:

from setuptools import setup, Extension, find_packages
from Cython.Build import cythonize


point_extension = Extension(
    "Geometry.Point.Point",
    [
        "src/Geometry/Point/Point.pyx",
        "../cpp/lib/src/Point.cpp"
    ],
    include_dirs=[
        "../cpp/lib/include"
    ],
    libraries=["Some Library"],
    library_dirs=[
        "src/Geometry"
    ],
    extra_compile_args=["-std=c++17", "-O3"],
    language="c++"
)

circle_extension = Extension(
    "Geometry.Circle.Circle",
    [
        "../cpp/lib/src/Circle.cpp",
        "src/Geometry/Circle/Circle.pyx",
        "../cpp/lib/src/Point.cpp"
    ],
    include_dirs=[
        "../cpp/lib/include"
    ],
    libraries=["Some Library"],
    library_dirs=[
        "src/Geometry"
    ],
    extra_compile_args=["-std=c++17", "-O3"],
    language="c++"
)

# 新增根模块扩展
geometry_extension = Extension(
    "Geometry.Geometry",
    [
        "src/Geometry/Geometry.pyx"
    ],
    include_dirs=[
        "../cpp/lib/include",
        "src/Geometry/Point",
        "src/Geometry/Circle"
    ],
    libraries=["Some Library"],
    library_dirs=[
        "src/Geometry"
    ],
    extra_compile_args=["-std=c++17", "-O3"],
    language="c++"
)


setup(
    name="Geometry",
    version="0.1",
    packages=find_packages(where="src"),
    package_dir={"": "src"},
    package_data={
        "Geometry": ["*.so", "*.pyi"],
        "Geometry.Circle": ["*.so", "*.pyi"],
        "Geometry.Point": ["*.so", "*.pyi"]
    },
    ext_modules=cythonize([point_extension, circle_extension, geometry_extension],
                          compiler_directives={"language_level": 3},
                          include_path=[
                                "../../Expression/cython/src/Some Library",
                                "src/Geometry",
                                "src/Geometry/Point",
                                "src/Geometry/Circle"
                          ],
                          annotate=True),
    zip_safe=False,
)

2. 编写Geometry.pxd

声明Cython层面的类型引用,方便根模块调用子模块的cdef类:

# 导入子模块的cdef类定义
from Geometry.Point.Point cimport Point as _Point
from Geometry.Circle.Circle cimport Circle as _Circle

# 对外暴露根模块的cdef类声明
cdef class Point:
    cdef _Point inner_point

cdef class Circle:
    cdef _Circle inner_circle

3. 编写Geometry.pyx

封装子模块的类并对外暴露:

from Geometry.Point.Point import Point as PointImpl
from Geometry.Circle.Circle import Circle as CircleImpl
from Geometry.Geometry cimport Point, Circle

# 直接继承子模块类,复用原有实现
cdef class Point(PointImpl):
    pass

cdef class Circle(CircleImpl):
    pass

# 声明对外导出的类
__all__ = ["Point", "Circle"]

4. 编写Geometry.pyi

提供Python静态类型提示:

from Geometry.Point.Point import Point as _Point
from Geometry.Circle.Circle import Circle as _Circle

class Point(_Point):
    def __init__(self, x: "Bryan" = ..., y: "Bryan" = ..., z: "Bryan" = ...) -> None: ...
    @property
    def x(self) -> "Bryan": ...
    @property
    def y(self) -> "Bryan": ...
    @property
    def z(self) -> "Bryan": ...
    def get_x(self) -> "Bryan": ...
    def get_y(self) -> "Bryan": ...
    def get_z(self) -> "Bryan": ...

class Circle(_Circle):
    # 根据Circle类实际方法补充类型提示,示例如下
    def __init__(self, center: Point, radius: "Bryan" = ...) -> None: ...
    @property
    def center(self) -> Point: ...
    @property
    def radius(self) -> "Bryan": ...

__all__ = ["Point", "Circle"]

5. 编写Geometry目录下的__init__.py

将根模块的类导入,实现直接从Geometry模块导入的效果:

from .Geometry import Point, Circle

__all__ = ["Point", "Circle"]

内容的提问来源于stack exchange,提问作者Punreach Rany

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 21:30:58