python移植c动态库进行fastlz压缩
编写python脚本进行fastlz压缩
本文讲解的是如何在python下利用fastlz压缩算法
第一步:编写fastlz的C动态库
1、从网上下载fastlz代码[添加链接描述](https://github.com/ariya/FastLZ),下载fastlz.c和fastlz.h,**再找一个配置文件rt_config.h**,没有配置文件编译的代码,在vs编译后测试数据对不上。
打开vs,建立dll工程
2、add->existing item…将上述链接下载的文件fastlz.h,fastlz.c,rt-config.h也可以直接将下载的文件添加到工程里,并放在同一目录下。
3、在fastlz.h 文件中添加
#pragma once
#define DLL_EXPORT extern “C” __declspec(dllexport)
在需要进行动态链接的函数前加上#define DLL_EXPORT int __stdcall
#pragma once
#define DLL_EXPORT extern "C" __declspec(dllexport)
DLL_EXPORT int __stdcall fastlz_compress(const void* input, int length, void* output);
DLL_EXPORT int __stdcall fastlz_decompress(const void* input, int length, void* output, int maxout);
DLL_EXPORT int __stdcall fastlz_compress_level(int level, const void* input, int length, void* output);
保持fastlz.h和fastlz.c的声明一致,包括后面的实现函数也要加上int __stdcall
int __stdcall fastlz_compress(const void* input, int length, void* output)
{
/* for short block, choose fastlz1 */
if (length < 65536)
return fastlz1_compress(input, length, output);
/* else... */
return fastlz2_compress(input, length, output);
}
int __stdcall fastlz_decompress(const void* input, int length, void* output, int maxout)
{
/* magic identifier for compression level */
int level = ((*(const flzuint8*)input) >> 5) + 1;
if (level == 1)
return fastlz1_decompress(input, length, output, maxout);
if (level == 2)
return fastlz2_decompress(input, length, output, maxout);
/* unknown level, trigger error */
return 0;
}
int __stdcall fastlz_compress_level(int level, const void* input, int length, void* output)
{
if (level == 1)
return fastlz1_compress(input, length, output);
if (level == 2)
return fastlz2_compress(input, length, output);
return 0;
}
在fastlz.c文件中添加
DLL_EXPORT int __stdcall fastlz_compress(const void* input, int length, void* output);
DLL_EXPORT int __stdcall fastlz_compress_level(int level, const void* input, int length, void* output);
DLL_EXPORT int __stdcall fastlz_decompress(const void* input, int length, void* output, int maxout);
头文件记得加#include<windows.h>
编译不过把.c改为.cpp,对应的在fastlz.c文件里找到“fastlz.c”,改为“fastlz.cpp”
编译,编译最好需要用到64位的,在设置中将.exe改为.dll。我的电脑装的64位python,要支持64位fastlz动态库链接的。
第二步:python导入动态库函数
找到上述dll文件的路径,直接贴代码
#!/usr/bin/python
# -*- coding:utf-8 -*-
import os
import sys
from ctypes import *
import re
from binascii import a2b_hex
dll = CDLL(".\compress.dll")
class BInfo(Structure):
_fields_ = [("m", c_int32),
("s", c_int32),
("length",c_int32),
("compressed", c_int32),
("res", c_int32)]
def compressed_data(dest_file, src_file):
if not os.path.exists(src_file) :
print('open %s err', src_file)
return
with open(src_file, 'rb') as fr:
while True:
file_header = BInfo()
file_header.m = 0x7E7E7E7E
file_header.s = 22
file_header.length = 1024 * 12 # 每次压缩的size
file_header.compressed = 1
file_header.res = 0x01
data = fr.read(file_header.length)
flag = False
if (len(data) < file_header.length):
flag = True
out_value = create_string_buffer(13*1024+400, '\0')
in_date = c_char_p()
in_date = data
ret = dll.fastlz_compress(in_date, file_header.length, out_value)
s = string_at(out_value, ret)
# print(type(s))
with open(dest_file, 'ab+') as n:
file_header.length = ret
n.write(file_header)
n.write(s)
if flag:
break
fr.close()
def main():
src_file = "D:\\1.log"
dest_file = "D:\\t.txt"
compressed_data(dest_file, src_file)
if __name__ == '__main__':
main()
要用到from ctypes import *,构造结构体,导入dll动态库文件,及构造buffer。
业务需要将需要压缩的文件进行先封装,后解压,所以压缩之前进行结构体构造一个头。
dll.fastlz_compress(in_date, file_header.length, out_value),第一个参数是输入参数,第二个参数是压缩的大小,第三个参数是压缩后的buffer,但是怎么构造第三个参数。需要用到creat_string_buffer进行构造,然后将输入参数进行强制类型转换,使输入类型和输出类型一致。得到压缩后的数据需要用到string_at函数。fastlz_compress(in_date, file_header.length, out_value)的返回值是压缩后的返回值。压缩就完成了。
python代码编写的过程遇到的问题
- 怎么使用python构造结构体?
- python的类型转换
- python怎么构造buffer,及怎么取到buffer的参数