为啥我可以在 Mac OS X 上使用 Cython 编译为 C 但不能编译为 C++

Posted

技术标签:

【中文标题】为啥我可以在 Mac OS X 上使用 Cython 编译为 C 但不能编译为 C++【英文标题】:Why can I compile as C but not as C++ with Cython on Mac OS X为什么我可以在 Mac OS X 上使用 Cython 编译为 C 但不能编译为 C++ 【发布时间】:2019-08-21 11:27:30 【问题描述】:

我想弄清楚如何使用 Cython 在 python 中使用 C/C++ 代码。我可以将以下示例用作 C 代码:

sum.h:

#ifndef MY_SUM_H_
#define MY_SUM_H_

int my_sum(int a, int b);

#endif

sum.c:

int my_sum(int a, int b)
    return a + b;

test.pyx:

cdef extern from "my_sum.h":
    cdef int my_sum(int a, int b)

cpdef sum_wrap(int a, int b):
    return my_sum(a, b)

setup.py:

from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext

ext_modules = [Extension("test", ["test.pyx", "my_sum.c"], language = "c")]

setup(cmdclass = 'build_ext': build_ext, ext_modules = ext_modules)

但是,如果我尝试将其作为 C++ 代码进行测试,则会失败。我将 sum.c 重命名为 sum.cpp 并在 setup.py 中将 language 更改为 c++。之后,它看起来像这样:

from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext

ext_modules = [Extension("test", ["test.pyx", "my_sum.cpp"], language = "c++")]

setup(cmdclass = 'build_ext': build_ext, ext_modules = ext_modules)

应该够了吧?它会产生以下错误:

$ python setup.py build_ext --inplace
running build_ext
cythoning test.pyx to test.cpp
/Users/jensrenders/miniconda3/lib/python3.7/site-packages/Cython/Compiler/Main.py:367: FutureWarning: Cython directive 'language_level' not set, using 2 for now (Py2). This will change in a later release! File: /Users/jensrenders/Dropbox/cython_demo/test.pyx
  tree = Parsing.p_module(s, pxd, full_module_name)
building 'test' extension
gcc -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -I/Users/jensrenders/miniconda3/include -arch x86_64 -I/Users/jensrenders/miniconda3/include -arch x86_64 -I/Users/jensrenders/miniconda3/include/python3.7m -c test.cpp -o build/temp.macosx-10.7-x86_64-3.7/test.o
warning: include path for stdlibc++ headers not found; pass '-std=libc++' on the command line to use the libc++ standard
      library instead [-Wstdlibcxx-not-found]
1 warning generated.
gcc -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -I/Users/jensrenders/miniconda3/include -arch x86_64 -I/Users/jensrenders/miniconda3/include -arch x86_64 -I/Users/jensrenders/miniconda3/include/python3.7m -c my_sum.cpp -o build/temp.macosx-10.7-x86_64-3.7/my_sum.o
warning: include path for stdlibc++ headers not found; pass '-std=libc++' on the command line to use the libc++ standard
      library instead [-Wstdlibcxx-not-found]
1 warning generated.
g++ -bundle -undefined dynamic_lookup -L/Users/jensrenders/miniconda3/lib -arch x86_64 -L/Users/jensrenders/miniconda3/lib -arch x86_64 -arch x86_64 build/temp.macosx-10.7-x86_64-3.7/test.o build/temp.macosx-10.7-x86_64-3.7/my_sum.o -o /Users/jensrenders/Dropbox/cython_demo/test.cpython-37m-darwin.so
clang: warning: libstdc++ is deprecated; move to libc++ with a minimum deployment target of OS X 10.9 [-Wdeprecated]
ld: library not found for -lstdc++
clang: error: linker command failed with exit code 1 (use -v to see invocation)
error: command 'g++' failed with exit status 1

我确实得到了一个test.cpp 文件作为输出,但没有共享对象。 是什么原因造成的,如何解决?

感谢您的帮助!


编辑: 正如@MaximEgorushkin 指出的那样,cython 尝试使用gcc 编译C++ 文件很奇怪。我可以通过将 os.environ["CC"] = "g++" 添加到setup.py 来强制它使用g++,但这并不能解决问题:

