python-3.xcffi

Python3 cffi: is there a way to merge two independent ffi's into one?


Suppose I have two libraries which need to work together. One library has a function that accepts a type built in another library.

Suppose further that I've created two independent FFI interfaces for each of the two libraries.

Now, I have everything working fine for each individual library, but when I go to pass the object type built in one ffi to the other ffi, I get the following error:

TypeError: initializer for ctype 'Foo *' appears indeed to be 'Foo *', but the types are different (check that you are not e.g. mixing up different ffi instances)

What I am trying to avoid is integrating the two libraries into one header and one totally integrated class. This is because the class will be a one-off and the mix of methods will be random, detailed, specific, over specialized: i.e., hard to name and remember to use later.

Is there some way that I can merge two ffi's so that they can work together?

Or, for example, perform some sort of casting operation from one ffi's type to the other? The library backend will work just fine...

(I've tried casting via second_ffi.cast('Foo *',first_ffi_foo), but something more manual seems to be required, like copying the bytes out of the first ffi into the second ffi w/ the cast)


Solution

  • I ended up solving this by separating the scope of the cffi.FFI instance from the classes I am partitioning C-headers into.

    By accepting a cffi.FFI() option at class declaration, I was able to mix library interfaces together:

    class LibFoo:
        def __init__(self, ffi_option: Optional[FFI], ...):
           if ffi_option is None:
              self.ffi = FFI()
              self.__ownFFI = True
           else:
              self.ffi = ffi
              self.__ownFFI = False
    
        def __del__(self):
            if self.__ownFFI:
               # close down the ffi
    
    

    And the composition:

    class ManyLibs(LibFoo, LibBar):
       def __init__(self):
           self.ffi = FFI()
           LibFoo.__init__(self,self.ffi)
           LibBar.__init__(self.self.ffi)