sen*_*inp 8 c++ python cmake pybind11
我正在尝试使用CMake和pybind 11将现有的Python代码和新的C++ 11代码打包在一起.我认为我遗漏了一些简单的东西添加到CMake脚本中,但无法在任何地方找到它:pybind11示例只有C++代码和没有Python,其他在线资源相当复杂而且不是最新的 - 所以我无法弄清楚如何将两种语言的函数打包在一起并通过Python提供它们import my_package......作为一个例子,我已经克隆了pybind11的cmake_example并增加了MULT功能成cmake_example/mult.py
def mult(a, b):
return a * b
Run Code Online (Sandbox Code Playgroud)
我如何将其与下面的测试一起显示add并subtract通过测试?
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
Run Code Online (Sandbox Code Playgroud)
目前,这个测试失败了..
谢谢!
最简单的解决方案与pybind11无关。以下是作者在将纯Python和C / Cython /其他本机扩展合并到同一软件包中时通常要做的事情。
您创建两个模块。
mymodule 是一个公共接口,一个纯Python模块_mymodule 是私有实现,已编译的模块然后,mymodule从中导入必要的符号_mymoudle(并在必要时回退到纯Python版本)。
这是来自yarl包的示例:
try:
from ._quoting import _quote, _unquote
quote = _quote
unquote = _unquote
except ImportError: # pragma: no cover
quote = _py_quote
unquote = _py_unquote
Run Code Online (Sandbox Code Playgroud)下面是脚本。为了重现性,我针对原始的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
Run Code Online (Sandbox Code Playgroud)
现在创建纯Python模块(在中cmake_example/cmake_example)。
cmake_example/__init__.py
"""Root module of your package"""
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
现在,让我们修改现有文件以将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
}
Run Code Online (Sandbox Code Playgroud)
CMakeLists.txt
cmake_minimum_required(VERSION 2.8.12)
project(cmake_example)
add_subdirectory(pybind11)
pybind11_add_module(_math src/main.cpp)
Run Code Online (Sandbox Code Playgroud)
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)
Run Code Online (Sandbox Code Playgroud)
现在我们可以构建它。
python setup.py bdist_wheel
Run Code Online (Sandbox Code Playgroud)
就我而言,它会产生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
Run Code Online (Sandbox Code Playgroud)