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

如何使用setuptools编译混合C/C++代码以供Cython调用

实现多阶段构建并复用setuptools指定编译器的方案

核心逻辑:不要手动初始化distutils的编译器实例,直接复用build_ext流程中已经完成初始化、完全匹配了用户指定编译器参数(如命令行--compiler参数、环境变量CC/CXX指定值)的编译器实例即可。

具体实现步骤如下:

  • 导入所需依赖模块,自定义build_ext子类重写构建逻辑,在默认的Cython/C++扩展构建流程前插入第三方C源码的编译步骤,全程复用当前实例已初始化的compiler对象
  • 在setup函数中通过cmdclass参数替换默认的build_ext命令为你自定义的子类

参考实现代码:

from setuptools import setup, Extension
from setuptools.command.build_ext import build_ext
from Cython.Build import cythonize

class CustomBuildExt(build_ext):
    def run(self):
        # 阶段1:使用当前实例的编译器(即setup实际要使用的编译器)编译第三方C依赖
        c_source_files = [
            "third_party/lib1/xxx.c",
            "third_party/lib2/yyy.c"
        ]
        c_include_dirs = [
            "third_party/lib1/include",
            "third_party/lib2/include"
        ]
        # 编译生成目标文件,输出到构建临时目录避免污染源码
        compiled_c_objects = self.compiler.compile(
            sources=c_source_files,
            include_dirs=c_include_dirs,
            output_dir=self.build_temp,
            debug=self.debug,
            # 可根据需要传入C源码专属编译参数
            extra_preargs=["-O2", "-fPIC"] if self.compiler.compiler_type != "msvc" else ["/O2"]
        )

        # 将编译好的C目标文件挂载到扩展属性中,后续链接阶段会自动引入
        for ext in self.extensions:
            ext.extra_objects = ext.extra_objects or []
            ext.extra_objects.extend(compiled_c_objects)

        # 阶段2:执行原生构建逻辑,完成Cython、C++代码的编译和链接
        super().run()

# 定义你的Python扩展
your_extension = Extension(
    name="your_package.module_name",
    sources=[
        "your_code/cython_wrapper.pyx",
        "your_code/cpp_logic.cpp"
    ],
    include_dirs=c_include_dirs,
    language="c++",
    # 可根据需要传入C++专属编译、链接参数
    extra_compile_args=["-std=c++17"] if self.compiler.compiler_type != "msvc" else ["/std:c++17"]
)

setup(
    name="your_package",
    version="0.1.0",
    ext_modules=cythonize([your_extension]),
    cmdclass={
        "build_ext": CustomBuildExt
    }
)

额外注意事项:

  • 如需区分不同编译器的参数差异,可通过self.compiler.compiler_type判断当前编译器类型,常见取值为gcc、clang、msvc
  • 如果第三方C依赖使用独立构建系统(如CMake、Makefile),也可在自定义build_ext的run方法中调用对应构建命令,编译器路径可直接从self.compiler.cc(C编译器路径)、self.compiler.cxx(C++编译器路径)获取传递给子构建系统
  • 所有用户通过命令行、环境变量传入的构建配置都会自动被self.compiler继承,无需手动解析处理

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 22:54:03