Python使用ctypes API调用c代码。以下代码在Python2中工作,但在Python3.8中不起作用。我发现函数lib .fread(即bytes_read)的结果是0(但实际上应该是282624)。有人知道根本原因吗?
real_size = 282624
buffer = (ctypes.c_ubyte * real_size)()
length = real_size
libc = ctypes.CDLL(ctypes.util.find_library("c"))
# open file
libc.fopen.restype = ctypes.c_void_p
libc.fopen.argtypes = (ctypes.c_void_p, ctypes.c_void_p)
fp = libc.fopen(file_path, 'rb')
if fp is None:
raise OSError('Cannot open file {}'.format(file_path))
libc.fclose.argtypes = (ctypes.c_void_p,)
# seek offset
libc.fseek.restype = ctypes.c_int
libc.fseek.argtypes = (ctypes.c_void_p,ctypes.c_long, ctypes.c_int)
if libc.fseek(fp, 0, os.SEEK_SET) != 0:
libc.fclose(fp)
raise IOError("fseek to {} failed".format(file_offset))
libc.fread.argtypes = (ctypes.c_void_p, ctypes.c_size_t, ctypes.c_size_t, ctypes.c_void_p)
libc.fread.restype = ctypes.c_size_t
bytes_read = libc.fread(ctypes.addressof(buffer), 1, length, fp) #why bytes_read is 0?
或者另一个问题是如何使用read从二进制文件读取数据?
ctypes.util.find_library('c')
不能在Windows上工作,但是给定一个C运行时库(我硬编码了一个),这可以工作:
from __future__ import print_function # so this code will work on Python 2 as well
import os
import ctypes as ct
# Opaque type so you can't pass any old void*.
# Better type-safety.
class FILE(ct.Structure):
pass
# represents FILE* from C
PFILE = ct.POINTER(FILE)
libc = ct.CDLL('msvcrt')
libc.fopen.argtypes = ct.c_char_p, ct.c_char_p
libc.fopen.restype = PFILE
libc.fclose.argtypes = PFILE,
libc.fclose.restype = ct.c_int
libc.fseek.argtypes = PFILE, ct.c_long, ct.c_int
libc.fseek.restype = ct.c_int
libc.fread.argtypes = ct.c_void_p, ct.c_size_t, ct.c_size_t, PFILE
libc.fread.restype = ct.c_size_t
buffer = (ct.c_ubyte * real_size)()
fp = libc.fopen(b'test.bin', b'rb') # Use byte strings for char*
if fp is None:
raise OSError('Cannot open file {}'.format(file_path))
# Not really needed since file starts at offset 0
if libc.fseek(fp, 0, os.SEEK_SET) != 0:
libc.fclose(fp)
raise IOError("fseek to {} failed".format(file_offset))
bytes_read = libc.fread(buffer, 1, length, fp)
print(bytes_read)
但是,没有ctypes
也是如此:
with open('test.bin','rb') as f:
data = f.read()
print(len(data))