引言:
"包装层"(Wrapper Layer)指的是在编程中创建一个中介层,这个层将某些底层实现或复杂功能封装起来,提供一个更简洁或更易用的接口供外部使用。这个中介层不会改变底层功能的实现,但通过简化、整理或者转换数据结构等手段,使得用户能够更方便地使用这些底层功能。
正文:
在 OpenCV 和 opencv-python
的例子中,OpenCV 库的核心是用 C++ 实现的,而 opencv-python
就是一个 Python 封装的包装层。这个包装层将 OpenCV 的 C++ API(应用程序接口)通过 Python 语言重新包装,使得 Python 开发者能够以更简便的方式调用这些底层的 C++ 函数,而不需要了解底层的复杂细节。
具体来说,包装层的作用包括:
简化接口:通过 Python 的语法和标准,提供更易用、Pythonic 的接口。例如,Python 封装可能会减少 C++ 接口中冗长的类型声明,使得使用起来更加直观。
自动化转换:包装层通常会处理不同语言之间的数据结构转换。例如,在 C++ 中,数据可能是以指针和数组的形式传递,而在 Python 中,可能会用更易理解的列表或矩阵表示。包装层负责在 C++ 和 Python 类型之间进行自动转换。
错误处理:包装层可能会捕捉底层函数的错误,转化为 Python 中的异常机制,使得开发者可以用 Python 的方式处理错误。
性能优化:在某些情况下,包装层可能会对底层功能进行某些优化或特定的调整,以适应特定语言的需求。
总之,包装层的目标是让不同语言的开发者能够轻松调用底层实现,而无需关心底层的复杂细节。
开始表演:
下面演示将main.c封装成so文件在python中使用c语言的函数,注意两者速度的区别
为了方便操作我在ubuntu22命令行中演示
命令1: 创建并进入编辑main.c文件
vim main.c
代码1内容: (创建test函数将0到一千万的数加到变量s上面并输出)
#include <stdio.h>
void test() {
long int i;
long long int s = 0;
for (i = 0; i < 10000000; i++){
s += i;
}
printf("%lld\n", s);
}
命令2: 将main.c编译成so文件(共享库)
gcc -shared -fPIC -o libmain.so main.c
这行命令的意思是:
-shared
:生成一个共享库。
-fPIC
:使生成的代码是位置无关的,适合在共享库中使用。
-o libmain.dll
:指定输出的共享库文件名为 libmain.dll
。
main.c
:要编译的源文件。
如果你没有安装gcc执行命令安装:
apt install gcc -y
使用ls命令可以看到目录下多了一个 libmain.so 文件
命令3: 创建并进入编辑app.py文件
vim app.py
#!/usr/bin/python3
#-*-coding:utf-8-*-
import ctypes
import time
lib = ctypes.CDLL("./libmain.so")#引入创建的so文件
t = time.time()#记录开始时间
lib.test()#运行test函数(见上文main.c代码)
print(time.time() - t)#输出"结束时间减去开始时间即test()用时"
t = time.time()#记录开始时间
s = 0
for i in range(10000000):
s += i
print(s)
#这四行相当于main.c中test函数
print(time.time() - t)#输出用时
==准备工作结束,现在开始验证:==
执行chmod +x app.py
命令赋予app.py文件执行权限
./app.py
命令直接运行python代码或python3 app.py
或python app.py
手动调用python解释器运行代码
可以看到结果如图:

python用时大约是c语言的70倍
不过,值得注意的是,本实验中python和c语言的运算时间都是包含了结果输出(printf和print)的时间的,python的print也要比c的printf慢很多,读者可以根据本实验内容修改拓展自行实验
(提示:测量非常薄的A4纸的厚度一般测100张的厚度除以100)
总结:
本文讲解了将c语言代码封装到python调用的方法(见上文代码2 ctypes库相关代码)及其必要性,用c语言编写计算量大的代码可以节约运算时间,在python中使用可以简化代码使开发者能专注于算法而非c语言语法,也避免了大篇幅繁杂的语法给开发者带来"头疼痛苦"
后续补充:
上文在ubuntu服务器(性能较差)上计算,而在本地笔记本电脑测试相同的数据出现了类似的但不尽相同的结果
不过,值得注意的是,Windows中应将so修改为ddl,
命令如下
gcc -shared -FPIC -o libmain.dll main.c
在CPU为Intel i7-12650H的windows11的笔记本电脑上测试, 加到一千万(==单位: 秒(s)==)
c 用时 0.016547441482543945
python用时 0.4777400493621826
加到一亿:
c 用时 0.1582632064819336
python用时 4.1656811237335205
结论:
在cpu性能较为强悍的计算机上运行,python计算速度大幅提升,从2.1419389247894287秒减少到0.4777400493621826秒