1. pybind:pybind11 — Seamless operability between C++11 and Python
  • header-only library exposes C++ types in Python and vice versa,
  • inferring type information using compile-time introspection.
  • mainly to create Python bindings of existing C++ code.
  • Its goals and syntax are similar to the excellent Boost.Python library by David Abrahams: to minimize boilerplate code in traditional extension modules
  • Think of this library as a tiny self-contained version of Boost.Python with everything stripped away that isn’t relevant for binding generation. Without comments, the core header files only require ~4K lines of code and depend on Python (3.6+, or PyPy) and the C++ standard library. This compact implementation was possible thanks to some of the new C++11 language features (specifically: tuples, lambda functions and variadic templates). Since its creation, this library has grown beyond Boost.Python in many ways, leading to dramatically simpler binding code in many common situations.
  1. pybind(pybind11-config)
  • Install:

    • pip install pybind11 cmake : as a standard Python package:
    • pip install "pybind11[global]" cmake : want available directly in your env. root:

      it will add files to:

      /usr/local/include/pybind11

      /usr/local/share/cmake/pybind11
  • Command-line Usage:

    • pybind11-config [--version] [--includes] [--cmakedir] [--pkgconfigdir]

      • pybind11-config --includes:

        -I<PYTHON_INSTALL_DIR>/include/python3.12

        -I<PY_LIB_DIR>/site-packages/pybind11/include
      • pybind11-config --cmakedir:

        <PY_LIB_DIR>/site-packages/pybind11/share/cmake/pybind11
      • pybind11-config --pkgconfigdir:

        <PY_LIB_DIR>/site-packages/pybind11/share/pkgconfig
  • CMake 直接包含 pybind 的头文件方式:

if(APPLE)
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-everything -w -undefined dynamic_lookup")
set (CMAKE_FIND_FRAMEWORK LAST)
endif() option(PYBIND_INCS "The output of `pybind11-config --includes` " OFF)
IF(NOT PYBIND_INCS)
EXECUTE_PROCESS(COMMAND sh -c 'pybind11-config --includes' OUTPUT_VARIABLE PYBIND_INCS ERROR_QUIET COMMAND_ERROR_IS_FATAL ANY)
SET(PYBIND_INCS "${PYBIND_INCS}" CACHE STRING "The output of `pybind11-config --includes`")
ENDIF()
message(STATUS "***** Detected PYBIND_INCS:${PYBIND_INCS}")
SET(CMAKE_CXX_FLAGS "${PYBIND_INCS} ${CMAKE_CXX_FLAGS}")
SET(CMAKE_C_FLAGS "${PYBIND_INCS} ${CMAKE_C_FLAGS}")
FIND_PACKAGE(pybind11 REQUIRED) # Define pybind11 tree module.
find_package(PyBind)
pybind11_add_module(_tree tree.h tree.cc) SET(ABSL_DEPS absl::int128 absl::raw_hash_set absl::raw_logging_internal absl::memory absl::strings absl::throw_delegate)
FIND_PACKAGE(absl REQUIRED COMPONENTS ${ABSL_DEPS})
if (absl_FOUND)
message("Found 'absl':${absl_CONFIG}")
GET_TARGET_PROPERTY(ABSL_INC_DIR absl::strings INTERFACE_INCLUDE_DIRECTORIES)
GET_TARGET_PROPERTY(ABSL_LIBS absl::strings INTERFACE_LINK_LIBRARIES)
message(" 'absl incs':${ABSL_INC_DIR}, ${ABSL_LIBS}" )
target_link_libraries(_tree PRIVATE ${ABSL_DEPS})
else()
message("Not Found: 'absl'")
endif()
  • Compiling the test cases on Linux/macOS:

    • On Linux you’ll need to install the python-dev or python3-dev packages as well as cmake.
    • On macOS, the included python version works out of the box, but cmake must still be installed.

    After installing the prerequisites, run(The last line will both compile and run the tests.)

