我正在尝试理解Python“ctypes”模块。我已经把一个简单的例子放在一起 - 理想情况下 - 包装了statvfs()函数调用。代码如下所示:
from ctypes import *
class struct_statvfs (Structure):
_fields_ = [
('f_bsize', c_ulong),
('f_frsize', c_ulong),
('f_blocks', c_ulong),
('f_bfree', c_ulong),
('f_bavail', c_ulong),
('f_files', c_ulong),
('f_ffree', c_ulong),
('f_favail', c_ulong),
('f_fsid', c_ulong),
('f_flag', c_ulong),
('f_namemax', c_ulong),
]
libc = CDLL('libc.so.6')
libc.statvfs.argtypes = [c_char_p, POINTER(struct_statvfs)]
s = struct_statvfs()
res = libc.statvfs('/etc', byref(s))
print 'return = %d, f_bsize = %d, f_blocks = %d, f_bfree = %d' % (
res, s.f_bsize, s.f_blocks, s.f_bfree)
运行此函数总是会返回:
return = 0, f_bsize = 4096, f_blocks = 10079070, f_bfree = 5048834
*** glibc detected *** python: free(): invalid next size (fast): 0x0000000001e51780 ***
*** glibc detected *** python: malloc(): memory corruption (fast): 0x0000000001e517e0 ***
我无法找到任何使用复杂类型调用函数的示例参数(有很多返回复杂类型的函数示例),但是在盯着ctypes文档一天左右之后,我认为我的调用语法是正确的......它实际上是在调用statvfs()调用并获得正确的结果。
我是否误解了ctypes文档?或者是其他事情发生在这里?
谢谢!
答案 0 :(得分:4)
执行此命令以获得系统上struct statvfs
的确切定义:
echo '#include <sys/statvfs.h>' | gcc -E - | less
然后按/struct statvfs<enter>
跳到定义并从那里浏览。
另请查看my patch以及their definition。
。{{3}}答案 1 :(得分:2)
statvfs的联机帮助页指出它使用的结构“大致如下定义”,因此您无法将联机帮助页的字段列表视为完整。
我的猜测是,在你定义它之后,在结构结束之后还有其他结构字段。这会导致statvfs函数覆盖结构外部的内存。我通过在我的结构定义中向_fields_
添加一个巨大的填充字段来解决这个问题:
("padding", c_int * 1000),
请记住,我的脚本以不同于您的方式表现出问题;我有一个段错误,而你只是收到一些错误消息。不过,我猜这是同样的问题,所以你应该尝试添加一些填充,看看问题是否仍然存在。
答案 2 :(得分:2)
正如Eli所说,查看/usr/include/bits/statvfs.h,您的结构未正确定义。
在我的64位Gentoo系统上,它将是:
class struct_statvfs (Structure):
_fields_ = [
('f_bsize', c_ulong),
('f_frsize', c_ulong),
('f_blocks', c_ulong),
('f_bfree', c_ulong),
('f_bavail', c_ulong),
('f_files', c_ulong),
('f_ffree', c_ulong),
('f_favail', c_ulong),
('f_fsid', c_ulong),
('f_flag', c_ulong),
('f_namemax', c_ulong),
('__f_space', c_int * 6) # you are missing this
]
答案 3 :(得分:0)
根据Fuse成功的pyfuse
ctypes包装器,以下内容用于Linux上的struct statvfs
:
class c_statvfs(Structure):
_fields_ = [
('f_bsize', c_ulong),
('f_frsize', c_ulong),
('f_blocks', c_fsblkcnt_t),
('f_bfree', c_fsblkcnt_t),
('f_bavail', c_fsblkcnt_t),
('f_files', c_fsfilcnt_t),
('f_ffree', c_fsfilcnt_t),
('f_favail', c_fsfilcnt_t)]