如何像访问ctypes一样访问ctypes结构的属性,而不是通过给定的包装器?

1 投票
2 回答
4241 浏览
提问于 2025-04-16 22:08

这段内容有点不一致:

from ctypes import *

class S(Structure):
    _fields_ = [("x", POINTER(c_int)), ("y", c_int)]

o = S()
print o.x
print o.y

返回的结果是

<__main__.LP_c_int object at 0x10d3d08c0>
0

在一种情况下,它返回的是一个 ctypes 类型,而在另一种情况下,它直接返回了值。

我有一些更通用的代码,里面总是需要传递一个 ctypes 类型的实例(这个实例是可以写的,也就是说,写入它就意味着修改上面例子中的 o)。对于 o.x 这样是可以的,但 o.y 就不行。

我该如何获取 o.yc_int 实例呢?

2 个回答

0

一开始我以为这只是对“正常”类型的 repr 方法有些不同,但经过一些测试后,我觉得这里肯定有些奇怪的地方。如果某个东西在结构里和不在结构里,确实会有很大的区别。

from ctypes import *

class S(Structure):
    _fields_ = [("x", POINTER(c_int)), ("y", c_int), ("z", c_float)]

o = S()

x = POINTER(c_int)
y = c_int(1)
z = c_float(2.2)

print("In structure: x:{}, y:{}, z:{}".format(o.x, o.y, o.z))
print("Out of structure: x:{}, y:{}, z:{}".format(x, y, z))

在结构里:x:<main.LP_c_long 对象在 0x000000000A090EC8>, y:0, z:0.0

不在结构里:x:, y:c_long(1), z:c_float(2.200000047683716)

特别是,我觉得这应该算是个bug:

o.x.contents = y #OK
o.x.contents = o.y #not OK!!

追踪信息(最近的调用在最前面): 文件 "", 第 1 行, 在 TypeError: 期望是 c_long 而不是 int

2

_ctypes的源代码来看,似乎在简单的ctypes实例被包装时,它并不会进行这种聪明的自动转换。

所以,有一个(不太优雅的)解决办法是这样的:

from ctypes import *

def WrapClass(c):
    class C(c): pass
    C.__name__ = "wrapped_" + c.__name__
    return C

class S(Structure):
    _fields_ = [("x", POINTER(c_int)), ("y", WrapClass(c_int))]

o = S()
print o.x
print o.y
print o.y.value

撰写回答