在Cython编译C和C++源代码 我试图在Cython同时编译C和C++源代码。这是我当前的设置:

在Cython编译C和C++源代码 我试图在Cython同时编译C和C++源代码。这是我当前的设置:,c++,compiler-errors,clang,cython,clang++,C++,Compiler Errors,Clang,Cython,Clang++,-setup.py from distutils.core import setup from Cython.Build import cythonize from distutils.extension import Extension import os language = "c++" extra_compile_flags = ["-std=c++17"] os.environ["CC"] = "clang++" ext_modules = [ Extension(

-setup.py

from distutils.core import setup
from Cython.Build import cythonize
from distutils.extension import Extension
import os

language = "c++"
extra_compile_flags = ["-std=c++17"]
os.environ["CC"] = "clang++"

ext_modules = [
    Extension(
        name="Dummy",
        sources=["mydummy.pyx", "source1.cpp","source2.c"],
        language=language,
        extra_compile_args=extra_compile_flags,
   )
]

ext_modules = cythonize(ext_modules)

setup(
    name="myapp",
    ext_modules=ext_modules,
)
-编译命令:

python3 setup.py build_ext --inplace --verbose
在日志中,我收到以下消息:

clang++ -DNDEBUG -g -fwrapv -O2 -Wall -g -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -fPIC -I. -I/usr/include/python3.6m -I/usr/include/python3.6m -c /path/source2.c -o build/temp.linux-x86_64-3.6/./path/source2.o -std=c++17 -O3
clang: warning: treating 'c' input as 'c++' when in C++ mode, this behavior is deprecated [-Wdeprecated]
汇编工作进展顺利,但警告看起来相当糟糕。我怎样才能摆脱它? 天真的解决方案

os.environ["CC"] = "clang"
os.environ["CXX"] = "clang++"

由于错误而失败:无效参数“-std=c++17”不允许与“c”

gcc或clang只是一个前端,它根据编译文件的文件扩展名调用相应的编译器c-或c++-编译器。c表示应使用c-编译器编译,而.cpp表示应使用c++编译器编译,例如,请参见类似的示例

因此,不需要将编译器设置为clang++,因为它将自动发生

但是,cython需要知道,它必须生成一个cpp文件,同时接受c++语法,而不是c文件。链接器还必须知道,它必须与cpp库进行链接。如果使用g++/clang++进行链接,则会自动进行链接。因此,我们需要在DavidW的回答中建议将语言+C++添加到扩展的定义中,这将解决最后两个问题。 剩下的问题是,我们希望对不同源文件的cpp文件使用不同的编译器选项-std=c++17。这可以使用一个不太为人所知的命令来实现:

setup.py: 从distutils.core导入设置 从Cython.Build导入cythonize 从distutils.extension导入扩展 外部模块=[ 扩大 name=mydummy, sources=[mydummy.pyx,source1.cpp] 语言=c++, 额外编译参数=[-std=c++17], ] ext_模块=cythonizeext_模块 myclib='myclib',{'sources':[source2.c]} 设置 name=mydummy, 库=[myclib], ext_模块=ext_模块, 现在,无论是用

python setup.py build --verbose

将首先构建一个由C代码组成的简单静态库,并将其链接到由C++代码组成的最终扩展

上面的代码在构建静态库时使用默认编译标志,这在您的情况下应该足够了

distutils允许指定附加标志,因此如果有必要,我们必须切换到提供此功能的标志,或者修补build_clib命令

对于第二个备选方案,我们必须将以下内容添加到上述setup.py文件中:

setup.py ... 添加cflags以构建clib 从distutils导入日志 从distutils.command.build\u clib导入build\u clib 使用原始实现,但使用经过调整的构建库! 类build\u clib\u与\u cflagsbuild\u clib: def构建库自身,库: 对于库名称,在库中生成库信息: sources=构建信息。获取“sources” 如果源为None或not isinstancesources,则列表、元组: raise DISTUTILSSETUP错误 在“库”选项库“%s”中, “来源”必须存在且必须是 源文件名%lib\u name的列表 源=列表源 log.infobuilding“%s”库,库名称 宏=构建信息。获取“宏” include\u dirs=构建信息。获取“include\u dirs” cflags=构建信息。获取“cflags”在这里我们添加cflags 对象=self.compiler.compilesources, 输出目录=自构建温度, 宏=宏, include_dirs=include_dirs, extra_postargs=cflags,这里我们使用cflags debug=self.debug self.compiler.create_static_libobjects,lib_name, output\u dir=self.build\u clib, debug=self.debug ... 设置 ... cmdclass={'build\u clib':使用\u cflags}构建\u clib\u,请使用我们的类而不是内置类! 现在,我们可以向库定义添加其他编译标志。如果使用setuptools,则可以跳过上一步:


gcc或clang只是一个前端,它根据编译文件的文件扩展名调用相应的编译器c-或c++-编译器。c表示它应该用c-编译器编译,.cpp表示它应该用c++编译器编译,例如,请参见此类似示例

因此,不需要将编译器设置为clang++,因为它将自动发生

但是,cython需要知道,它必须生成一个cpp文件,同时接受c++语法,而不是c文件。链接器还必须知道,它必须与cpp库进行链接。如果使用g++/clang++进行链接,则会自动进行链接。因此,我们需要在DavidW的回答中建议将语言+C++添加到扩展的定义中。 e注意最后两个问题

剩下的问题是,我们希望对不同源文件的cpp文件使用不同的编译器选项-std=c++17。这可以使用一个不太为人所知的命令来实现:

setup.py: 从distutils.core导入设置 从Cython.Build导入cythonize 从distutils.extension导入扩展 外部模块=[ 扩大 name=mydummy, sources=[mydummy.pyx,source1.cpp] 语言=c++, 额外编译参数=[-std=c++17], ] ext_模块=cythonizeext_模块 myclib='myclib',{'sources':[source2.c]} 设置 name=mydummy, 库=[myclib], ext_模块=ext_模块, 现在,无论是用

python setup.py build --verbose

将首先构建一个由C代码组成的简单静态库,并将其链接到由C++代码组成的最终扩展

上面的代码在构建静态库时使用默认编译标志,这在您的情况下应该足够了

distutils允许指定附加标志,因此如果有必要,我们必须切换到提供此功能的标志,或者修补build_clib命令

对于第二个备选方案,我们必须将以下内容添加到上述setup.py文件中:

setup.py ... 添加cflags以构建clib 从distutils导入日志 从distutils.command.build\u clib导入build\u clib 使用原始实现,但使用经过调整的构建库! 类build\u clib\u与\u cflagsbuild\u clib: def构建库自身,库: 对于库名称,在库中生成库信息: sources=构建信息。获取“sources” 如果源为None或not isinstancesources,则列表、元组: raise DISTUTILSSETUP错误 在“库”选项库“%s”中, “来源”必须存在且必须是 源文件名%lib\u name的列表 源=列表源 log.infobuilding“%s”库,库名称 宏=构建信息。获取“宏” include\u dirs=构建信息。获取“include\u dirs” cflags=构建信息。获取“cflags”在这里我们添加cflags 对象=self.compiler.compilesources, 输出目录=自构建温度, 宏=宏, include_dirs=include_dirs, extra_postargs=cflags,这里我们使用cflags debug=self.debug self.compiler.create_static_libobjects,lib_name, output\u dir=self.build\u clib, debug=self.debug ... 设置 ... cmdclass={'build\u clib':使用\u cflags}构建\u clib\u,请使用我们的类而不是内置类! 现在,我们可以向库定义添加其他编译标志。如果使用setuptools,则可以跳过上一步:


我想你误解了我的一点回答:我建议不要在setup.py中使用language=c++,这也已经在原始问题中了。相反,我建议只把它放在pyx文件中。答案的其余部分似乎是为不同的源指定不同的命令行参数的合理方法。我想我的另一个问题是:扩展是否与myclib链接,还是DavidW是我创建的?”我确信DITCUTIL:语言= C++具有与通过扩展的语言参数设置相同的效果。它不仅仅是从PYX文件生成CPP文件,而且还使用G+来链接。@当连接实际扩展时,将传递的LIMyclib。A链接到链接器。将语言放在setup.py中也会强制将其放在源代码中列出的任何.c文件上,这无论如何都不会影响您的答案。这似乎是错误的,所以我删除了我的答案,因为这是我的主要观点。我也不确定默认情况下库是否链接到所有的东西,也没有文档。我想你已经测试过了,所以我现在要安静了……我想你误解了我的一点回答:我建议不要在setup.py中使用language=c++,这也已经在原始问题中了。相反,我建议只把它放在pyx文件中。答案的其余部分似乎是为不同的源指定不同的命令行参数的合理方法。我想我的另一个问题是:扩展是否与myclib链接,还是DavidW是我创建的?”我确信DITCUTIL:语言= C++具有与通过扩展的语言参数设置相同的效果。它不仅仅是从PYX文件生成CPP文件,而且还使用G+来链接。@当连接实际扩展时,将传递的LIMyclib。A链接到链接器。将语言置于设置中 .py还将其强制应用于源代码中列出的任何.c文件,这无论如何都不会影响您的答案。这似乎是错误的,所以我删除了我的答案,因为这是我的主要观点。我也不确定默认情况下库是否链接到所有的东西,也没有文档。我想你已经测试过了,所以我现在会安静下来。。。
...
myclib = ('myclib', {'sources': ["source2.c"], 'cflags' : ["-O3"]})
...