gpt4 book ai didi

python - 区分 "fundamental"ctypes数据类型及其子类?

转载 作者:太空宇宙 更新时间:2023-11-04 04:18:09 25 4
gpt4 key购买 nike

简介

我正在开发一个代码生成器,它可以生成围绕 ctypes.cdll 的函数加载的函数。生成器将获取有关 ctypes 的信息。的参数和返回值,并生成一些行为(并且在某种程度上看起来)像这样的东西:

func = getattr(dll, 'UglyLongAndUselessCName')
func.argtypes = [ctypes.c_uint32, ctypes.c_int8, ctypes.c_char_p]
func.restype = ctypes.c_int16

def nice_python_name(handle: int, arg1: int, arg2: str) -> int:
return func(handle, arg1, arg2)

注意 python 类型注释如何与 ctypes 很好地配合使用函数参数的数据类型。另请注意,nice_python_name 中的 python 类型之间没有转换代码。功能和func功能。这就是我的问题。

接近问题

ctypes文档说如果 argtypes使用“基本数据类型”指定加载的 DLL 函数的属性,然后在调用加载的 DLL 函数时,ctypes将为您转换为 python 类型。这很好,因为在这种情况下,我生成的代码将类似于上面的示例 - 我不需要显式转换 ctypes返回值的对象转换为 python 类型的值,而参数则相反。

但是,文档还说对于“基本数据类型的子类”,这个技巧不起作用,调用加载的 DLL 函数将需要 ctypes对象作为参数,结果将是 ctypes对象。

这是来自 the ctypes docs 的摘录关于它:

Fundamental data types, when returned as foreign function call results, or, for example, by retrieving structure field members or array items, are transparently converted to native Python types. In other words, if a foreign function has a restype of c_char_p, you will always receive a Python bytes object, not a c_char_p instance.

Subclasses of fundamental data types do not inherit this behavior. So, if a foreign functions restype is a subclass of c_void_p, you will receive an instance of this subclass from the function call. Of course, you can get the value of the pointer by accessing the value attribute.

所以,我想解决这个问题。

看来我需要知道一个类型是“基础”还是“子类”。这将帮助我定义代码生成的方式,即对于“基本”类型,生成的代码看起来类似于上面的示例,对于“基本”类型的子类,它将从 ctypes 进行额外转换。将对象转换为合理的 Python 类型(否则生成器只会抛出一个异常,提示“这不受支持”)。

问题:

如何区分“基本 ctypes 数据类型”和“基本 ctypes 数据类型的子类”?

我查看了 ctypes 的代码python 模块并发现 c_void_pc_char_pctypes._SimpleCData 的子类,因此一个在任何方面都不是另一个的子类。

另外,我是否误解了这个问题也适用于输入参数,或者这只是针对返回值的处理?

最佳答案

... do I misunderstand it that this problem also applies to the input arguments, or is this only the deal for the returned values?

它不适用于输入参数,如下面的序列所示:

>>> dll=CDLL('msvcrt')
>>> dll.printf.argtypes = c_char_p,
>>> dll.printf(b'abc') # Note: 3 is the return value of printf
abc3
>>> class LPCSTR(c_char_p): # define a subtype
... pass
...
>>> dll.printf.argtypes = LPCSTR,
>>> dll.printf(b'abc')
abc3

转换仍然适用于输入子类型;但是,输出子类型的工作方式与您提到的文档引用不同:

>>> dll.ctime.argtypes = c_void_p,
>>> dll.ctime.restype = c_char_p
>>> dll.ctime(byref(c_int(5)))
b'Wed Dec 31 16:00:05 1969\n'
>>> dll.ctime.restype = LPCSTR
>>> dll.ctime(byref(c_int(5))) # not converted to Python byte string
LPCSTR(1989707373328)
>>> x = dll.ctime(byref(c_int(5))) # but can get the value
>>> x.value
b'Wed Dec 31 16:00:05 1969\n'

关于python - 区分 "fundamental"ctypes数据类型及其子类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55050845/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com