mkdir build
cd build
cmake ..
make check -j 4
  • Header and namespace conventions

    For brevity, all code examples assume that the following two lines are present(Some features may require additional headers, but those will be specified as needed.):
#include <pybind11/pybind11.h>
namespace py = pybind11;
  • Example:
  • Python Example: https://github.com/pybind/python_example
  • CMake Example: https://github.com/pybind/cmake_example

    For simplicity 1, we’ll put both this function and the binding code into a file named example.cpp with the following contents:

    • In practice, implementation and binding code will generally be located in separate files.
    • The PYBIND11_MODULE() macro creates a function that will be called when an import statement is issued from within Python.

      The module name (example) is given as the first macro argument (it should not be in quotes).

      The second argument (m) defines a variable of type py::module_ which is the main interface for creating bindings.

      The method module_::def() generates binding code that exposes the add() function to Python.
#include <pybind11/pybind11.h>

int add(int i, int j) {
return i + j;
} PYBIND11_MODULE(example, m) {
m.doc() = "pybind11 example plugin"; // optional module docstring m.def("add", &add, "A function that adds two numbers");
}

https://github.com/google-deepmind/tree/setup.py

"""Setup for pip package."""

import os, platform, sys, sysconfig, shutil, subprocess, setuptools

from setuptools.command import build_ext

here = os.path.dirname(os.path.abspath(file))

def _get_tree_version():
"""Parse the version string from tree/__init__.py."""
with open(os.path.join(here, 'tree', '__init__.py')) as f:
try:
version_line = next(line for line in f if line.startswith('__version__'))
except StopIteration:
raise ValueError('__version__ not defined in tree/__init__.py')
else:
ns = {}
exec(version_line, ns) # pylint: disable=exec-used
return ns['__version__'] def _parse_requirements(path):
with open(os.path.join(here, path)) as f:
return [
line.rstrip() for line in f
if not (line.isspace() or line.startswith('#'))
] class CMakeExtension(setuptools.Extension):
"""An extension with no sources. We do not want distutils to handle any of the compilation (instead we rely
on CMake), so we always pass an empty list to the constructor.
""" def __init__(self, name, source_dir=''):
super().__init__(name, sources=[])
self.source_dir = os.path.abspath(source_dir) class BuildCMakeExtension(build_ext.build_ext):
"""Our custom build_ext command. Uses CMake to build extensions instead of a bare compiler (e.g. gcc, clang).
""" def run(self):
self._check_build_environment()
for ext in self.extensions:
self.build_extension(ext) def _check_build_environment(self):
"""Check for required build tools: CMake, C++ compiler, and python dev."""
try:
subprocess.check_call(['cmake', '--version'])
except OSError as e:
ext_names = ', '.join(e.name for e in self.extensions)
raise RuntimeError(
f'CMake must be installed to build the following extensions: {ext_names}'
) from e
print('Found CMake') def build_extension(self, ext):
extension_dir = os.path.abspath(
os.path.dirname(self.get_ext_fullpath(ext.name)))
build_cfg = 'Debug' if self.debug else 'Release'
cmake_args = [
f'-DPython3_ROOT_DIR={sys.prefix}',
f'-DPython3_EXECUTABLE={sys.executable}',
f'-DCMAKE_LIBRARY_OUTPUT_DIRECTORY={extension_dir}',
f'-DCMAKE_BUILD_TYPE={build_cfg}'
]
if platform.system() != 'Windows':
cmake_args.extend([
f'-DPython3_LIBRARY={sysconfig.get_paths()["stdlib"]}',
f'-DPython3_INCLUDE_DIR={sysconfig.get_paths()["include"]}',
])
if platform.system() == 'Darwin' and os.environ.get('ARCHFLAGS'):
osx_archs = []
if '-arch x86_64' in os.environ['ARCHFLAGS']:
osx_archs.append('x86_64')
if '-arch arm64' in os.environ['ARCHFLAGS']:
osx_archs.append('arm64')
cmake_args.append(f'-DCMAKE_OSX_ARCHITECTURES={";".join(osx_archs)}')
os.makedirs(self.build_temp, exist_ok=True)
subprocess.check_call(
['cmake', ext.source_dir] + cmake_args, cwd=self.build_temp)
subprocess.check_call(
['cmake', '--build', '.', f'-j{os.cpu_count()}', '--config', build_cfg],
cwd=self.build_temp) # Force output to <extension_dir>/. Amends CMake multigenerator output paths
# on Windows and avoids Debug/ and Release/ subdirs, which is CMake default.
tree_dir = os.path.join(extension_dir, 'tree') # pylint:disable=unreachable
for cfg in ('Release', 'Debug'):
cfg_dir = os.path.join(extension_dir, cfg)
if os.path.isdir(cfg_dir):
for f in os.listdir(cfg_dir):
shutil.move(os.path.join(cfg_dir, f), tree_dir) setuptools.setup(
name='dm-tree',
version=_get_tree_version(),
url='https://github.com/deepmind/tree',
description='Tree is a library for working with nested data structures.',
author='DeepMind',
author_email='tree-copybara@google.com',
long_description=open(os.path.join(here, 'README.md')).read(),
long_description_content_type='text/markdown',
# Contained modules and scripts.
packages=setuptools.find_packages(),
tests_require=_parse_requirements('requirements-test.txt'),
test_suite='tree',
cmdclass=dict(build_ext=BuildCMakeExtension),
ext_modules=[CMakeExtension('_tree', source_dir='tree')],
zip_safe=False,
# PyPI package information.
classifiers=[
'Development Status :: 4 - Beta',
'Intended Audience :: Developers',
'Intended Audience :: Science/Research',
'License :: OSI Approved :: Apache Software License',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: 3.10',
'Programming Language :: Python :: 3.11',
'Topic :: Scientific/Engineering :: Mathematics',
'Topic :: Software Development :: Libraries',
],
license='Apache 2.0',
keywords='tree nest flatten',
)

