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. Redis Stream消息队列

    工具类部分内容 package com.hwd.campus.common.redis.utils; import com.hwd.campus.common.redis.constant.Redis ...

  2. Java编程--设计模式之装饰者模式

    目录 装饰者模式 简介 做馒头实例 生产汽车实例 常见使用 装饰者模式 简介 装饰者模式的主要功能就是对一个类的功能进行扩充! 对于需要对某个类扩充,但是该类是final类,不能被继承,这是时候可以用 ...

  3. 工具 | Hashcat

    0x00 简介 Hashcat是一款强大的密码破解工具. 下载地址 Hashcat下载: Hashcat下载 0x01 功能说明 直接破解 组合攻击 掩码暴力破解 混合攻击 联合攻击 注:仅供安全研究 ...

  4. linux中部署自己的系统内核

    1.计算机是如何将系统起起来的?-- PC机的引导流程 PC机BIOS固件是固化在PC机主板上的ROM芯片中,断电也能保存,PC机上电后的第一条指令就是在BIOS固件中,它负责检测和初始化CPU.内存 ...

  5. C# 控制台程序验证await立即返回

    class Program{ public static volatile bool flag = true; public static void Main() { Action a = null; ...

  6. Error: A JNI error has occurred, please check your installation and try again Exception in thread "main" java.lang.UnsupportedClassVersionError: HelloWorld has been compiled by a more

    一个新手容易遇到的问题,电脑上装了多个版本的java,比如8和11,导致javac和java的版本不一样 在控制面板里将其他版本卸载,留个8就行 然后在环境变量里重新配置一下就ok

  7. 航空货运系统总结性Blog

    前言 本次题目集以航空运送货物为背景,设计航空货物管理系统,主要考察对类设计的把握是否合理还有对继承和多态的使用,能否设计出符合标准的类,是否充分理解对面向对象六大设计原则(SRP,OCP,LSP,D ...

  8. qt动画类学习

    Qt动画类 QPropertyAnimation 显示动画 QPropertyAnimation *animation = new QPropertyAnimation(window(), " ...

  9. 在Matlab中如何计算决定系数R^2和相关系数r

    Problem 当你使用 polyfit 函数进行多项式拟合之后,你希望计算决定系数或者相关系数看看拟合效果如何.聪明的你肯定觉得聪明的 Matlab 的 polyfit 函数的返回值中会有 \(R^ ...

  10. fabric peer节点账本验证器相关代码解读

    账本验证器相关代码 fabric/core/commiter/txvalidator/v20/validator.go // Semaphore provides to the validator m ...