Python3、ctypes API 和枚举

Python3, ctypes API and Enum

提问人:Wör Du Schnaffzig 提问时间:12/24/2020 最后编辑:Wör Du Schnaffzig 更新时间:12/24/2020 访问量:373

问:

似乎我无法实例化 ctypes。具有枚举返回值的 CFUNCTYPE 原型,即使枚举包含 classmethod 也是如此。 有人经历过吗? 也许有解决方法吗? 我做错了什么吗?from_param

这有效:

import ctypes as ct

@ct.CFUNCTYPE(ct.c_int, ct.c_int)
def pyfunc(a):
    return 100

print(pyfunc(10))

100

这也有效(linux):

import ctypes as ct
import enum


class MyEnum(enum.Enum):
    A = 1
    B = 2

    @classmethod
    def from_param(cls, param):
        return ct.c_int(param)


printf = ct.CDLL("libc.so.6").printf
printf.restype = MyEnum  
printf(b"1")

<MyEnum.A:1>

printf(b"12")

<MyEnum.B:2>

这将失败:

import ctypes as ct
import enum

class E(enum.Enum):
    A = 10
   
    @classmethod
    def from_param(cls, param):
        return ct.c_int(param)

 @ct.CFUNCTYPE(E, ct.c_int)
 def pyfunc(a):
     return E(10)
Traceback (most recent call last):
  File "<pyshell#18>", line 1, in <module>
    @ct.CFUNCTYPE(E, ct.c_int)
TypeError: invalid result type for callback function
python-3.x 枚举 回调 原型 c型

评论

0赞 Ethan Furman 12/24/2020
您需要使用 ,但取决于 ctytpes 如何处理其参数,这些参数可能仍然不起作用。IntEnum
0赞 Wör Du Schnaffzig 12/24/2020
我试过了 ->这给了我完全相同的结果
0赞 CristiFati 12/24/2020
为什么需要回调函数来返回枚举值?为什么不简单地返回一个 int 并将其转换为枚作为最后一步呢?
0赞 Wör Du Schnaffzig 12/24/2020
因为我知道如果一切都是 int 而不是一些正确的类型,代码会有多混乱
0赞 CristiFati 12/24/2020
这是真的。嗯,从上面的例子来看,不清楚 C 在哪里发挥作用。

答:

1赞 Ethan Furman 12/24/2020 #1

这里有几个问题:

  • 的返回值返回到 C 例程,因此必须是标准 ctypes 类型(不是 ctype 类型)pyfuncE

  • 既没有,也没有似乎被调用为返回类型from_param_as_parameter_

要解决这些问题,您必须

  • 将 in 更改为E@ct.CFUNCTYPEct.c_int

以及以下其中一项:

  • 使用代替IntEnumEnum

  • 返回E(a).value

  • 将 and 添加到您的枚举中(这使得它足够像):__int____index__intctypes
    class E(enum.Enum):
        A = 10
        #
        def __int__(self):
            return self.value
        __index__ = __int__

评论

0赞 Wör Du Schnaffzig 12/24/2020
“pyfunc 的返回值将返回 [,,,]” -> 不,pyfunc 被调用方的返回值将返回到 python 调用方。“既不是from_param也不是as_parameter [...]” -> 请参阅我添加的示例,即 ctypes 确实可以在枚举成员中转换c_int返回值。
0赞 Mark Tolonen 12/24/2020
@pqans,但通常 -wrapped 函数由 C 调用者调用,并且它无法处理 Python Enum 对象。如果您使用 Python 调用程序调用它,请不要使用 .CFUNCTYPECFUNCTYPE
0赞 Wör Du Schnaffzig 12/24/2020
如果它的行为与原始 c 函数不同,则它不是单元测试的适当模拟。但现在我明白了为什么 CFUNCTYPE 会以这种方式行事。