cython - 防止cython中c文件的双重编译

标签 cython

我正在编写一个 c 库的包装器,这个库包含几乎所有函数的文件,比如说 all_funcs.c。该文件又需要编译许多其他 c 文件

我已经创建了 all_funcs.pyx,其中包装了所有函数,但我还想创建一个子模块,它可以访问 all_funcs.c 中的函数。现在有效的方法是将所有 c 文件添加到 setup.py 中的两个扩展中,但是每个 c 文件都会编译两次:第一次用于 all_funcs.pyx,第二次用于子模块扩展。

有没有办法为每个扩展提供通用源文件?

当前 setup.py 的示例:

ext_helpers = Extension(name=SRC_DIR + '.wrapper.utils.helpers',
                        sources=[SRC_DIR + '/wrapper/utils/helpers.pyx'] + source_files_paths,
                        include_dirs=[SRC_DIR + '/include/'])


ext_all_funcs = Extension(name=SRC_DIR + '.wrapper.all_funcs',
                          sources=[SRC_DIR + '/wrapper/all_funcs.pyx'] + source_files_paths,
                          include_dirs=[SRC_DIR + '/include/'])

EXTENSIONS = [
    ext_helpers,
    ext_all_funcs,
]

if __name__ == "__main__":
    setup(
        packages=PACKAGES,
        zip_safe=False,
        name='some_name',
        ext_modules=cythonize(EXTENSIONS, language_level=3)
        )

source_files_paths - 常见 C 源文件列表

最佳答案

注意:此答案仅解释如何使用 setup 函数的 libraries 参数避免多次编译 c/cpp 文件。但是,它没有解释如何避免由于 ODR 违规而可能出现的问题 - 请参阅 this SO-post .

libraries参数添加到setup将在构建ext_modules之前触发build_clib(当运行 >setup.py buildsetup.py install 命令),当扩展链接时,生成的静态库也将自动传递给链接器。

对于您的setup.py,这意味着:

from setuptools import setup, find_packages, Extension
...
#common c files compiled to a static library:
mylib = ('mylib', {'sources': source_files_paths}) # possible further settings

# no common c-files (taken care of in mylib):
ext_helpers = Extension(name=SRC_DIR + '.wrapper.utils.helpers',
                        sources=[SRC_DIR + '/wrapper/utils/helpers.pyx'],
                        include_dirs=[SRC_DIR + '/include/'])

# no common c-files (taken care of in mylib):
ext_all_funcs = Extension(name=SRC_DIR + '.wrapper.all_funcs',
                          sources=[SRC_DIR + '/wrapper/all_funcs.pyx'],
                          include_dirs=[SRC_DIR + '/include/'])

EXTENSIONS = [
    ext_helpers,
    ext_all_funcs,
]

if __name__ == "__main__":
    setup(
        packages=find_packages(where=SRC_DIR),
        zip_safe=False,
        name='some_name',
        ext_modules=cythonize(EXTENSIONS, language_level=3),
        # will be build as static libraries and automatically passed to linker:
        libraries = [mylib] 
        )

要就地构建扩展,应该调用:

python setupy.py build_clib build_ext --inplace

仅作为 build_ext 是不够的:我们需要先构建静态库,然后才能在扩展中使用它们。

关于cython - 防止cython中c文件的双重编译,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57673283/

相关文章:

python - Cython 编译器错误

python - 有没有办法欺骗类的 isinstance 结果?

python - 使用 Cython 未获得预期的加速

python - Cython 的计算不正确

python - 如何使用 STL 列表参数为 C++ 函数构建 cython 包装器

python - 如何在 Cython 的新型缓冲区对象中包装 C 指针和长度?

python - 使用 Python 在非常大的图像中进行高性能变量模糊

c++ - 用 C++ 类编译 cython 并获得 undefined symbol

c++ - 将 C++11 数组与 Cython 接口(interface)

python - Cython:了解具有间接连续内存布局的类型化内存 View