目录

  • 1 为什么需要多语言联合编程?
  • 2 Python调用C++的主要方式
    • 2.1 SWIG
    • 2.2 Boost::Python
    • 2.3 ctypes
  • 3 Boost::Python安装
  • 4 测试实例:python继承C++接口
  • 5 常见问题
  • 6 参考文档

1 为什么需要多语言联合编程?


在大型工程项目中,经常会遇到多语言联合编程的情况,举个例子:

在一个远端控制系统中,前端Web使用html+css+js;后端采用python-flask作为服务端,底层控制采用C/C++

这是因为不同编程语言有各自的适用场景和语法特性,联合编程可使得各种语言发挥自己的特长。本文主要比较Python和C++,先列举各自特点如下:

对比项目 C++ Python
本质 编译型语言 解释型语言
编程难度 难以掌握 易于上手
语法特性 静态 动态
垃圾回收 不支持 支持
安装 难(需要专门打包)
数据类型 在编译时由关键字确定 在运行时由数值确定
函数 输入参数和返回值类型有限制 输入参数和返回值类型无限制
执行速度
性能

国外有一个测试指出在相同复杂度算法中,C++约比Python快50倍左右。因此Python不适合用于底层算法的开发,应用在上层应用中作粘合剂或进行智能领域的研究比较占优;C/C++则适合用于底层控制算法编程。下面主要介绍Python调用C++,让C++和Python形成优势互补。

2 Python调用C++的主要方式

主要介绍三种C++/Python联合编程的方式:

2.1 SWIG

  • 支持Python、Java、Ruby等语言调用C接口
  • 文档全面,易于学习
  • 绑定性能欠佳, 不支持属性和内部类封装
  • C++支持不好

2.2 Boost::Python

  • 支持Python2与Python3调用C++接口
  • 大量使用C++ templates,明显提高编译时间
  • 非常可靠、稳定、经过充分测试
  • 语法较复杂,且文档不详细

本文采用Boost::Python进行C++/Python联合编程。

2.3 ctypes

  • 灵活,完全兼容C语言
  • 使用较繁琐且不支持C++特性

3 Boost::Python安装

打开参考中的官方下载地址,根据不同的操作系统平台下载boost,UNIX和Windows的安装流程差不多,下面以Windows系统为例说明安装过程。


按下面步骤安装编译Boost::Python

  • 下载最新的boost_1_79_0.zip并解压到本地目录
  • 运行bootstrap.bat在目录下产生b2.exe可执行文件
  • 进入根目录新建user-config.jam用户配置文件,存放本地C++/Python信息
    using msvc : 14.2;
    using python : 3.7.5: "D:/Anaconda/Anaconda/envs/test/python.exe": "D:/Anaconda/Anaconda/envs/test/include": "D:/Anaconda/Anaconda/envs/test/libs";
    

    其中msvcVisual Studio对应的msvc toolset版本,具体对应关系如下:
    python则定义了本地使用的python解释器相关路径和库

  • 命令行执行自动化安装:
    b2 --with-python install --prefix="D:/3rdLib/boost/boost_1_79_0/bin/lib64-msvc-14.2" toolset=msvc-14.2 link=static address-model=64 --user-config=user-config.jam
    

    其中一些关键参数解释如下:

    • with- | without-:前者后接要编译的Boost库名,如本文中只需编译Boost下的Python库;后者即为编译除之外的所有库,缺省则为全部编译
    • stage | install:前者表示只生成库文件(.dll与.lib),后者会额外生成include目录包含库文件对应的头文件,推荐使用stage,因为安装完成后根目录下的boost与include目录文件完全一致,可直接作为头文件使用,节省编译时间
    • stagedir | prefix:表示编译生成文件的路径,前者对应stage安装模式,后者对应install安装模式。建议在根目录下新建bin目录管理生成的库文件
      # VS2019编译的x86库文件
      bin/lib32-msvc-14.2
      # VS2019编译的x64库文件
      bin/lib64-msvc-14.2
      
    • toolset:表示编译器,可选gccmsvc-14.2(VS2019)等
    • link:指定生成动态链接库shared还是静态链接库static,推荐使用静态库方式编译,这样发布程序时无需连带发布Boost的.dll文件,本文采用静态编译。

    • address-model:指定编译版本,可选32 | 64,该参数必须和本地安装的Python位数相对应,否则会编译出错
    • user-config:使用的本地用户配置文件路径

