Cython封装C库项目结构与setup.py配置问题咨询
C/Cython项目最优结构与setup.py配置方案
最优项目结构
project/ ├── src/ │ ├── myproject/ # 主Python包,统一管理所有模块 │ │ ├── __init__.py │ │ ├── c_lib/ # 独立存放C源码与头文件 │ │ │ ├── __init__.py # 空文件,标记为Python子包 │ │ │ ├── c1.c │ │ │ ├── c1.h │ │ │ ├── c2.c │ │ │ └── c2.h │ │ └── cython_modules/ # 存放Cython模块与声明文件 │ │ ├── __init__.py │ │ ├── cython1.pyx │ │ ├── cython1.pxd │ │ ├── cython2.pyx │ │ ├── cython2.pxd │ │ └── c_includes.pxd # 集中管理C函数的Cython声明 └── setup.py
正确的setup.py配置
from setuptools import setup, Extension from Cython.Build import cythonize # 1. 将C源码编译为独立静态库Extension c_lib_sources = [ "src/myproject/c_lib/c1.c", "src/myproject/c_lib/c2.c" ] c_lib_ext = Extension( "myproject.c_lib._c_lib", sources=c_lib_sources, include_dirs=["src/myproject/c_lib"], extra_compile_args=["-fPIC"], # 生成位置无关代码,支持动态链接 ) # 2. 定义Cython模块Extension,统一链接C静态库 cython_extensions = [] for module_name in ["cython1", "cython2"]: ext = Extension( f"myproject.cython_modules.{module_name}", sources=[f"src/myproject/cython_modules/{module_name}.pyx"], include_dirs=["src/myproject/c_lib"], # 链接编译好的C静态库 extra_link_args=[c_lib_ext.outputs[0]] if hasattr(c_lib_ext, 'outputs') else [] ) cython_extensions.append(ext) # 3. 执行打包配置 setup( name="myproject", package_dir={"": "src"}, # 指定源码根目录为src packages=["myproject", "myproject.c_lib", "myproject.cython_modules"], include_package_data=True, package_data={ "myproject.c_lib": ["*.h"], # 打包头文件供外部项目引用 "myproject.cython_modules": ["*.pxd"] # 打包pxd文件支持cimport }, ext_modules=cythonize([c_lib_ext] + cython_extensions), zip_safe=False # 动态库无法安全压缩,禁用该选项 )
核心问题的解决细节
1. 消除cimport时找不到C文件的问题
- 彻底放弃在
.pxd中直接引用.c文件的写法,改为引用.h头文件。 - 在
c_includes.pxd中集中声明C函数:cdef extern from "c1.h": void c1_function() cdef extern from "c2.h": void c2_function() - 其他Cython模块通过
cimport myproject.cython_modules.c_includes引入声明,cimport只会依赖.pxd和.h文件,不再受C源码路径影响。
2. 解决符号缺失问题
- 将所有C源码编译为一个独立的静态库,所有Cython模块统一链接这个库,确保C函数的符号被正确注入到最终的共享库中,避免运行时找不到符号。
3. 解决C函数重复声明/定义问题
- 只编译一次C源码生成静态库,所有Cython模块共享这个库,从根源避免重复编译C文件导致的符号冲突。
- C文件间的相互引用(如
c2.c包含c1.h)会在编译C静态库时自动处理,无需额外配置。
内容的提问来源于stack exchange,提问作者Ipse Lium
相关产品推荐
相关产品推荐

