ctypes 对枚举和标志有支持吗?

5 投票
2 回答
5043 浏览
提问于 2025-04-16 00:19

我有一个想用Python调用的API。这个API里面有一些用#define定义的标志和枚举。

// it's just almost C so don't bother adding the typedef and parenthesis diarrhea here.
routine(API_SOMETHING | API_OTHERTHING)
stuff = getflags()
? stuff & API_SOMETHING

action(API_INTERESTING)
mode = getaction()
? mode == INTERESTING

如果只关注枚举和标志的话,我的绑定应该把它们转换成:

routine(["something", "otherthing"])
stuff = getflags()
if 'something' in stuff

action('interesting')
mode = getaction()
if mode == 'interesting'

ctypes有没有直接处理这些的办法?如果没有,那就告诉我你通常用什么工具来处理Python绑定中的标志和枚举。

2 个回答

3

为什么不使用 c_uint 来处理 enum 参数,然后用这样的映射呢?(枚举通常是无符号整数值)

在C语言中:

typedef enum {
  MY_VAR      = 1,
  MY_OTHERVAR = 2
} my_enum_t;

在Python中:

class MyEnum():
    __slots__ = ('MY_VAR', 'MY_OTHERVAR')

    MY_VAR = 1
    MY_OTHERVAR = 2


myfunc.argtypes = [c_uint, ...]

这样你就可以把 MyEnum 的字段传递给这个函数了。

如果你想要枚举值的字符串表示,可以在 MyEnum 类中使用一个 dictionary(字典)。

3

我有点失望自己要回答这个问题。特别是因为我都是从那个手册里找到的答案。

http://docs.python.org/library/ctypes.html#calling-functions-with-your-own-custom-data-types

为了补充我的回答,我会写一些代码来包装一个项目。

from ctypes import CDLL, c_uint, c_char_p

class Flag(object):
    flags = [(0x1, 'fun'), (0x2, 'toy')]
    @classmethod
    def from_param(cls, data):
        return c_uint(encode_flags(self.flags, data))

libc = CDLL('libc.so.6')
printf = libc.printf
printf.argtypes = [c_char_p, Flag]

printf("hello %d\n", ["fun", "toy"])

encode_flags 这个函数会把那个很酷的列表转换成一个整数。

撰写回答