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

时间:2019-03-30 21:22:38

标签: python c++ cython cythonize

我试图弄清楚如何使用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 ++文件很奇怪。我可以通过将g++添加到setup.py来强制其使用 os.environ["CC"] = "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

1 个答案:

答案 0 :(得分:3)

这是一个类似的问题: 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)