编程语言
首页 > 编程语言> > 使用pybind11为Python编写C++扩展(一)配置篇:Build(编译和链接)

使用pybind11为Python编写C++扩展(一)配置篇:Build(编译和链接)

作者:互联网

目录
最后决定选用pybind11,理由如下:

  1. 比python原生的C API看起来人性多了
  2. 我的C++代码不是现成的,需要一定的C++开发工作量,所以感觉cython不是很方便。如果C++接口已经给好了,只需要简单包装一下,Cython可能更好。
  3. pybind11声称只包含头文件,且能通过pip安装,感觉比boost_python轻量且最后这个扩展包容易分发。此外,感觉它的文档也比boost python友好不少……

Setuptools

参考官方的Setuptools构建文档

这种方式适合python包的构建、打包、分发、上传到PyPi一条龙服务。python使用C++扩展需要在setup.py里配置好Extension。以下是一个setup.py的样例:

import glob
import os.path
from distutils.core import setup

__version__ = "0.0.1"

# make sure the working directory is BASE_DIR
BASE_DIR = os.path.dirname(__file__)
os.chdir(BASE_DIR)

ext_modules = []

try:
    from pybind11.setup_helpers import Pybind11Extension, ParallelCompile, naive_recompile

    # `N` is to set the bumer of threads
    # `naive_recompile` makes it recompile only if the source file changes. It does not check header files!
    ParallelCompile("NPY_NUM_BUILD_JOBS", needs_recompile=naive_recompile, default=4).install()

    # could only be relative paths, otherwise the `build` command would fail if you use a MANIFEST.in to distribute your package
    # only source files (.cpp, .c, .cc) are needed
    source_files = glob.glob('source/path/*.cpp', recursive=True)

    # If any libraries are used, e.g. libabc.so
    include_dirs = ["INCLUDE_DIR"]
    library_dirs = ["LINK_DIR"]
    # (optional) if the library is not in the dir like `/usr/lib/`
    # either to add its dir to `runtime_library_dirs` or to the env variable "LD_LIBRARY_PATH"
    # MUST be absolute path
    runtime_library_dirs = [os.path.abspath("LINK_DIR")]
    libraries = ["abc"]

    ext_modules = [
        Pybind11Extension(
            "package.this_package", # depends on the structure of your package
            source_files,
            # Example: passing in the version to the compiled code
            define_macros=[('VERSION_INFO', __version__)],
            include_dirs=include_dirs,
            library_dirs=library_dirs,
            runtime_library_dirs=runtime_library_dirs,
            libraries=libraries,
            cxx_std=14,
            language='c++'
        ),
    ]
except ImportError:
    pass

setup(
    name='project_name',  # used by `pip install`
    version='0.0.1',
    description='xxx',
    ext_modules=ext_modules,
    packages=['package'], # the directory would be installed to site-packages
    setup_requires=["pybind11"],
    install_requires=["pybind11"],
    python_requires='>=3.8',
    include_package_data=True,
    zip_safe=False,
)

一些需要注意的点(坑):

CMake

参考官方的CMake构建文档

如果是编译嵌入python的C++程序,可以用CMake,比较方便。

虽然python extension似乎也可以用CMake,但是还是setuptools比较方便。

我这里主要是用CMake编译C++部分的测试。CMakeLists.txt大概长这样:

# the CMakeList to test the C++ part from a C entry point
cmake_minimum_required(VERSION 3.21)
project(project_name)

set(CMAKE_CXX_STANDARD 14)

# Find pybind11
find_package(pybind11 REQUIRED)

# If any library (e.g. libabc.so) is needed
include_directories(INCLUDE_DIR)
link_directories(LINK_DIR)

# Add source file
file(GLOB A_NAME_FOR_SOURCE CONFIGURE_DEPENDS "source/path/*.cpp")
file(GLOB A_NAME_FOR_TEST CONFIGURE_DEPENDS "test/path/*.cpp")
add_executable(TARGET_NAME test_cpp_part.cpp ${A_NAME_FOR_SOURCE} ${A_NAME_FOR_TEST})
target_link_libraries(TARGET_NAME abc pybind11::embed)

标签:dirs,package,Python,setup,C++,python,Build,pybind11
来源: https://www.cnblogs.com/milliele/p/15856813.html