$ python setup.py build_ext --inplace
running build_ext
building 'test' extension
g++ -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -I/Users/jensrenders/miniconda3/include -arch x86_64 -I/Users/jensrenders/miniconda3/include -arch x86_64 -I/Users/jensrenders/miniconda3/include/python3.7m -c test.cpp -o build/temp.macosx-10.7-x86_64-3.7/test.o
warning: include path for stdlibc++ headers not found; pass '-std=libc++' on the command line to use the libc++ standard
      library instead [-Wstdlibcxx-not-found]
1 warning generated.
g++ -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -I/Users/jensrenders/miniconda3/include -arch x86_64 -I/Users/jensrenders/miniconda3/include -arch x86_64 -I/Users/jensrenders/miniconda3/include/python3.7m -c my_sum.cpp -o build/temp.macosx-10.7-x86_64-3.7/my_sum.o
warning: include path for stdlibc++ headers not found; pass '-std=libc++' on the command line to use the libc++ standard
      library instead [-Wstdlibcxx-not-found]
1 warning generated.
g++ -bundle -undefined dynamic_lookup -L/Users/jensrenders/miniconda3/lib -arch x86_64 -L/Users/jensrenders/miniconda3/lib -arch x86_64 -arch x86_64 build/temp.macosx-10.7-x86_64-3.7/test.o build/temp.macosx-10.7-x86_64-3.7/my_sum.o -o /Users/jensrenders/Dropbox/cython_demo/test.cpython-37m-darwin.so
clang: warning: libstdc++ is deprecated; move to libc++ with a minimum deployment target of OS X 10.9 [-Wdeprecated]
ld: library not found for -lstdc++
clang: error: linker command failed with exit code 1 (use -v to see invocation)
error: command 'g++' failed with exit status 1

【问题讨论】:

它应该使用g++来编译.cpp文件,而不是gcc ... -c my_sum.cpp -o my_sum.o 仅供参考,C++ 中的 C 声明 int my_sum(int, int)extern "C" int my_sum(int, int)。如果您不调整 Cython 代码中的相应声明,它们将不匹配,因此事情会失败。 BTW:没有“C/C++代码”这样的东西,C和C++是不同的语言。 @UlrichEckhardt 在 C++ 中 int my_sum(int, int)extern "C++"。这就是这里所需要的。 @UlrichEckhardt 是的,它们是不同的语言,但我上面的 C 代码也是有效的 C++ 代码,对吧?我尝试将其视为 C++ 代码,以便以后在此工作后使用更多 C++ 功能。 阅读警告和错误信息,C++ 标准库似乎没有正确安装。被执行以编译为 C++ 和链接的命令似乎都需要它(这在构建为 C++ 时是相当正常的)。因此,您需要检查您的 C++ 编译器和标准库是否已正确安装,以及编译器是否正在查找它所期望的标准库版本和相关标头。该问题也可能是环境变量设置不正确造成的。 【参考方案1】:

这是一个类似的问题: https://github.com/pandas-dev/pandas/issues/23424

正如他们所建议的,并且如输出中的行所示

clang: warning: libstdc++ is deprecated; move to libc++ with a minimum deployment target of OS X 10.9 [-Wdeprecated]

添加extra_link_args=["-stdlib=libc++", "-mmacosx-version-min=10.9"] 解决了这个问题。 setup.py 然后看起来像这样:

from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext

ext_modules = [Extension("test",
                         sources=["test.pyx", "my_sum.cpp"],
                         language="c++",
                         extra_link_args=["-stdlib=libc++", "-mmacosx-version-min=10.9"])]

setup(cmdclass = 'build_ext': build_ext, ext_modules = ext_modules)

【讨论】:

以上是关于为啥我可以在 Mac OS X 上使用 Cython 编译为 C 但不能编译为 C++的主要内容,如果未能解决你的问题,请参考以下文章

为啥来自 /dev/null 的 ioctl FIONREAD 在 Mac OS X 上返回 0 而在 Linux 上返回随机数?

为啥“光标下的跟随符号”在 Mac OS X 的 Qt Creator 中不起作用?

为啥在线程中使用 system() 时,多线程 C 程序在 Mac OS X 上被强制使用单个 CPU?

为啥mac升级之后,升级成mac OS Sierra 10.12.1,我的parallels Desktop就启动不了,需要重新安装吗?

在 Mac OS X 上检索系统信息 [关闭]

Haskell openGL 和 GLUT 在 Mac OS X 上冻结?我可以在 GLUT 上使用 GLFW 吗?