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. chrome “从 Google 获取图片说明”

    右键菜单"从 Google 获取图片说明"多余去掉. 设置-高级-使用硬件加速模式(如果可用)-关闭 在用户使用上firefox完胜chrome,但是firefox的开发人员工具相 ...

  2. IDEA在检查更新的时候报错 Connection Error Failed to load plugins from 'https://plugins.jetbrains.com/idea': org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 3; 文档中根元素前面的标记必须格式正确。

    问题: IDEA在更新的时候报错 Connection Error Failed to load plugins from 'https://plugins.jetbrains.com/idea': ...

  3. 【笔记】reko 0.10.2 反编译工具安装和使用记录|(1) README.md

    (翻译自README.md,并通过自己的实际操作情况重新整理了一遍) 笔者注:我已经成功地根据README.md下载了Release版本,也自己试了下从源码编译,跟着README都挺顺利的.如果操作过 ...

  4. Pandas 批量处理文本表

    就是一个批量读取文件, 然后计算指标的过程. 难度到是没啥, 只是想记录一把, 毕竟这类的需求, 其实还是蛮多的. 但涉及一些数据的安全, 和指标这块也是不能透露的, 因此只能是贴上代码, 目的还是给 ...

  5. SpringAI-RC1正式发布:移除千帆大模型!

    续 Spring AI M8 版本之后(5.1 发布),前几日 Spring AI 悄悄的发布了最新版 Spring AI 1.0.0 RC1(5.13 发布),此版本也将是 GA(Generally ...

  6. Python 潮流周刊#102:微软裁员 Faster CPython 团队(摘要)

    本周刊由 Python猫 出品,精心筛选国内外的 250+ 信息源,为你挑选最值得分享的文章.教程.开源项目.软件工具.播客和视频.热门话题等内容.愿景:帮助所有读者精进 Python 技术,并增长职 ...

  7. 秒杀/高并发解决方案+落地实现 (技术栈: SpringBoot+Mysql + Redis +RabbitMQ +MyBatis-Plus +Maven + Linux + Jmeter )-01

    秒杀/高并发方案-介绍 @ 目录 秒杀/高并发方案-介绍 秒杀/高并发解决方案+落地实现 (技术栈: SpringBoot+Mysql + Redis +RabbitMQ +MyBatis-Plus ...

  8. 通用jar包部署脚本

      在<Linux下部署Spring Boot 项目 jar包>中,小编介绍了一步一步发布jar包的方法,这里提供一个通用Shell脚本,傻瓜式发布Spring Boot项目.   通过W ...

  9. Django Web应用开发实战第十六章

    一.即时通信 - AJAX技术:通过AJAX实现网页与服务器的无刷新交互,在网页上每隔一段时间就通过AJAX从服务器中获取数据.然后将数据更新并显示在网页上,这种方法简单明了,实时性不高. - Com ...

  10. 《刚刚问世》系列初窥篇-Java+Playwright自动化测试-17- 如何优雅地切换浏览器多窗口(详细教程)

    1.简介 有时候我们在网页上点击一些按钮或超链接时,有时会打开一个新的网页窗口.这个时候如果下一步操作是在新的网页窗口上,那么就需要切换网页窗口,切换到新的网页窗口后再执行元素定位等操作.Playwr ...