4

Before the enum module existed, c_int or related types were often used as substitute enums. But this did not have nor check for types.

Now that python has an enum module, is there a way to use that directly with ctypes?

simonzack
  • 19,729
  • 13
  • 73
  • 118

1 Answers1

3

Yes, we can easily create our own CEnum class thanks to ctypes allowing us the option to use custom classes. Enum types are checked automatically by ctypes.

from ctypes import windll
from enum import IntEnum


class CEnum(IntEnum):
    @classmethod
    def from_param(cls, self):
        if not isinstance(self, cls):
            raise TypeError
        return self


class EnumA(CEnum):
    CONST = 0


class EnumB(CEnum):
    CONST = 0

Here's an example (which abuses types, but shows the usage correctly):

windll.kernel32.GetModuleHandleA.argtypes = [EnumA]

>>> windll.kernel32.GetModuleHandleA(EnumA.CONST)
>>> windll.kernel32.GetModuleHandleA(EnumB.CONST)
ArgumentError: argument 1: <class 'TypeError'>: 

As an aside, I've since switched to cffi, which supports enums natively, and uses c definitions which happens to be a lot more concise compared to their ctype counterparts.

simonzack
  • 19,729
  • 13
  • 73
  • 118
  • I don't get any `ValueError` when I run your code on Python 3.4.1 -- also the error message shown seems odd, wouldn't it be `ValueError: 0 is not a valid EnumA`? – martineau Nov 29 '14 at 07:48
  • @eryksun Hmm, not sure how that happened, fixed. – simonzack Nov 30 '14 at 03:07
  • Unfortunately this doesn't allow me to use `CEnum` subclasses as C types in `ctypes.Structure` definitions. I've made a new [question](http://stackoverflow.com/questions/36877391/using-an-intenum-as-the-type-in-a-ctypes-structure-fields) for this. – Vlad Firoiu Apr 27 '16 at 00:26