Foreign function interface
A foreign function interface is a mechanism by which a program written in one programming language can call routines or make use of services written in another.
Naming
The term comes from the specification for Common Lisp, which explicitly refers to the language features for inter-language calls as such; the term is also used officially by the Haskell and Python programming languages. Other languages use other terminology: the Ada programming language talks about "language bindings", while Java refers to its FFI as the JNI or JNA. Foreign function interface has become generic terminology for mechanisms which provide such services.Operation
The primary function of a foreign function interface is to mate the semantics and calling conventions of one programming language, with the semantics and conventions of another. This process must also take into consideration the runtime environments and/or application binary interfaces of both. This can be done in several ways:- Requiring that guest-language functions which are to be host-language callable be specified or implemented in a particular way; often using a compatibility library of some sort.
- Use of a tool to automatically "wrap" guest-language functions with appropriate glue code, which performs any necessary translation.
- Use of wrapper libraries
- Restricting the set of host language capabilities which can be used cross-language. For example, C++ functions called from C may not include reference parameters or throw exceptions.
- If one language supports garbage collection and the other does not; care must be taken that the non-GC language code does nothing to cause GC in the other to fail. In JNI, for example, C code which "holds on to" object references that it receives from Java must "register" this fact with the Java runtime environment ; otherwise, Java may delete objects before C has finished with them.
- Complicated or non-trivial objects or datatypes may be difficult to map from one environment to another.
- It may not be possible for both languages to maintain references to the same instance of a mutable object, due to the mapping issue above.
- One or both languages may be running on a virtual machine ; moreover, if both are, these will probably be different VMs.
- Cross-language inheritance and other differences, such as between type systems or between object-composition models, may be especially difficult.
By language
- Ada language bindings, allowing not only to call foreign functions but also to export its functions and methods to be called from non-Ada code.
- C++ has a trivial FFI with C, as the languages share a significant common subset. The primary effect of the declaration in C++ is to disable C++ name mangling.
- Clean provides a bidirectional FFI with all languages following C or the stdcall calling convention.
- CNI, alternative to JNI used in the GNU compiler environment.
- D does it the same way as C++ does, with extern "C" through extern
- Dart includes dart:ffi library to call native C code for mobile, command-line, and server applications
- Dynamic languages, such as Python, Perl, Tcl, and Ruby, all provide easy access to native code written in C/C++.
- Factor has FFIs for C, , , and ; all of these enable importing and calling arbitrary shared libraries dynamically.
- The FFIs of Common Lisp and Haskell
- Fortran 2003 has a module ISO_C_BINDING which provides interoperable data types, interoperable pointers, interoperable global data stores, and mechanisms for calling C from Fortran and for calling Fortran from C.
- Go can call C code directly via the
"C"
pseudo-package. - GWT, in which Java is compiled to JavaScript, has an FFI called JSNI which allows Java source to call arbitrary JavaScript functions, and for JavaScript to call back into Java.
- JNI, which provides an interface between Java and C/C++, the preferred systems languages on most systems where Java is deployed. JNA provides an interface with native libraries without having to write glue code. Another example is
- Julia has
ccall
keyword to call C ; while packages, providing similar no-boilerplate support, are available for some languages e.g. for Python, Java and R. Interactive use with C++ is also possible with Cxx.jl package. - PHP provides FFI to C.
- Python provides the and modules. For example, the ctypes module can load C functions from shared libraries/DLLs on-the-fly and translate simple data types automatically between Python and C semantics as follows:
libc = ctypes.CDLL # Under Linux/Unix
t = libc.time # Equivalent C code: t = time
- P/Invoke, which provides an interface between the Microsoft Common Language Runtime and native code.
- Racket has a native FFI based heavily on macros that enables importing arbitrary shared libraries dynamically.
- Raku can call Ruby, Python, Perl, Brainfuck, Lua, C, C++, Go and Scheme Guile/Gambit
- Rust also defines a foreign function interface.
- Visual Basic has a declarative syntax that allows it to call non-Unicode C functions.
- One of the bases of the Component Object Model is a common interface format, which natively uses the same types as Visual Basic for strings and arrays.
- LuaJIT, a just-in-time implementation of Lua, has an FFI that allows "calling external C functions and using C data structures from pure Lua code".
- PhoneGap is a platform for building native mobile applications using HTML, CSS and JavaScript. Additionally has FFIs via JavaScript callback functions for access to methods and properties of mobile phone's native features including Accelerometer, Camera, Compass, Storage, Notification, Media and Capture, File, Contacts, Events, Device and Connection information.,.
- Wolfram Language provides a technology called WSTP which enables bidirectional calling of code between other languages with bindings for C++, Java,.NET and other languages.
Some FFIs are restricted to free standing functions, while others also allow calls of functions embedded in an object or class ; some even permit migration of complex datatypes and/or objects across the language boundary.
In most cases, an FFI is defined by a "higher-level" language, so that it may employ services defined and implemented in a lower level language, typically a systems language like C or C++. This is typically done to either access OS services in the language in which the OS' API is defined, or for performance considerations.
Many FFIs also provide the means for the called language to invoke services in the host language as well.
The term foreign function interface is generally not used to describe multi-lingual runtimes such as the Microsoft Common Language Runtime, where a common "substrate" is provided which enables any CLR-compliant language to use services defined in any other. In addition, many distributed computing architectures such as the Java remote method invocation, RPC, CORBA, SOAP and D-Bus permit different services to be written in different languages; such architectures are generally not considered FFIs.