在Python ctypes中实现offsetof()函数

6 投票
2 回答
5271 浏览
提问于 2025-04-16 10:09

我在使用ctypes的时候,发现无法实现一个结构体的偏移量(offsetof)。我看过ctypes的常见问题解答,但要么是没用,要么我搞不清楚具体细节。

Python 2.6.4 (r264:75706, Dec 19 2010, 13:04:47) [C] on sunos5
Type "help", "copyright", "credits" or "license" for more information.
>>> from ctypes import *
>>> class Dog(Structure):
...   _fields_ = [('name', c_char_p), ('weight', c_int)]
...   def offsetof(self, field):
...     return addressof(field) - addressof(self)
... 
>>> d = Dog('max', 80)
>>> d.offsetof(d.weight)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in offsetof
TypeError: invalid type
>>> d.offsetof(weight)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'weight' is not defined
>>> d.offsetof('weight')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in offsetof
TypeError: invalid type

看起来addressof()这个函数在结构体的成员上(比如d.weight)不太管用。我试过用pointer()byref()等其他方法,但都没成功。

当然,我希望这个方法能在所有架构上都能用,不管指针的大小,也不管填充的影响,所以请不要建议我直接把所有前面元素的大小加起来,除非你能确保考虑到C编译器添加的任何填充。

有没有什么好主意?谢谢!

2 个回答

0

问题在于,结构体的成员有时候会被当作普通的Python类型返回。

举个例子:

class Test(Structure):
    _fields_ = [('f1', c_char), ('f2', c_char * 0)]

你可以看到,Test类中的f1和f2这两个成员的类型都是字符串(str)。

20
class Dog(Structure):
    _fields_ = [('name', c_char_p), ('weight', c_int)]

Dog.name.offset
# 0
Dog.weight.offset
# 4 (on my 32-bit system)

把这个变成一个方法的任务就留给你自己去做啦 :)

撰写回答