python虽然拥有强大的生态库,但是其解释型编程风格,使得代码运行效率相对于C语言低很多;在一些对运行性能要求高的工程,其弊端就表现的很明显。这里介绍一种用ctypes标准库实现代码运行速度的方法。下面就以计算CRC32为例。
1、编写crc32函数
用C语言或C++或C#编写crc32程序,假设编写的函数为
uint32_t CRC32_Calc(uint8_t *pDataAddr, uint32_t length)
其中*pDataAddr表示要计算crc32的数据地址,length表示要计算crc32的数据长度,函数返回32bits的crc值;具体的crc32实现代码,网上很多;
2、生成DLL文件
用相关手段,将上述的代码(包括.c和.h文件)生成crc32_lib.so或者crc32_lib.dll等库文件;
3、python通过ctypes调用库文件
import os, ctypes
path_python = os.path.split(os.path.realpath(__file__))[0]
crc32_lib = ctypes.cdll.LoadLibbrary(os.path.join(path_python, "\\crc32_lib.dll"))
CRC32_CALC = crc32_lib.CRC32_Calc
CRC32_CALC.argtypes = [ctypes.c_char_p, ctypes.c_uint32]
CRC32_CALC.restype = ctypes.c_uint32
代码介绍:
1)path_python = os.path.split(os.path.realpath(__file__))[0],表示获取当前python脚本的文件路径,用于获取dll文件的路径;
2)crc32_lib = ctypes.cdll.LoadLibbrary(os.path.join(path_python, "\\crc32_lib.dll")),先用os.path.join获取dll完整的路径,再用ctypes.cdll.LoadLibbrary导入库文件;
3)CRC32_CALC = crc32_lib.CRC32_Calc,定义计算crc32函数名;
4)最后2行代码生命函数的输入形参数据类型和函数返回数据类型;
4、封装成python函数
def crc32_update(data, size):
if type(data) == bytearray:
data = bytes(data)
return CRC32_CALC(data, size)
5、代码调用
# 定义生成16进制的数组
def byteArray_gen(byte_len, hex_val) -> bytearray():
a_byte = hex_val.to_bytes(length=1, byteorder='little')
null_data = bytearray(byte_len)
i = 0
while i < byte_len:
null_data[i] = a_byte[0]
i += 1
return null_data
# 计算crc32
magic_size = 256
magic_array = byteArray_gen(self.magic_size, 0xFF)
hw_crc = crc32_update(magic_array, magic_size)
按照上述方式,python可通过调用C语言或C++语言或C#语言编写的crc32函数生成的库文件,快速计算数据的crc32值;特别是对于以MB或GB为单位的数据,计算效率显而易见。
总结
上述简单列举以计算crc32的值为例,介绍python如何通过调用C语言等生成的库文件,加快程序的运行时间,特别是针对一些大数据或复杂算法的计算,效果明显。