A ForeignFunctionInterface (FFI) is an interface that allows calling code written in one programming language, from another that is neither a superset nor a subset.
The term comes from CommonLisp; though it's applicable to any such interface. Other language communities don't use the term FFI as much; some languages such as Java have their own term -- Java refers to it as the JavaNativeInterface.
The most common cases are interfaces that allow calling CeeLanguage or CeePlusPlus from a higher-level language.
...with the caveat that the collection of functions that are callable in CeePlusPlus is restricted -- generally things that are callable from C.
There are implementations for many languages to call CeeLanguage and CeePlusPlus in SimplifiedWrapperAndInterfaceGenerator (SWIG).
Implementing an FFI can be done in several ways:
- Requiring the called functions in the target language implement a specific protocol. JNI works in this fashion; any C/C++ function called by JNI must be defined in terms of a specific set of Java-compatible datatypes. Converting this stuff to standard C datatypes and back is (or at least was) the responsibility of the called native code. JNI also provides ways for C code to call back Java code -- necessary in many cases, especially if the C code needs to "hold on to" Java objects. The Java GarbageCollector does not examine the native code for references, so C code that holds on to Java objects must explicitly mark them reserved/unreserved (this is not necessary for objects which are arguments to native functions, but whose native functions go out of scope when the function returns).
- Implementing a wrapper library that takes a given low-language function, and "wraps" it with code to do data conversion to/from the high-level language conventions.
- Examples are the FFIs of Squeak
- and Haskell
- see
- Requiring functions declared native to use a subset of high-level functionality (which is compatible with the low-level language).
See also "Design Issues for Foreign Function Interfaces", at
If we refer to the low-level language as the "host" language and the high-level language as the "guest" language, then these three approaches boil down to ways to bridge the gap between them, as follows.
- The host is expected to bridge the gap. You have to write host-language functions specifically to be called from the guest. An API may be offered for the host language to use to communicate with guests.
- The gap is bridged by some kind of tool that does not belong strictly to either the host or guest languages.
- The guest is expected to bridge the gap. This means the guest language can call any host-language function, but the guest language now has to have support for many low-level features, in order to communicate with the host language effectively.
It seems that many VbClassic programs use "components" written in C.
- Like almost all modern languages, VbClassic can call C code. VbClassic can also use COM objects, Microsofts component technology, which uses the *other* method of FFI, which is requiring all participants to implement a specific calling convention and data definition used for communication.