C++与Python的互操作(pybind11): 从零开始
来源:互联网 发布:杭州滨江淘宝诈骗视频 编辑:程序博客网 时间:2024/06/16 22:14
所谓互操作,我觉得不妨先简单理解为C++调Python和Python调C++。前者主要是为了灵活和扩展,后者主要是为了效率。实现python和C++互操作的框架不少,包括著名的boost.python。我无意也没有实力评价各种框架的优劣,尝试pybind11也是因为公司的一次技术讨论,权当娱乐。
既然是从零开始,我想第一步就是下载pybind11,然后再能跑起来两个最简单的例子,一个是C++调python,另一个是python调C++.
0. 准备工作:
C++编译器:我是在windows上折腾,选择的就是visual studio 2015。pybind11因为用了C++11的新特性,对编译器还是比较挑剔。官网上说visual studio需要2015及以上。总之越新越好吧。python: 我是从https://www.python.org/下载的最新版本。安装后,确保在安装目录下能看到include目录和libs目录。这两个目录里提供了头文件和链接时需要的库,对使用pybind11来说很重要。include下应该能找到Python.h,libs目录下应该能找到python35.lib (以python 3.5为例)。
git:这个主要是下载源码时用。不装也无所谓,直接从github上下载源码压缩包也行。如果用git的话,在本地空目录下git clone https://github.com/pybind/pybind11.git
cmake: 可以暂时不用
1. 几个重要的路径
pybind11的头文件: pybind11是header only的,所以我们只需要关心其头文件的路径即可。我的是:
E:\PYBIND11\PYBIND11\INCLUDE
└───pybind11
attr.h
buffer_info.h
cast.h
chrono.h
class_support.h
common.h
complex.h
descr.h
eigen.h
embed.h
eval.h
functional.h
numpy.h
operators.h
options.h
pybind11.h
pytypes.h
stl.h
stl_bind.h
typeid.h
python的头文件:我的是在C:\Users\shenfang\AppData\Local\Programs\Python\Python35\include
python的库文件:我的是在C:\Users\shenfang\AppData\Local\Programs\Python\Python35\libs
2. Python调C++的简单例子:
其实就是用C++写pyd,只是pybind11把过程简化了。C++代码源自pybind11的帮助
#include <pybind11/pybind11.h>namespace py = pybind11;int add(int i, int j){ return i + j;}PYBIND11_PLUGIN(example){ py::module m("example", "pybind11 example plugin"); m.def("add", &add, "A function which adds two numbers"); return m.ptr();}
我使用的是vs2015 x64 Native Tools Command Prompt,需要指定前面说的几个重要路径。命令行如下:
cl example.cpp /I "e:\pybind11\pybind11\include" /I "C:\Users\shenfang\AppData\Local\Programs\Python\Python35\include" /LD /Fe:example.pyd /link/LIBPATH:"C:\Users\shenfang\AppData\Local\Programs\Python\Python35\libs\"
执行成功后会生成一个example.pyd,也就是我们用C++写的python模块。
简单的试一下,结果如下:
E:\pybind11\mytest>python
Python 3.5.2 (v3.5.2:4def2a2901a5, Jun 25 2016, 22:18:55) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import example
>>> dir(example)
['__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'add']
>>> example.add(3,4)
7
>>>
3. C++调python的简单例子
我的目的是想从C++程序里调用python脚本里的函数。所以C++的code是这样
#include <pybind11/embed.h>#include <iostream>namespace py = pybind11;int main() { py::scoped_interpreter python; py::module sys = py::module::import("sys"); py::print(sys.attr("path")); py::module t = py::module::import("tttt"); t.attr("add")(1,2); return 0;}
python的脚本是这样:
"""tttt.py located in the working directory"""def add(i, j): print("hello,pybind11") return i + j
名字起成tttt.py主要是避免一些不必要的和已有库重名的麻烦。
还是用命令行编译:
cl invoker.cpp /I "e:\pybind11\pybind11\include" /I "C:\Users\shenfang\AppData\Local\Programs\Python\Python35\include" /Fe:invoker.exe /link /LIBPATH:"C:\Users\shenfang\AppData\Local\Programs\Python\Python35\libs\"
同样重点还是那几个关键的路径,这里不再赘述了。
运行invoker.exe,可以得到
E:\pybind11\mytest>invoker
['C:\\Users\\shenfang\\AppData\\Local\\Programs\\Python\\Python35\\python35.zip', 'C:\\Users\\shenfang\\AppData\\Local\\Programs\\Python\\Python35\\Lib', 'C:\\Users\\shenfang\\AppData\\Local\\Programs\\Python\\Python35\\DLLs', 'E:\\pybind11
\\mytest', 'C:\\Users\\shenfang\\AppData\\Local\\Programs\\Python\\Python35', 'C:\\Users\\shenfang\\AppData\\Local\\Programs\\Python\\Python35\\lib\\site-packages', '.']
hello,pybind11
4. 结论
感觉pybind11对双向互操作的支持还是挺不错的。互操作一个比较重要的方面就是C++ runtime和python runtime的相互访问,包括内存管理,数据类型转换等等。貌似pybind11都有不错的支持。下一步我准备从Python调C++入手,继续深入学习使用pybind11。
- C++与Python的互操作(pybind11): 从零开始
- python 中的赋值操作,与c/c++的对比
- Python从零开始(库的安装与初步使用1)
- Python从零开始(库的安装与初步使用2)
- Python 与 C/C++ 互操作资源汇总
- python与C++的互操作
- OCaml与C的互操作
- Go与C语言的互操作
- Go与C语言的互操作
- Go与C语言的互操作
- Go与C语言的互操作
- Go与C语言的互操作
- Go与C语言的互操作
- 从零开始的Python入门教程1
- 从零开始的Python入门教程2
- 从零开始的Python入门教程0
- Python从零开始系列连载(2)——jupyter的常用操作
- 从零开始的C语言知识点
- websphere服务二:websphere字符集修改
- 使用EXCEL编写生成SQL语句的模板
- window speech实现语音控制
- 昆凌带女儿放风 小周周侧脸曝光肉嘟嘟
- OSI七层协议和TCP/IP四层协议比较
- C++与Python的互操作(pybind11): 从零开始
- 图像拼接之透视矩阵
- 远程服务器与本地文件下载和上载
- 缓存数据redis的配置-
- Jmeter测试报告生成(jmete模板3)
- import zbarlight的过程
- 浅析python 中__name__ = '__main__' 的作用
- 论微信会员的重要性
- PCB放置总线