gpt4 book ai didi

python - pybind11:如何将c++和python代码打包成一个包?

转载 作者:太空狗 更新时间:2023-10-29 21:00:18 37 4
gpt4 key购买 nike

我正在尝试使用 CMake 和 pybind 11 将现有的 Python 代码和新的 C++ 11 代码打包在一起。我想我缺少一些简单的东西可以添加到 CMake 脚本中,但无法在任何地方找到它:pybind11 示例只有C++ 代码,没有 Python,其他在线资源相当复杂而且不是最新的——所以我只是想不出如何将两种语言的函数打包在一起,并通过 Python 的 import my_package< 使它们可用 在线...例如,我从 pybind11 和 added a mult function 克隆了 cmake_example进入 cmake_example/mult.py

def mult(a, b):
return a * b

我如何让它与 addsubtract 一起可见以通过下面的测试?

import cmake_example as m

assert m.__version__ == '0.0.1'
assert m.add(1, 2) == 3
assert m.subtract(1, 2) == -1
assert m.mult(2, 2) == 4

目前,这个测试fails..

谢谢!

最佳答案

最简单的解决方案与 pybind11 本身无关。当作者想要在同一个包中组合纯 Python 和 C/Cython/其他 native 扩展时,通常会做以下事情。

您创建了两个模块。

  1. mymodule 是一个公共(public)接口(interface),一个纯Python模块
  2. _mymodule 是私有(private)实现,编译模块

然后在 mymodule 中,您从 _mymoudle 导入必要的符号(如有必要,回退到纯 Python 版本)。

这是来自 yarl 的示例包裹:

  1. quoting.py

    try:
    from ._quoting import _quote, _unquote
    quote = _quote
    unquote = _unquote
    except ImportError: # pragma: no cover
    quote = _py_quote
    unquote = _py_unquote
  2. _quoting.pyx

更新

下面是脚本。为了可重复性,我正在根据原始 cmake_example 进行操作.

git clone --recursive https://github.com/pybind/cmake_example.git
# at the time of writing https://github.com/pybind/cmake_example/commit/8818f493
cd cmake_example

现在创建纯 Python 模块(在 cmake_example/cmake_example 内)。

cmake_example/__init__.py

"""Root module of your package"""

cmake_example/math.py

def mul(a, b):
"""Pure Python-only function"""
return a * b


def add(a, b):
"""Fallback function"""
return a + b

try:
from ._math import add
except ImportError:
pass

现在让我们修改现有文件,将 cmake_example 模块转换为 cmake_example._math

src/main.cpp(为简洁起见删除了subtract)

#include <pybind11/pybind11.h>

int add(int i, int j) {
return i + j;
}

namespace py = pybind11;

PYBIND11_MODULE(_math, m) {
m.doc() = R"pbdoc(
Pybind11 example plugin
-----------------------

.. currentmodule:: _math

.. autosummary::
:toctree: _generate

add
)pbdoc";

m.def("add", &add, R"pbdoc(
Add two numbers

Some other explanation about the add function.
)pbdoc");

#ifdef VERSION_INFO
m.attr("__version__") = VERSION_INFO;
#else
m.attr("__version__") = "dev";
#endif
}

CMakeLists.txt

cmake_minimum_required(VERSION 2.8.12)
project(cmake_example)

add_subdirectory(pybind11)
pybind11_add_module(_math src/main.cpp)

setup.py

# the above stays intact

from subprocess import CalledProcessError

kwargs = dict(
name='cmake_example',
version='0.0.1',
author='Dean Moldovan',
author_email='dean0x7d@gmail.com',
description='A test project using pybind11 and CMake',
long_description='',
ext_modules=[CMakeExtension('cmake_example._math')],
cmdclass=dict(build_ext=CMakeBuild),
zip_safe=False,
packages=['cmake_example']
)

# likely there are more exceptions, take a look at yarl example
try:
setup(**kwargs)
except CalledProcessError:
print('Failed to build extension!')
del kwargs['ext_modules']
setup(**kwargs)

现在我们可以构建它了。

python setup.py bdist_wheel

在我的例子中,它生成 dist/cmake_example-0.0.1-cp27-cp27mu-linux_x86_64.whl(如果 C++ 编译失败,它是 cmake_example-0.0.1-py2-none-any .whl).这是它的内容(unzip -l ...):

Archive:  cmake_example-0.0.1-cp27-cp27mu-linux_x86_64.whl
Length Date Time Name
--------- ---------- ----- ----
0 2017-12-05 21:42 cmake_example/__init__.py
81088 2017-12-05 21:43 cmake_example/_math.so
223 2017-12-05 21:46 cmake_example/math.py
10 2017-12-05 21:48 cmake_example-0.0.1.dist-info/DESCRIPTION.rst
343 2017-12-05 21:48 cmake_example-0.0.1.dist-info/metadata.json
14 2017-12-05 21:48 cmake_example-0.0.1.dist-info/top_level.txt
105 2017-12-05 21:48 cmake_example-0.0.1.dist-info/WHEEL
226 2017-12-05 21:48 cmake_example-0.0.1.dist-info/METADATA
766 2017-12-05 21:48 cmake_example-0.0.1.dist-info/RECORD
--------- -------
82775 9 files

关于python - pybind11:如何将c++和python代码打包成一个包?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47599162/

37 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com