分享好友 站长动态首页 网站导航

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

2022-04-27 08:05 · 头闻号编程技术

目录

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

2.2 Boost::Python

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

2.3 ctypes

3 Boost::Python安装

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

在这里插入图片描述
按下面步骤安装编译Boost::Python

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

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} SHARED    helloword.cpp	)if (UNIX)  set_target_properties(${MODULE_NAME}    PROPERTIES    PREFIX ""  )elseif (WIN32)  set_target_properties(${MODULE_NAME}  PROPERTIES  SUFFIX ".pyd"  )endif()target_link_libraries(${MODULE_NAME}  ${Boost_LIBRARIES}  ${PYTHON_LIBRARIES})

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

mkdir buildcd buildcmake ..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 <boostpython.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 参考文档


🔥 更多精彩专栏

🏠 欢迎加入社区和更多志同道合的朋友交流:AI 技术社

👇配套代码 · 优质体验 · 系统知识 请关注👇

免责声明:本平台仅供信息发布交流之途,请谨慎判断信息真伪。如遇虚假诈骗信息,请立即举报

举报
反对 0
打赏 0
更多相关文章

评论

0

收藏

点赞