Jos*_*osh 11 python reflection ctypes
test.c的:
#include <stdio.h>
#include <stdlib.h>
struct s {
char a;
int b;
float c;
double d;
};
struct s *create_struct()
{
struct s *res = malloc(sizeof(struct s));
res->a = 1; res->b = 2; res->c = 3.0f; res->d = 4.0;
return res;
}
Run Code Online (Sandbox Code Playgroud)
test.py:
from ctypes import *
class S(Structure):
_fields_ = [
('a', c_byte),
('b', c_int),
('c', c_float),
('d', c_double)
]
lib = CDLL('./test.so')
create_struct = lib.create_struct
create_struct.restype = POINTER(S)
create_struct.argtypes = []
s_ptr = create_struct()
s = s_ptr.contents
print s._fields_[0][0], s.a
print s._fields_[1][0], s.b
print s._fields_[2][0], s.c
print s._fields_[3][0], s.d
print s.__dict__
Run Code Online (Sandbox Code Playgroud)
输出:
a 1
b 2
c 3.0
d 4.0
{}
Run Code Online (Sandbox Code Playgroud)
我想调整上面的python脚本来打印我的结构的每个字段,而不必为每个字段明确地做.据我所知,这可以使用__dict__属性完成,但我的是空的.对于扩展ctypes.Structure的类,有没有办法做到这一点?
fal*_*tru 15
怎么用getattr?
>>> from ctypes import *
>>>
>>> class S(Structure):
... _fields_ = [
... ('a', c_byte),
... ('b', c_int),
... ('c', c_float),
... ('d', c_double)
... ]
...
>>> s = S(1, 2, 3, 4.0)
>>>
>>> for field_name, field_type in s._fields_:
... print field_name, getattr(s, field_name)
...
a 1
b 2
c 3.0
d 4.0
Run Code Online (Sandbox Code Playgroud)
UPDATE
如果结构(或联合)中有一个位域,则迭代_fields_产生一个由3个项组成的元组,这将导致ValueError.为了防止您需要调整代码:
...
for field in s._fields_:
print field[0], getattr(s, field[0])
Run Code Online (Sandbox Code Playgroud)
我刚刚想出了这个,对于我正在从事的一个项目,我希望能够漂亮地打印几个 C 结构(在我的例子中,在 Jupyter 笔记本中):
>>> # /sf/answers/4340832121/
>>>
>>> from ctypes import Structure, c_byte, c_int, c_float, c_double
>>>
>>>
>>> class MyStructure(Structure):
...
... def __repr__(self) -> str:
... values = ", ".join(f"{name}={value}"
... for name, value in self._asdict().items())
... return f"<{self.__class__.__name__}: {values}>"
>>>
>>> def _asdict(self) -> dict:
... return {field[0]: getattr(self, field[0])
... for field in self._fields_}
>>>
>>>
>>> class S(MyStructure):
... _fields_ = (
... ('a', c_byte),
... ('b', c_int),
... ('c', c_float),
... ('d', c_double)
... )
>>>
>>> s = S(1, 2, 3.0, 4.0)
>>> s
<S: a=1, b=2, c=3.0, d=4.0>
Run Code Online (Sandbox Code Playgroud)