Python扩展:使用不同的编译器标志来实现C部分和C++部分

2024-05-20 14:38:41 发布

您现在位置:Python中文网/ 问答频道 /正文

我的Python扩展,我既有C(来自嵌入式库),又有C++文件,它们被编译并链接在一起。只有C++部分与Python(通过SWIG)进行接口。这在使用VS2015的windows和linux下的gcc中都有效。但是,对于GCC,C++文件需要不同的编译器标志(例如-STD= C++ 11,Wno重新排序),而不是C文件,以避免关于C.</P>中的不正确标记的警告。

setuptools/distutils中是否有方法分别更改每个文件的编译器标志,例如基于文件扩展名

我已经使用了来自https://stackoverflow.com/a/36293331/3032680的自定义构建步骤

更新:

主要问题是,{{CD1>}不检查C或C++的文件扩展名,并用$CC运行所有内容。即使定义CXXFLAGS也没有帮助。我将忍受这些警告,无论是使用export还是在setup.py文件中使用os.eniviron的定义

更新2:

在使用Clang8.0.0的macOS上,情况变得更糟:尝试用-std=c++11编译.c文件不是警告,而是错误


Tags: 文件警告编译器定义排序链接标志linux
2条回答

还有另一个选项是重载distutils编译器类(比如unix C编译器):

import os
from distutils.unixccompiler import UnixCCompiler

cpp_flags = ['-std=c++11']

class C_CxxCompiler(UnixCCompiler):
  def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):
    _cc_args = cc_args

    # add the C++ flags for source files with extensions listed below
    if os.path.splitext(src)[-1] in ('.cpp', '.cxx', '.cc'):
      _cc_args = cc_args + cpp_flags

    UnixCCompiler._compile(self, obj, src, ext, _cc_args, extra_postargs, pp_opts)

然后重载distutils.build_ext命令以拦截扩展构建并在编译继续之前替换编译器:

class BuildC_CxxExtensions(build_ext):
  def build_extensions(self, ext):
    if self.compiler.compiler_type == 'unix':
      # Replace the compiler
      old_compiler = self.compiler
      self.compiler = C_CxxCompiler()

      # Copy its attributes
      for attr, value in old_compiler.__dict__.items():
        setattr(self.compiler, attr, value)
    build_ext.build_extensions(self, ext)

根据您的平台,您可能需要重载其他编译器类MSVCCompilerCygwinCCompilerMingw32CCompilerBCPPCompiler

因为distutils在确保所有文件都使用相同的编译器标志进行编译方面走了很长的路,而不管它们的文件扩展名是.c还是.cpp。因此,即使使用CFLAGS和CXXFLAGS也没有被考虑在内,但gcc和CLang仍然以不同的方式处理它们。VisualStudio只是编译所有的东西作为C++。p><>我通过接受C在大多数情况下仍然是C++的子集来解决问题,并将C源文件重命名为.CPP,即使文件包含C。这个解决方案是丑陋的,但是我摆脱了GCC中的警告和CLang的错误——特别是因为这个解决方案再次模糊了C和C++之间的语言障碍。p>

我稍后采用的第二个解决方案是从distutlis外部的C代码创建一个静态库,并链接Python extension to that static library

相关问题 更多 >