ctypes.string_at 函数报错 SystemError Negative size

创建日期: 2023-07-03 15:53 | 作者: 风波 | 浏览次数: 14 | 分类: Python

报错信息:ctypes.string_at SystemError: Negative size

原因

调用函数 ctypes.string_at(ptr, size) 的时候,size 参数或小于0,或者太大,大于了 int 类型的表示范围,结果导致了函数报错。

修正

但是调用 so 文件的 C API 返回的数据就是这么大,总不能只读取一半数据吧。 所以,解决方案就是增加一个函数,返回 ptr 参数偏移后的指针。这样就可以分段的读取原来 ptr 指向的内存空间了。

import io
import ctypes
from loguru import logger
#import hashlib

# 加载动态库
lib = ctypes.CDLL("./libmodelpre.so")

lib.unpack.argtypes = [ctypes.c_char_p, ctypes.c_char_p, ctypes.c_char_p, ctypes.c_char_p, ctypes.POINTER(ctypes.c_ulong)]
lib.unpack.restype = ctypes.c_void_p

lib.free_memory.argtypes = [ctypes.c_void_p]
lib.free_memory.restype = None

lib.range.argtypes = [ctypes.c_void_p, ctypes.c_ulong]
lib.range.restype = ctypes.c_void_p

def unpack(self, sslpath, filepath, iv="", md5=""):
    # 将文件路径转换为 C 字符串
    c_file_path = ctypes.c_char_p(filepath.encode())
    c_ssl_path = ctypes.c_char_p(sslpath.encode())
    c_iv = ctypes.c_char_p(iv.encode())
    c_md5 = ctypes.c_char_p(md5.encode())
    # 定义整数变量,用于接收文件长度
    file_length = ctypes.c_ulong()

    # 调用 C API 函数,并获取返回的文件内容指针
    # TODO 在 C API 里面判断 c_iv/c_md5 是不是 empty ?
    file_content_ptr = lib.unpack(c_ssl_path, c_file_path, c_iv, c_md5, ctypes.byref(file_length))

    logger.info("file length: {}".format(file_length.value))
    if file_length.value <= 0:
        lib.free(file_content_ptr)
        return None

    bio = io.BytesIO()
    # 将文件内容指针转换为 Python 字符串
    logger.info("get content ...")
    step = 2 ** 30
    for i in range(0, file_length.value, step):
        size = min(step, file_length.value - i)
        logger.info("i + step = {}".format(i + size))
        ptr = lib.range(file_content_ptr, i)
        file_content = ctypes.string_at(ptr, size)
        bio.write(file_content)
    #file_content = ctypes.string_at(file_content_ptr, 1024)
    logger.info("get content ok")
    # 释放返回的文件内容指针
    logger.info("free ...")
    lib.free_memory(file_content_ptr)
    logger.info("free ok")

    bio.seek(0)
    return bio

注意⚠️:释放内存的时候,lib.free_memory 函数应该是 void*的,而不应该是 char*的,都则会报错

invalid pointer error

参考:https://devpress.csdn.net/python/63045c69c67703293080bd32.html

14 浏览
7 爬虫
0 评论