SciTech-Python-编译Python的C/C++扩展的setup.py使用pybind映射C/C++到Python库的更多相关文章

  1. Python 库打包分发、setup.py 编写、混合 C 扩展打包的简易指南(转载)

    转载自:http://blog.konghy.cn/2018/04/29/setup-dot-py/ Python 有非常丰富的第三方库可以使用,很多开发者会向 pypi 上提交自己的 Python ...

  2. Python各种扩展名(py, pyc, pyw, pyo, pyd)区别

    扩展名 在写Python程序时我们常见的扩展名是py, pyc,其实还有其他几种扩展名.下面是几种扩展名的用法. py py就是最基本的源码扩展名 pyw pyw是另一种源码扩展名,跟py唯一的区别是 ...

  3. [Python] [转] python.exe和pythonw.exe的区别(区分.py、.pyw、.pyc文件)

    Windows系统搭建好Python的环境后,进入Python的安装目录,大家会发现目录中有python.exe和pythonw.exe两个程序.如下图所示: 它们到底有什么区别和联系呢? 概括说明一 ...

  4. python 编写简单的setup.py

    学习python也已经有一段时间了,发现python作为脚本语言一个很重要的特点就是简单易用,而且拥有巨多的第三方库,几乎方方面面的库都有,无论你处于哪个行业,想做什么工作,几乎都能找到对应的第三方库 ...

  5. Python中setup.py一些不为人知的技巧

    http://python.jobbole.com/80912/ 在我开始之前,我想先说清楚我将要解释的是些“窍门”.他们不是“最好的做法”,至少在一种情况下是不可取的. 说到不可取的做法,我会适时写 ...

  6. 使用 Python 的 SQLite JSON1 和 FTS5 扩展

    早在九月份,编程界出现一个名为 json1.c 的文件,此前这个文件一直在 SQLite 的库里面.还有,笔者也曾总结通过使用新的 json1 扩展来编译 pysqlite 的技巧.但现在随着 SQL ...

  7. python 教程 第二十一章、 扩展Python

    第二十一章. 扩展Python /* D:\Python27\Lib\Extest-1.0\Extest2.c */ #include <stdio.h> #include <std ...

  8. 2.准备Python编译环境

    2.准备Python编译环境 2.1下载Python2.7.6.tgz.ipython1.2.1.tgz.sqlite-autoconf-3071401.tar.gz 2.2安装Python2.7.6 ...

  9. 【转】ubuntu下安装eclipse以及配置python编译环境

    原文网址:http://blog.csdn.net/wangpengwei2/article/details/17580589 一.安装eclipse 1.从http://www.eclipse.or ...

  10. 使用Code::Blocks配置Python编译环境

    1.先在CodeBlock中新建C或C++工程. CodeBlock新建工程步骤:File——New——Project——Console applications——C或C++都可——Project所 ...

