I would like to get the full listing of enums from the header file using cffi. But I see a strange behaviour: by observing the object, I'm forcing the change in the underlying __dict__
:
>>> from cffi import FFI
>>> ffi = FFI()
>>> ffi.cdef('typedef enum {RANDOM, IMMEDIATE, SEARCH} strategy;')
>>> c = ffi.dlopen('c')
# the dictionary is empty
>>> print c.__dict__
{}
>>> dir(c)
# the dictionary is populated
>>> print c.__dict__
{'SEARCH': 2, 'RANDOM': 0, 'IMMEDIATE': 1}
I'm guessing that __dict__
is not populated until first getattr()
on the class is called, but the real question is: what does dir()
do that populates __dict__
? Calling hasattr()
seems to do the same thing.
Technically, the reason for what you observe is that dir()
tries to get a few special attributes like __members__
on the lib
object. The code in cffi adds attributes lazily as they are computed. If a name is not found as a function, it proceeds to install all enums declarations and tries to return one of them if that's the name we try to read. That's why trying to read a non-existing name will always install all enums in lib.__dict__
. (This logic is only for libs returned by ffi.dlopen()
, not for the API mode.)
Ideally, you should not rely on any of this, but in this case you have to: it is really a bug. Note that you can simply read dir(lib)
twice: the second time, it will contain the enum values...
(Fixed the bug in 19cae8d1a5f6: at least dir(lib)
should always work in cffi 1.4---and no longer list all the special Python method names.)