【发布时间】:2018-01-24 01:34:37
【问题描述】:
我有一个从中读取的文件,其中包含在单独项目中使用的 ctypes 定义。我可以读取文件并获取在 Python 中创建我想要的 ctype 所需的所有必要信息,例如名称、字段、位域、ctype 基类(结构、联合、枚举等)和包。
我希望能够根据上述信息创建一个 ctype 类。我还希望这些 ctypes 是可腌制的。
我目前有两个解决方案,我觉得这两个都是 hack。
解决方案 1
手动或使用 Jinja2 之类的工具以适当的 ctype 格式生成 Python 代码对象,然后评估 Python 代码对象。
此解决方案有使用 eval 的缺点。我总是尽量远离 eval,我觉得这不是一个使用它的好地方。
解决方案 2
在函数中动态创建 ctype,如下所示:
from ctypes import Structure
def create_ctype_class(name, base, fields, pack):
class CtypesStruct(base):
_fields_ = fields
_pack_ = pack
CtypesStruct.__name__ = name
return CtypesStruct
ctype = create_ctype_class('ctype_struct_name', ctypes.Structure,
[('field1', ctypes.c_uint8)], 4)
这个解决方案还不错,但是设置类的名字很丑,而且类型不能pickle。
有没有更好的方法来创建动态 ctype 类?
注意:我使用的是 Python 2.7
【问题讨论】:
-
您可以使用通用函数,例如
create_type = lambda name, *bases, **attrs: type(name, bases, attrs)。然后使用ctype = create_type('ctype', Structure, _fields_=[('field1', c_uint8)], _pack_=4)。 -
对于酸洗,模块中设置的名称必须与类名一致。同样对于数组类型,子类
Array并设置_type_和_length_,不幸的是,这不如使用ctype * length方便。此外,ctypes 默认__reduce__不会pickle 任何指针类型的实例,例如c_char_p,或包含一个或多个指针的聚合。 -
如果我将
_type_和_length_作为属性,您的第一条评论是否仍然有效?我正在开发一种适用于这些类的 reduce 方法。 -
解决方案 2 对我来说效果很好。给那里的菜鸟(像我一样)
'create_ctype_class()的一个注释返回类本身,而不是它的实例。所以你必须my_ctype_class = create_ctype_class(...)然后my_ctype = my_ctype_class()才能实际使用它。