在 Python 中动态创建 Ctypes
Dynamically create Ctypes in Python
我有一个文件,我从中读取了一个单独项目中使用的 ctypes 的定义。我可以读取文件并获取所有必要的信息以在 Python 中创建我想要的 ctype,例如名称、字段、位域、ctype 基础 class(结构、联合、枚举等),以及包。
我希望能够根据以上信息创建一个 ctype class。我也希望这些 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)
这个解决方案还不错,但是设置 class 的名称很难看,而且类型不能被 pickled。
是否有更好的创建动态 ctype 的方法class?
注:我用的是Python2.7
解决方案 2 可能是更好的选择,但如果您还静态地编写这样的 类,您可能希望使用元类来删除部分代码的重复数据。如果您需要您的对象是可腌制的,那么您将需要一种方法来从可腌制对象中重建它们。一旦你实现了这样的机制,你可以使用 a __reduce__()
method.
让 pickle 模块知道它
我会选择解决方案 1 的变体。与其评估代码,不如创建一个带有 __init__.py
的目录(即一个包),将其添加到您的 sys.path 并写出整个python 模块包含所有 类。然后你可以从一个稳定的命名空间导入它们,这会让 pickle
更快乐。
您可以获取输出并将其添加到应用程序的源代码中,或者动态重新创建它并在运行时将其缓存在目标机器上。
pywin32 使用类似这样的方法来缓存从 ActiveX 接口生成的 类。
我有一个文件,我从中读取了一个单独项目中使用的 ctypes 的定义。我可以读取文件并获取所有必要的信息以在 Python 中创建我想要的 ctype,例如名称、字段、位域、ctype 基础 class(结构、联合、枚举等),以及包。
我希望能够根据以上信息创建一个 ctype class。我也希望这些 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)
这个解决方案还不错,但是设置 class 的名称很难看,而且类型不能被 pickled。
是否有更好的创建动态 ctype 的方法class?
注:我用的是Python2.7
解决方案 2 可能是更好的选择,但如果您还静态地编写这样的 类,您可能希望使用元类来删除部分代码的重复数据。如果您需要您的对象是可腌制的,那么您将需要一种方法来从可腌制对象中重建它们。一旦你实现了这样的机制,你可以使用 a __reduce__()
method.
我会选择解决方案 1 的变体。与其评估代码,不如创建一个带有 __init__.py
的目录(即一个包),将其添加到您的 sys.path 并写出整个python 模块包含所有 类。然后你可以从一个稳定的命名空间导入它们,这会让 pickle
更快乐。
您可以获取输出并将其添加到应用程序的源代码中,或者动态重新创建它并在运行时将其缓存在目标机器上。
pywin32 使用类似这样的方法来缓存从 ActiveX 接口生成的 类。