python-cffi

cffi equivalent of ctypes "in_dll()"?


When accessing framework dlls on MacOS, which often have a lot of string constants defined, with ctypes I can do something like this to retrieve an arbitrary one at runtime, without having to define them all:

CFString = c_void_p
CFStringRef = POINTER(CFString)
my_dll = CDLL(...)
s1 = CFStringRef.in_dll(my_dll, "kSomeSpecificConstant")
s2 = CFStringRef.in_dll(my_dll, "kSomeOtherConstant)

With cffi, I can do something like this to explicitly define things:

my_dll = cffi.FFI()
my_dll.cref("""
    typedef void *CFTypeRef;
    typedef CFTypeRef CFStringRef;
    extern CFStringRef kSomeSpecificConstant
    extern CFStringRef kSomeOtherConstant
""")

but there doesn't seem to be a mechanism to do a runtime lookup for a symbol in the way in_dll() does?


Solution

  • In API mode (ffi.set_source()) it is not directly possible to do runtime lookups after the ffi.set_source() and ffi.compile() are done. In ABI mode (lib=ffi.dlopen()) you could do it by calling ffi.cdef() again to declare the symbol, and then I'm pretty sure it can be immediately accessed via a previously-returned lib. It's a bit of a hack but it should work. There are also ways to do it by invoking directly some internal functions in the CFFI runtime, but again only in ABI mode (in API mode we have no dynamic handle to the DLL in the first place; indeed there is not necessary a separate DLL at all).

    But the proper way to do dynamic symbol lookups is to do it in the same way as you would in C: by using standard library functions like dlsym(). With CFFI you would do it by adding the declaration void *dlsym(void *handle, const char *symbol); to the ffi.cdef(), and related functions starting with void *dlopen(const char *filename, int flags). Check the man pages for details on MacOSX; there may be differences between these standard POSIX functions and the way they are used for frameworks on Mac.