• python调用c++代码《从C++共享链接库编译到python调用指南》



    该系列文章:
    (一)python调用c++代码《从C++共享链接库编译到python调用指南》
    (二)ndarray(Python)与Mat(C++)数据的传输
    (三)C++结构体与python的传输

    1、前言

    对于某些时候,我们希望能在python中调用c++代码,或许是为了追求速度,或许是为了调用现成的c++代码。

    网上也有很多相关方面的教程,但他们的c++代码仅仅为一个函数或者一个类,情况比较简单。

    我找到了一个不错的c++项目,但是我没有能力用python重写,所以我将c++中的main函数写成一个类,并希望导出为共享链接库(.so文件),在python中调用。

    我的难点在于我希望导出的这个类,使用了第三方库OpenCV,以及这个类还使用了其他的类,情况一下就复杂了。

    实际上这也符合真实情况,如果我只想调用c++实现的一个函数或者单纯的类,为什么不直接用python写呢?实际情况才是如同上面我讲的那样,情况复杂。

    2、介绍

    {这里给出一张图}

    注意:opencv.cpp是作者自己写的一个类(类似于RPPG.cpp),而OpenCV是第三方库,不要混淆了

    三个类都使用了OpenCV第三方库,同时HB使用了RPPG类和opencv类,RPPG使用了opencv类,而我要导出HB类,使其可以在python中调用,依赖关系复杂了。

    所以,我们使用cmake来帮助编译so文件

    3、环境安装

    首先我们在Ubuntu20.04中编译( (一)Ubuntu安装详细教程(从镜像制作到NVIDIA驱动安装全流程)——超详细的图文教程

    3.1 gcc安装

    先查看是否安装gcc:
    在这里插入图片描述

    如果没有安装:

    # 在终端中,依次执行
    sudo apt-get update
    sudo apt-get install build-essential gdb
    
    • 1
    • 2
    • 3

    3.2 cmake安装

    先查看是否安装cmake:
    在这里插入图片描述
    如果没有安装,请参阅 Kitware APT存储库中适用于您的平台的说明

    4、编译

    # .hpp 头文件,用于申明
    # .cpp 实现头文件中申明的函数或类
    -project
    --HB.cpp
    --HB.hpp
    --RPPG.cpp
    --RPPG.hpp
    --opencv.cpp
    --opencv.hpp
    --......
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    首先我的结构目录如上,在节2中给出了之间的关系,我们的目的是导出HB.cpp为so文件

    4.1 CMakeLists.txt

    我们知道编译时会指定许多参数,CMakeLists.txt就是告诉cmake我们编译时的参数设定。

    我们在project文件夹下新建CMakeLists.txt文件,内容如下:

    cmake_minimum_required(VERSION 3.0.0)	# 最小版本
    project(hbp VERSION 0.1.0)  # 项目名称
    
    set(CMAKE_CXX_FLAGS "-std=c++11")   # 添加c++11标准
    
    find_package(OpenCV REQUIRED) # 添加OpenCV库
    include_directories(${OpenCV_INCLUDE_DIRS})
    
    add_library(opencv SHARED opencv.cpp)	# 把opencv.cpp导出为链接库,SHARED指定为共享链接库
    target_link_libraries(opencv ${OpenCV_LIBS})	#因为opencv.cpp使用了OpenCV,所以将OpenCV链接到opencv中,相当于告诉opencv去哪儿找OpenCV
    
    add_library(RPPG SHARED RPPG.cpp)
    target_link_libraries(RPPG ${OpenCV_LIBS})	# RPPG也使用了OpenCV库,也要链接
    
    add_library(HB SHARED HB.cpp)
    target_link_libraries(HB ${OpenCV_LIBS})	# HB也使用了OpenCV库
    
    target_link_libraries(RPPG opencv)	# RPPG还使用了opencv类
    target_link_libraries(HB RPPG) # HB使用了RPPG(同时RPPG链接了opencv,相当于HB间接链接了opencv)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    可以看出:

    1. 第三方库是通过target_link_libraries直接链接
    2. 自定义类要先通过add_library定义为共享链接库,后面再通过target_link_libraries链接

    4.2 编译

    在project中新建build文件夹:

    -project
    --build/
    --CMakeLists.txt
    --HB.cpp
    --HB.hpp
    --RPPG.cpp
    --RPPG.hpp
    --opencv.cpp
    --opencv.hpp
    --......
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    再终端中进入build/,执行命令:$ cmake ..
    在这里插入图片描述
    再执行:$ make
    在这里插入图片描述
    然后就得到了想要的HB.so文件:
    在这里插入图片描述
    (会自动加lib-前缀,所以libHB.so就是编译好的文件)

    4.3 检查

    编译时成功不代表真的成功,我们需要检查一下。
    执行命令$ ldd -r libHB.so
    在这里插入图片描述
    在这里插入图片描述
    这代表成功了。

    失败了是什么样的?

    如果我直接按照python调用C++中的函数【最简明教程】编译so文件:$ g++ -o HB.so -shared -fPIC HB.cpp得到HB.so文件,现在检查一下这个有没有问题$ ldd -r HB.so
    在这里插入图片描述
    可以看到出现大量的"undefined symbol:“,从后面的_ZN2cv8fastFreeEPv可以看出是缺少OpenCV的链接,导致使用的OpenCV函数为"undefined symbol:”,同理还可以看到“RPPG”等。

    如果你想查看是具体什么函数,你可以执行命令:
    c++filt _ZN2cv8fastFreeEPv就可以查看到后面的一串到底代表哪个函数
    在这里插入图片描述

    5、python中调用

    直接给代码:

    import ctypes
    dll=ctypes.cdll.LoadLibrary
    
    # 加载so链接库
    lib=dll("./libHB.so")
    
    # 这里是调用HB类中的load函数
    lib.load()
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    可以看到C++中HB.load()函数执行成功会打印字符串:
    在这里插入图片描述
    验证一下,运行python代码,ok!
    在这里插入图片描述

  • 相关阅读:
    十分钟搞懂机器学习中的余弦相似性
    深入浅出Spring(28)
    实在智能AI+RPA:引领数字化转型的超自动化智能体
    第九章 将对象映射到 XML - 控制集合属性的映射形式
    字符串数字出现的新功能
    JHipster介绍:一个适用于Java和JavaScript的全栈框架
    Diffle-Hellman Key Exchange密钥交换
    《向量数据库指南》——Milvus Cloud和Elastic Cloud 特性对比
    数学建模学习(73):用Python敏感性分析,如此轻松简单
    初见物理引擎库Cannon.js(2)
  • 原文地址:https://blog.csdn.net/qq_40243750/article/details/125484311