首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >区分“基本”ctype数据类型及其子类?

区分“基本”ctype数据类型及其子类?
EN

Stack Overflow用户
提问于 2019-03-07 18:49:01
回答 1查看 363关注 0票数 2

引言

我正在开发一个代码生成器,它将围绕ctypes.cdll加载的函数生成函数。生成器将获取有关参数的ctypes和返回值的信息,并生成一些行为(在某种程度上,类似)的内容:

代码语言:javascript
复制
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函数和func函数中的python类型之间没有转换代码。这就是我的问题所在。

接近这个问题

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

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

这是 docs关于它的摘录:

当作为外部函数调用结果返回时,或者例如通过检索结构字段成员或数组项,基本数据类型将透明地转换为本机Python类型。换句话说,如果一个外部函数有一个restype of c_char_p,那么您将始终接收一个Python字节对象,而不是一个c_char_p实例。 基本数据类型的子类不继承此行为。因此,如果一个外部函数restypec_void_p的子类,您将从函数调用中接收到这个子类的一个实例。当然,您可以通过访问value属性获得指针的值。

所以我想绕开这件事。

似乎我需要知道一个类型是“基本”还是“子类”。这将帮助我定义生成代码的方式,即对于“基本”类型,生成的代码看起来类似于上面的示例,对于“基本”类型的子类,它将额外地将ctypes对象转换为合理的python类型(或者生成器将抛出一个异常,表示“不支持此操作”)。

问题:

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

我研究了ctypes python模块的代码,发现c_void_pc_char_p都是ctypes._SimpleCData的子类,因此在任何方面都不是其他类的子类。

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

EN

回答 1

Stack Overflow用户

发布于 2019-03-07 22:58:00

..。我是否误解了这个问题也适用于输入参数,还是这仅仅是对返回值的处理?

它不适用于输入参数,如下所示:

代码语言:javascript
复制
>>> 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

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

代码语言:javascript
复制
>>> 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'
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55050845

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档