将 C++ 扩展标头与 Python 包源代码分发捆绑在一起

Dan*_*age 5 python packaging python-extensions python-packaging

我正在为 C++ 库编写 Cython 包装器,我想将其作为 Python 包分发。我已经想出了我的包的虚拟版本,如下所示(完整源代码在这里)。

\n\n
$ tree\n.\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 bogus.pyx\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 inc\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 bogus.hpp\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 setup.py\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 src\n    \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 bogus.cpp\n$\n$ cat inc/bogus.hpp \n#ifndef BOGUS\n#define BOGUS\n\nclass bogus\n{\nprotected:\n    int data;\n\npublic:\n    bogus();\n    int get_double(int value);\n};\n\n#endif\n$\n$ cat src/bogus.cpp \n#include "bogus.hpp"\n\nbogus::bogus() : data(0)\n{\n\n}\n\nint bogus::get_double(int value)\n{\n    data = value * 2;\n    return data;\n}\n$ cat bogus.pyx \n# distutils: language = c++\n# distutils: sources = src/bogus.cpp\n# cython: c_string_type=str, c_string_encoding=ascii\n\ncdef extern from \'bogus.hpp\':\n    cdef cppclass bogus:\n        bogus() except +\n        int get_double(int value)\n\ncdef class Bogus:\n    cdef bogus b\n    def get_double(self, int value):\n        return self.b.get_double(value)\n
Run Code Online (Sandbox Code Playgroud)\n\n

通过以下setup.py文件,我可以确认该库是否正确安装python setup.py install并且可以正常工作。

\n\n
from setuptools import setup, Extension\nimport glob\n\nheaders = list(glob.glob(\'inc/*.hpp\'))\n\nbogus = Extension(\n    \'bogus\',\n    sources=[\'bogus.pyx\', \'src/bogus.cpp\'],\n    include_dirs=[\'inc/\'],\n    language=\'c++\',\n    extra_compile_args=[\'--std=c++11\', \'-Wno-unused-function\'],\n    extra_link_args=[\'--std=c++11\'],\n)\n\nsetup(\n    name=\'bogus\',\n    description=\'Troubleshooting Python packaging and distribution\',\n    author=\'Daniel Standage\',\n    ext_modules=[bogus],\n    install_requires=[\'cython\'],\n    version=\'0.1.0\'\n)\n
Run Code Online (Sandbox Code Playgroud)\n\n

但是,当我使用 构建源发行版时python setup.py sdist build,不包含 C++ 头文件,并且无法编译 C++ 扩展。

\n\n

我如何确保 C++ 头文件与源代码分发捆绑在一起?!?!

\n\n

<咆哮>

\n\n

对此问题进行故障排除发现了极其复杂且不一致的文档、建议和黑客,但这些都对我不起作用。放一条graft线进去MANIFEST.in?没有。或package_data选项data_files?没有。在过去的几年里,Python 打包似乎有了很大的改进,但对于我们这些不熟悉 Python 打包的人来说,它仍然几乎是难以理解的!

\n\n

</咆哮>

\n

Dan*_*age 3

简短回答

放入文件include inc/*.hpp中MANIFEST.in。

长答案

基于各种博客文章和 SO 线程,我尝试了在文件中声明文件的建议MANIFEST.in。按照这些说明,我添加了一行graft inc/以MANIFEST.in包含整个目录。这不起作用。

然而,用 替换这条线include inc/*.hpp确实有效。可以说这应该是我尝试的第一件事,但由于不熟悉 setuptools 和 distutils 的复杂性和缺陷,我没有理由认为这graft是行不通的。