随机推荐

  1. DevEco Studio AI辅助开发工具两大升级功能 鸿蒙应用开发效率再提升

    随着搭载HarmonyOS 5的Pura X发布,鸿蒙生态进入快车道,各应用正在加速适配开发,越来越多开发者加入到鸿蒙应用开发浪潮中.为提升鸿蒙应用开发效率,华为前不久上线了首款开发HarmonyOS ...

  2. coreybutler/nvm-windows 简单使用

    目录 nvm是什么 安装 简单命令 nvm是什么 Windows电脑node.js管理器.可以方便node.js的安装与切换. 最新版本1.1.11 coreybutler/nvm-windows 有 ...

  3. 腾讯CodeBuddy,一款自带MCP市场的编程助手

    今天我发现了一个非常实用的腾讯云编程助手--CodeBuddy.之前它的名称是腾讯云代码助手,但现在已经正式更名为CodeBuddy,并且在更名的同时,其功能也得到了显著增强.今天,我们将详细了解一下 ...

  4. Alembic迁移脚本:让数据库变身时间旅行者

    title: Alembic迁移脚本:让数据库变身时间旅行者 date: 2025/05/09 13:08:18 updated: 2025/05/09 13:08:18 author: cmdrag ...

  5. 那些神奇的CSS特性,你都有用过么?

    @charset "UTF-8"; .markdown-body { line-height: 1.75; font-weight: 400; font-size: 15px; o ...

  6. codeup之C语言10.10

    Description 给定字符串定义char *a = "I love China!",读入整数n,输出在进行了a = a + n这个赋值操作以后字符指针a对应的字符串. Inp ...

  7. CAD如何使用 “库” 和 “打开文件菜单栏” 和 “项目管理器”

    这个是一个简单的问题,就是库工具栏丢了怎么办? 点击 默认-块-插入-库中的块,这个菜单栏就会恢复了 打开文件菜单栏,有些同学的菜单栏默认是不存在的,需要特殊功能时可以使用命令行MANUBAR使其显现 ...

  8. MQTT协议与ODOO的结合使用

     一.MQTT简述      MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种基于发布/订阅(publish/subscribe)模式的 ...

  9. JAVA经典算法分析

      算法分析是对一个算法需要多少计算时间和存储空间作定量的分析. 算法(Algorithm)是解题的步骤,可以把算法定义成解一确定类问题的任意一种特殊的方法.在计算机科学中,算法要用计算机算法语言描述 ...

  10. java netty socket实例:报文长度+报文内容,springboot

    前言 说实话,java netty方面的资料不算多,尤其是自定义报文格式的,少之又少 自己写了个简单的收发:报文长度+报文内容 发送的话,没有写自动组装格式,自己看需求吧,需要的话,自己完善 服务端启 ...