补充一下编译库文件的命名格式:

libboost_python37-vc142-mt-gd-x64-1_79
| ||   | |      | |   | || ||| | | |  |-  ---   ------   ---  -- - -  -   --1   2       3      4    5 6 7  8    9
  1. 静态库以lib开头,动态库没有lib前缀
  2. boost::python库名称和版本
  3. 编译器名称及版本
  4. mt代表threading=multi,没有则代表threading=single
  5. s代表runtime-link=static,没有则代表runtime-link=shared
  6. gd代表debug版本,没有则代表release版本
  7. x32代表32 位程序,x64代表64 位
  8. Boost库版本,1_79代表Boost 1.79版本。

4 测试实例:python继承C++接口

新建工程文件夹,包含三个文件helloworld.cpphelloworld.pyCMakeLists.txt

helloworld.cpp中编写:

// 因为采用静态编译boost库,因此必须定义此宏,否则编译出错
#define BOOST_PYTHON_STATIC_LIB#include<boost/python.hpp>
#include<boost/python/wrapper.hpp>
#include<string>
#include<iostream>using namespace boost::python;
using namespace std;struct Base
{virtual ~Base() {}virtual int f() { return 0; };
};struct BaseWrap : Base, wrapper<Base>
{int f(){if (override f = this->get_override("f"))return f(); //如果函数进行重载了,则返回重载return Base::f(); //否则返回基类}int default_f() { return this->Base::f(); }
};BOOST_PYTHON_MODULE(hello)
{class_<BaseWrap, boost::noncopyable>("Base").def("f", &Base::f, &BaseWrap::default_f);
}

CMakeLists.txt中编写编译规则

project(Boost_Test)
cmake_minimum_required(VERSION 2.8.3)if(MSVC)# set(Boost_USE_STATIC_LIBS ON)set(Boost_DIR D:/3rdLib/boost/boost_1_79_0/stage/lib/cmake/Boost-1.79.0)set(PYTHON_INCLUDE_DIRS D:/Anaconda/Anaconda/envs/test/include)set(PYTHON_LIBRARIES D:/Anaconda/Anaconda/envs/test/libs/python37.lib)find_package(Boost 1.79.0 CONFIG COMPONENTS python REQUIRED)include_directories(${Boost_INCLUDE_DIR} ${PYTHON_INCLUDE_DIRS})
endif(MSVC)set(MODULE_NAME hello)
add_library(${MODULE_NAME} SHAREDhelloword.cpp)if (UNIX)set_target_properties(${MODULE_NAME}PROPERTIESPREFIX "")
elseif (WIN32)set_target_properties(${MODULE_NAME}PROPERTIESSUFFIX ".pyd")
endif()target_link_libraries(${MODULE_NAME}${Boost_LIBRARIES}${PYTHON_LIBRARIES}
)

在工程目录下执行以下命令行:

mkdir build
cd build
cmake ..
make

即可编译出hello.pyd二进制文件,将该文件置于工程目录下(与helloworld.py在同一个目录),在helloworld.py中导入接口,测试多态:

import hello
base = hello.Base()
# 定义派生类,继承C++类
class Derived(hello.Base):def f(self):return 42derived = Derived()
print( base.f())
print (derived.f())

输出以下内容,证明实验成功

>>> 0
>>> 42

5 常见问题

  1. #include <boost\python.hpp>无法打开源文件'pyconfig.h'

    解决方案:首先确保当前虚拟环境下有pyconfig,否则需要pip install。接着对于vscode,在c_cpp_properties.json中添加python的include目录

  2. error LNK2019: 无法解析的外部符号 "__declspec(dllimport) class boost::python::xxx

    解决方案:库链接出错,对于静态编译的Boost::python库需要在C++文件中声明静态编译宏

    #define BOOST_PYTHON_STATIC_LIB
    

6 参考文档

  • Boost::Python官方文档
  • Boost::Python下载官网

C++比Python快50倍?如何让C++和Python优势互补?(Boost::Python)相关推荐

  1. 震惊,使用imba.io框架,得到比 vue 快50倍的性能基准

    上图表示了vue, react 以及 imba 在 todo 这个项目中拥有60个 todoItem 不同进行 crud 操作的表现.可以看到 imba 达到了每秒操作5w次以上.如果你也想试一试该测 ...

  2. 编译器大神 Chris Lattner 官宣新编程语言:Mojo,比 Python 快 35000 倍!

    整理 | 王子彧    责编 | 张红月 出品 | CSDN(ID:CSDNnews) 说起 Chris Lattner,大家一定不陌生.这位编译器大神,曾经领导了众多大型技术项目.他不仅是 LLVM ...

  3. 论文解读:FastSAM | Fast Segment Anything | 基于yolov8-seg实现 比SAM快50倍

    发表时间:2023.06.21 论文地址:http://export.arxiv.org/pdf/2306.12156 项目地址:https://github.com/CASIA-IVA-Lab/Fa ...

  4. 新AI编程语言Mojo,比Python快35000倍

    随着近期AI的火热以及AI在各个行业的应用,Python的热度有望进一步提升. 除了 Python,Julia 也是很多开发者选择的编程语言."Julia 是否会取代 Python" ...

  5. 转载:比Python快100倍,利用spaCy和Cython实现高速NLP项目

    Cython 是一个工具包,可以使你在 Python 中编译 C 语言,这就是为什么 numpy 和 pandas 很快的原因,Cython 就是 Python 的超集.在本文中,作者将为我们介绍他的 ...

  6. 真香!spaCy+Cython比Python快100倍.....

    选自Medium      作者:Thomas Wolf 编译:机器之心(almosthuman2014) Cython 是一个工具包,可以使你在 Python 中编译 C 语言,这就是为什么 num ...

  7. python lua 性能比较 内存_Lua 的速度为什么比 Python 快?

    最近研究了下Python的代码,有了一些新的发现.大量的内置字符串常量没有做Intern优化,在python源码中搜索形如"__dict__"之类的常量是这么用的: PyObjec ...

  8. Batoo JPA –比领先的JPA提供商快15倍

    介绍 我早在2000年代就喜欢JPA 1.0. 我甚至在稳定版本发布之前就将其与EJB 3.0一起使用. 我非常喜欢它,因此我为JBoss 3.x实现贡献了一些零碎的部分. 那时我们公司规模还很小. ...

  9. 掌握这个小技巧,让你的 C++ 编译速度提升 50 倍!

    随着 C++ 项目的持续扩大,编译效率越来越是一个问题了.想一想你每天花在这上面的时间,再乘以团队成员的个数,是不是成本很高? 那有没有什么办法,在不需要修改源码,也不更换硬件的情况下提升效率呢?一起 ...

最新文章

  1. 方法 retrun 异步的值,创建一个变量直接等于一个异步方法返回的值
  2. Failed to initiate service connection to simulator
  3. [Python人工智能] 三.theano实现分类神经网络及机器学习基础
  4. 《leetcode》single-number-ii
  5. Android RaingBar评分条的使用
  6. 在DELL服务器上升级ESXI 5.5
  7. NUnit单元测试笔记
  8. Android studio SweetAlert for Android
  9. 【Linux-shell】shell脚本基础语法练习
  10. ARC094F Normalization
  11. CStdioFile UNICODE编译 读取中文汉字乱码 .
  12. DotNetBar for WinForms使用教程:图表控件用户指南(一)
  13. 上海交通大学2004年数学分析考研试题
  14. 蚂蚁迷宫—有限状态机设计(ANT MAZE)
  15. [深度学习]基于TensorFlow的基本深度学习模型
  16. 微信网页小游戏网站源码带后台+可后台添加游戏+推荐到微信
  17. 对于多目标跟踪论模型CTracker的解析
  18. LeetCode 491 递增子序列
  19. 新版标准日本语初级_第三十七课
  20. java线程状态研究

热门文章

  1. 【BMT】MTK电池充电问题
  2. 新浪微博分享 WBWebpageObject 无法显示图片问题
  3. 数据挖掘易犯的11大错误与数据分析技能
  4. (转 蜡人张)RDL(C) Report Design Step by Step 1: DrillThrough Report
  5. 大数据画像:85%在线学习者“知道但不了解人工智能”,更多人对AI普及应用存顾虑
  6. WPF TabControl Styles
  7. java tabcontrol_TabControl的用法步骤详解
  8. 脱口而出100句经典英语
  9. 要么解决问题,要么把问题升华
  10. html5 仿手机聊天,HTML5仿手机微信聊天界面