python中使用C动态库

本文介绍了如何在Python中利用FastLZ压缩算法。首先,通过VS创建C动态库,修改fastlz源代码以适应动态链接,并确保编译为64位DLL。接着,在Python中使用ctypes导入动态库,定义结构体,进行数据压缩。压缩过程中,利用create_string_buffer构造缓冲区,fastlz_compress函数进行压缩,最后将结果写入目标文件。
摘要由CSDN通过智能技术生成

编写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代码编写的过程遇到的问题

  1. 怎么使用python构造结构体?
  2. python的类型转换
  3. python怎么构造buffer,及怎么取到buffer的参数
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值