2015-05-10 2 views
1

У меня есть перечисление в Python (портированном enum пакет 2,7), который предназначен, чтобы быть только целыми числами:Использование Python 2.7 перечисления из C

import enum 
class MyEnum(enum.Enum): 
    val = 0 

Допустим, я получаю PyObject * в расширение C указывающей до MyEnum.val. Я хочу целое значение, связанное с PyObject *. Как мне получить его наиболее лаконично?

+0

Насколько я знаю, пакет 'enum34' не предоставляет специального представления C или API, поэтому вам просто нужно вызвать' PyObject_GetAttr' и друзей, как и любой другой тип pure-Python. – abarnert

+0

Предоставляет ли он что-нибудь, что позволило бы мне унифицировать кодовые пути для обработки их вместе с объектами 'x', для которых' PyInt_Check (x)! = 0'? например поддержка встроенных протоколов, что-то вроде 'PyNumber_Int (x)' (если это действительно сработало). – user

+1

Значения «Enum» явно сконструированы _not_, чтобы действовать так, как будто они являются подтипом 'int'. Значения IntEnum - это еще одна история. Вы должны иметь возможность «PyInt_Check» и «PyInt_AsLong». Но для 'Enum' вы не должны быть в состоянии, поэтому вам (по крайней мере, должно) нужно получить значение' value' attr, если вы хотите использовать их как ints, так же, как и для Python. – abarnert

ответ

2

Глядя на источник на enum34 backport, так же как и модуль enum в формате 3.4+, это чистый Python и ничего не дает, чтобы открыть пользовательский API C.

Итак, вы просто используете PyObject_GetAttr и друзей, чтобы получить доступ к атрибутам класса. В частности, если у вас есть MyEnum.val, вам необходимо получить его атрибут value, который будет int, который вы можете затем PyInt_AsLong.

Точно так же все работает на Python. Если вы попытаетесь использовать MyEnum.val, где ожидается int, вы должны получить TypeError; если вы попытаетесь явным образом позвонить int(MyEnum.val), вы получите получите TypeError. Итак, хотя я не тестировал его, PyInt_AsLong прямо на константе вместо value должен поднять TypeError и вернуть -1.

Если вам нужны константы перечисления, которые действуют как подтипы int, то, как объясняют документы enum, вы хотите IntEnum. Обычно это не совсем то, что вы хотите (как объясняют документы), но если это так, конечно, это работает. И вы должны быть в состоянии PyInt_Check и PyInt_AsLong значение IntEnum (хотя, опять же, я не тестировал).