Использование перечислений в ctypes.Structure - PullRequest
10 голосов
/ 10 октября 2009

У меня есть структура, к которой я обращаюсь через ctypes:

struct attrl {
   char   *name;
   char   *resource;
   char   *value;
   struct attrl *next;
   enum batch_op op;
};

Пока у меня есть код Python вроде:

# struct attropl
class attropl(Structure):
    pass
attrl._fields_ = [
        ("next", POINTER(attropl)),
        ("name", c_char_p),
        ("resource", c_char_p),
        ("value", c_char_p),

Но я не уверен, что использовать для перечисления batch_op. Должен ли я просто сопоставить его с c_int или?

Ответы [ 2 ]

9 голосов
/ 10 октября 2009

По крайней мере, для GCC enum - это просто числовой тип. Это может быть 8-, 16-, 32-, 64-битный или любой другой (я проверял это с 64-битными значениями), а также signed или unsigned. Я думаю, он не может превышать long long int, но практически вы должны проверить диапазон ваших enum с и выбрать что-то вроде c_uint.

Вот пример. Программа на C:

enum batch_op {
    OP1 = 2,
    OP2 = 3,
    OP3 = -1,
};

struct attrl {
    char *name;
    struct attrl *next;
    enum batch_op op;
};

void f(struct attrl *x) {
    x->op = OP3;
}

и Python один:

from ctypes import (Structure, c_char_p, c_uint, c_int,
    POINTER, CDLL)

class AttrList(Structure): pass
AttrList._fields_ = [
    ('name', c_char_p),
    ('next', POINTER(AttrList)),
    ('op', c_int),
]

(OP1, OP2, OP3) = (2, 3, -1)

enum = CDLL('./libenum.so')
enum.f.argtypes = [POINTER(AttrList)]
enum.f.restype = None

a = AttrList(name=None, next=None, op=OP2)
assert a.op == OP2
enum.f(a)
assert a.op == OP3
5 голосов
/ 10 октября 2009

Использование c_int или c_uint будет в порядке. Кроме того, в кулинарной книге есть рецепт для класса перечисления.

...