Fact-checked by Grok 2 weeks ago

Foreign function interface

A foreign function interface (FFI) is a mechanism that enables software written in one programming language, known as the host language, to invoke and interact with code or libraries written in another language, referred to as the foreign language, thereby facilitating interoperability between disparate language ecosystems. Typically, the foreign language is a lower-level one like C or C++, allowing higher-level languages to access performance-optimized or legacy components without full reimplementation. FFIs play a vital role in modern software development by promoting code reuse and efficiency; for instance, they enable applications in languages such as Python, Java, and .NET to integrate existing C libraries for tasks like system calls or numerical computations, which might otherwise require costly native rewrites. Prominent examples include Python's ctypes module, a standard library that loads and calls functions from dynamic-link libraries (DLLs) or shared objects using C-compatible data types and calling conventions. In Java, the Java Native Interface (JNI) provides a standardized way for Java Virtual Machine-hosted code to interoperate with native applications and libraries in C, C++, or assembly, supporting object manipulation and exception propagation across boundaries. Similarly, .NET's Platform Invoke (P/Invoke) allows managed code to access unmanaged libraries, handling data marshaling for structs, callbacks, and functions in DLLs. Other languages, such as Haskell, incorporate FFIs to describe and invoke foreign code interfaces directly in their type systems. While FFIs enhance modularity and performance, they introduce challenges stemming from linguistic differences, including mismatches in type systems, models, , and , which can lead to subtle bugs like memory leaks or if not carefully managed. To mitigate these, many FFIs incorporate features like automatic , runtime checks, or static analysis tools, though developers must often manually specify signatures and handle resource cleanup. Overall, FFIs remain essential for polyglot programming environments, balancing the abstraction of high-level languages with the raw efficiency of .

Core Concepts

Definition

A foreign function interface (FFI) is a mechanism that enables software written in one programming language to call functions, routines, or services implemented in another programming language, facilitating interoperability between disparate language ecosystems. This interface typically serves as a bridge, allowing code in a host language to invoke foreign code while handling the necessary translations at the boundaries of the two languages. Key characteristics of an FFI include support for runtime binding, which enables of foreign code modules such as shared libraries or DLLs, as well as compile-time linking for static integration. It must address (ABI) compatibility to ensure proper function invocation across languages, including management of calling conventions, data types, and memory layouts. Additionally, FFIs often provide portability across different architectures, operating systems, and implementations by abstracting low-level details into higher-level constructs. Unlike broader interoperability frameworks that might encompass object serialization or full runtime integration, an FFI is specifically focused on enabling direct function calls and the exchange of data between languages, without assuming type consistency or extensive ecosystem merging. For instance, it is commonly employed in scenarios where high-level scripting languages interact with low-level C libraries.

Purpose and Applications

Foreign function interfaces (FFIs) primarily serve to extend the capabilities of a programming language by allowing it to invoke optimized libraries written in other languages, such as calling performance-critical C code from Python to handle computationally intensive tasks without rewriting the library. This approach leverages the strengths of lower-level languages for efficiency while retaining the productivity of higher-level ones. Additionally, FFIs enable polyglot programming in modular systems, where different components of an application are developed in specialized languages to optimize for specific needs like concurrency or domain-specific logic. They also facilitate the integration of legacy codebases—often in C or C++—into modern applications, avoiding the costly and error-prone process of full rewrites by providing a bridge to existing, battle-tested implementations. In practical applications, FFIs are widely used for embedding scripting languages within host applications, particularly in game development where Lua is embedded into C++ engines to script behaviors, AI, and user interfaces dynamically without recompiling the core engine. Another common use is wrapping low-level system APIs—such as operating system calls or device drivers—for access from higher-level languages, enabling safer and more abstracted interactions with platform-specific functionality. FFIs also support plugin architectures, allowing modular extensions where components in different languages interact in-process, such as a Python application invoking a Rust-based cryptographic library. The benefits of FFIs include substantial of existing codebases, reducing time and minimizing by incorporating mature libraries rather than duplicating effort. They accelerate prototyping by combining the rapid of scripting languages with the performance of compiled ones, as seen in workflows blending 's ease with C's speed. Furthermore, FFIs provide access to hardware-specific optimizations in specialized libraries, enhancing overall system performance in resource-constrained environments like embedded systems.

Terminology

Naming Conventions

The standard term "foreign function interface" (FFI) refers to a mechanism enabling a program in one programming language to invoke functions or services written in another language, with "foreign" denoting code that is non-native to the host environment. This nomenclature originated in the context of implementations, where it described interfaces to external C libraries and other non-Lisp code. Alternative terms include "foreign language interface," which emphasizes interactions across programming languages more broadly, as seen in systems like and CLISP. Another variation is "external function interface," used in environments such as and to highlight calls to routines outside the primary language runtime. Language-specific implementations often adopt tailored names, such as the "" (JNI) for Java's binding to native code, or Python's "ctypes" module for dynamic loading of shared libraries. A historical shift in terminology from general "foreign interface" to "foreign function interface" underscores the emphasis on function-level invocations, particularly as APIs increasingly consist of callable procedures rather than broader services. Naming diversity arises from differing emphases—such as language boundaries versus application binary interface (ABI) compatibility—and ecosystem-specific conventions, exemplified by "FFI" in Ruby's bindings library and "interop" in .NET for cross-language marshaling. A foreign function interface (FFI) is closely related to but distinct from an (ABI), which specifies the low-level conventions for binary compatibility, including calling conventions, data representation, and symbol resolution across software components on a given . FFIs depend on a stable ABI to perform cross-language function calls at the binary level, yet an ABI addresses broader interoperability concerns, such as and memory layout, that extend beyond the scope of function invocation alone. In contrast to an (API), which offers a high-level, language-specific for software within the same or , an FFI enables direct, low-level access to routines in foreign languages, typically native code outside the host environment. Interoperability frameworks like CORBA, which facilitate communication across networks via an Object Request Broker, or RPC, which supports remote procedure invocation over distributed systems, differ fundamentally as they operate across process boundaries rather than enabling in-process, local function calls. Bindings and wrappers represent intermediate code layers that map foreign functions to the host language's idioms, often generated automatically to handle type conversions and error propagation. Tools such as automate the creation of these bindings by parsing C/C++ headers and producing language-specific wrappers that leverage an underlying FFI for execution. While essential for usability, bindings are tools or abstractions built atop an FFI, not the interface mechanism itself, which focuses on the raw protocol for invoking foreign code. Key distinctions of FFIs include their emphasis on dynamic and , unlike compile-time linking that statically binds dependencies during the build , or comprehensive virtual machine interop that integrates languages within a unified execution without explicit bridging. This -centric, in-process nature positions FFIs as a targeted solution for local cross-language reuse, avoiding the overhead of protocols or full fusion.

Mechanisms

Basic Operation

A foreign function interface (FFI) enables a in one language to invoke functions compiled in another language, typically by leveraging the operating system's dynamic linking facilities to load and access external code at . This contrasts with static linking, where dependencies are resolved at , by providing greater flexibility for loading libraries on demand, such as when optional extensions are needed or to support plugins. Dynamic linking is particularly useful in FFIs because it allows the host to discover and bind to foreign functions without recompilation, though it introduces overhead for resolution. The basic operation of an FFI involves a sequence of steps to prepare, invoke, and handle the results of a foreign function call. First, the foreign is loaded dynamically into the process's using platform-specific APIs, such as dlopen() on systems, which returns a handle to the loaded module and resolves its dependencies according to the specified mode (e.g., lazy binding to defer symbol resolution). On Windows, this corresponds to LoadLibrary(), which maps the DLL into memory and increments its reference count. Next, the address of the desired foreign function is resolved from the loaded library via symbol lookup functions like dlsym() in environments, which searches for the symbol name within the module's handle and returns a pointer to it, or GetProcAddress() on Windows, which retrieves the procedure's by name or ordinal. This step ensures the host program obtains a callable reference to the foreign code, often using lazy resolution to avoid upfront costs for unused symbols. Arguments are then marshaled into formats compatible with the foreign language's expectations, such as converting high-level data structures to primitive types, before the is invoked through the resolved pointer while adhering to the platform's for parameter passing and stack management. Upon completion, the return value is unmarshaled back into the host language's representation, and the library handle may be closed if no longer needed to free resources. The following high-level pseudocode illustrates a typical FFI invocation flow:
library_handle = load_library("foreign_library")
if library_handle is null:
    handle_error("Failed to load library")

function_pointer = resolve_symbol(library_handle, "foreign_function")
if function_pointer is null:
    handle_error("Failed to resolve function")

# Marshal arguments (high-level conversion)
prepared_args = marshal(arguments)

# Invoke, respecting calling convention
result = call(function_pointer, prepared_args)

# Unmarshal result
unmarshaled_result = unmarshal(result)

unload_library(library_handle)  # Optional, if reference count allows
This sequence ensures safe cross-language interaction while deferring detailed type conversions and memory handling to separate mechanisms.

Calling Conventions

In foreign function interfaces (FFI), a calling convention defines the protocol for how arguments are passed to a , how return values are handled, and how the and registers are managed between the caller and the callee to ensure proper execution across language or module boundaries. This agreement is essential for binary compatibility, as it specifies details such as the order of argument pushing (typically right-to-left), the allocation of space, and the responsibility for cleanup. Common calling conventions vary by platform and compiler. The cdecl convention, the default for C and many Unix-like systems, pushes arguments onto the stack from right to left, with the caller responsible for cleaning the stack after the call, which supports variable-argument functions like printf. In contrast, the stdcall convention, widely used for Windows API functions, also pushes arguments right-to-left but requires the callee to clean the stack, reducing code size in the caller at the expense of flexibility for variable arguments. The fastcall convention optimizes performance by passing the first few arguments (typically two or four integers or pointers) in CPU registers (such as ECX and EDX on x86) before using the stack for additional parameters, with the caller handling stack cleanup; it is supported by compilers like Microsoft Visual C++ and GCC but varies in exact register usage. For Unix-like systems, the System V ABI specifies a standardized approach, particularly on x86-64, where the first six integer or pointer arguments are passed in registers (RDI, RSI, RDX, RCX, R8, R9) and floating-point arguments in XMM registers, with the stack used for excess parameters and aligned to 16 bytes; the caller cleans the stack. In FFI contexts, mismatches in calling conventions between the calling code and the target function can result in stack corruption, incorrect parameter passing, or program crashes due to improper usage or unbalanced stack operations. To mitigate this, FFI libraries and tools provide mechanisms to specify or emulate the appropriate convention; for example, Python's ctypes module uses CDLL for the cdecl convention and WinDLL for stdcall when loading shared libraries, ensuring compatibility with the target's ABI. Libraries like libffi abstract these differences by allowing developers to select the convention at , enabling portable invocation across platforms without recompilation.

Data Management

Type Mapping and Marshalling

Type mapping in foreign function interfaces (FFIs) establishes correspondences between data types in the host language and the foreign language to facilitate safe and correct data exchange during inter-language calls. For instance, in Haskell's FFI, basic types such as Int are mapped to C's int using the Foreign.C module, while fixed-size variants like Int32 ensure portability across platforms by corresponding to 32-bit integers regardless of the host architecture. Similarly, Rust's FFI with C uses the libc crate to map primitives like i32 directly to c_int and u8 to unsigned char, with pointers represented as raw *const T or *mut T types to match C's void*. These mappings often treat pointers from the foreign language as opaque handles in the host to avoid direct manipulation, preserving abstraction while allowing pass-through. Marshalling extends type mapping by serializing complex data structures, such as structs and arrays, into formats compatible with the foreign language's memory layout and (ABI). In Pharo's Unified FFI, structs are defined as subclasses of FFIStructure—for example, a C struct with int numerator; int denominator; maps to a Pharo object with generated accessors—enabling by-value or by-reference passing, where arrays within structs are handled as embedded FFIArray instances. The process accounts for requirements, automatically inserting padding bytes as per C standards (e.g., aligning an int after a char with 3 bytes of padding), though packed variants like FFIPackedStructure can eliminate this for dense layouts. Endianness considerations arise during marshalling of multi-byte types, where host and foreign systems may differ (e.g., little-endian x86 vs. big-endian PowerPC), necessitating explicit byte-order conversions in portable implementations to prevent . Common issues in type mapping and marshalling stem from architectural and representational differences between languages. Size variances, such as a 32-bit int in one language versus a 64-bit long in another, can lead to or if not addressed with explicit fixed-width types like int32_t from <stdint.h>. Signed/unsigned mismatches exacerbate this, where a signed C int interpreted as unsigned in the host might yield incorrect negative values due to bit-level reinterpretation, requiring careful declaration matching to avoid runtime errors. For variable-sized data like arrays or unions, buffers or opaque references are often used to encapsulate contents without exposing internal layouts, mitigating portability challenges across compilers and platforms. In garbage-collected languages interfacing with C, additional hurdles include boxing/unboxing overheads for scalars and ensuring stable representations for pointers during marshalling.

Memory Management

In foreign function interfaces (FFIs), memory management focuses on establishing clear rules for allocation, deallocation, and transfer across language boundaries to avoid leaks, dangling references, or invalid accesses. models typically specify whether the caller or callee handles lifecycle, with conventions documented in to guide implementers. For instance, libraries, often allocate resources and return pointers, implicitly transferring to the caller, who is then responsible for deallocation using a paired ; this pattern enables high-level languages to infer and automate cleanup through static of flows. In languages employing , such as certain bindings for or , counters are incremented on transfer and decremented on release to track shared safely. For garbage-collected languages like , bridges maintain object reachability, preventing premature collection while crossing boundaries. Common techniques prioritize and correctness. The copy-in/copy-out approach duplicates input data into the callee's before invocation and extracts outputs afterward, eliminating shared and disputes at the cost of duplication overhead. Shared memory pointers, conversely, allow direct access via raw addresses but require explicit transfer, often via conventions like passing allocation sizes or using opaque handles to signal lifetime boundaries. Callbacks introduce additional complexity, as they may invoke code across boundaries asynchronously; here, data referenced by the callback must remain valid, typically achieved by extending scopes or using persistent storage like static allocations until the callback completes. Platform-specific implementations adapt these models to runtime characteristics. In 's JNI, native code uses local references for short-lived access to Java objects, scoped to the current native frame, while long-lived access requires global references created via NewGlobalRef, which must be explicitly deleted with DeleteGlobalRef to release and avoid leaks. The modern Foreign Function and Memory API (FFM) shifts to scoped arenas, where native allocations are confined to a ResourceScope or , ensuring automatic deallocation upon closure without manual reference tracking. In C environments, management is fully manual, relying on malloc for allocation and for deallocation, with strictly following API documentation—such as the caller providing pre-allocated buffers to avoid transfer ambiguities. When marshalling pointers as part of type handling, their must align with these models to prevent invalid dereferences.

Implementations

Language-Specific Approaches

In , the includes the ctypes module, which facilitates foreign function interfaces by enabling dynamic loading of shared libraries and providing C-compatible data types for and calls without requiring of extension modules. As an alternative, the CFFI library offers a more performant approach for interacting with C code, using C-like declarations to generate bindings that can be faster than ctypes in scenarios involving frequent calls, particularly in out-of-line mode where C code is compiled ahead-of-time for direct calls without libffi overhead. Java implements foreign function interfaces through the (JNI), a standard API that allows Java code running in the (JVM) to call native methods in or libraries, establishing bridges via JNIEnv pointers for accessing JVM features and managing data types. Additionally, since Java 22 (finalized in March 2024), the Foreign Function & Memory API () provides a modern, standardized way to link and call native libraries directly, offering improved safety and performance over JNI for many use cases. In , foreign function interfaces emphasize safety through the language's ownership model, which helps prevent issues like memory leaks or data races during interop; the bindgen tool automates the generation of safe Rust wrappers for libraries by parsing header files and producing idiomatic bindings that respect Rust's borrow checker. In .NET, Platform Invoke (P/Invoke) enables managed code to call functions in unmanaged DLLs, with automatic marshaling for data types, structs, and callbacks, while handling differences in and calling conventions. In , the Foreign Function Interface (FFI) allows declaration of foreign imports and exports using syntax like foreign import ccall, integrating C functions into Haskell's with support for marshalling and safe wrappers via libraries like bindings-*. Other languages provide specialized support for FFIs. uses the to load dynamic libraries, bind functions, and invoke them from Ruby code with automatic type mapping. Go employs cgo, a integrated into the Go build system, to create packages that import C code as a pseudo-package, enabling seamless calls to C functions while handling garbage collection boundaries.

Libraries and Tools

Several libraries and tools have been developed to streamline the creation of foreign function interfaces, particularly by automating the generation of bindings from existing C or C++ codebases to higher-level languages. One prominent example is the Simplified Wrapper and Interface Generator (SWIG), which parses C/C++ header files to automatically produce wrapper code for integration with languages such as Python, Java, Perl, Ruby, and Tcl. SWIG supports features like type mapping for complex data structures, handling of callbacks from the target language back to C/C++, and the generation of documentation alongside the bindings, making it suitable for large-scale projects requiring multi-language support. For Python-specific interoperability with C libraries, serves as an that extends syntax to include C types and declarations, enabling the creation of efficient extension modules that act as bridges between code and C functions. facilitates header parsing and automatic generation of type-safe wrappers, including support for callbacks and hints to minimize overhead in performance-critical applications. Complementing , the C Foreign Function Interface (cffi) library allows direct interaction with C code using C-like declarations within , without requiring compilation of custom wrappers for simple cases, while offering ABI-level compatibility for precompiled libraries. cffi emphasizes through runtime checks and supports advanced features like variadic functions and callbacks, often used in scenarios where of shared libraries is preferred. In the context of WebAssembly, wasm-bindgen is a Rust-based tool and library that generates JavaScript bindings for WebAssembly modules, enabling seamless passing of high-level types such as strings, objects, and closures between JavaScript and Wasm code. It automates the creation of idiomatic JavaScript APIs from Rust exports, including support for asynchronous callbacks and error handling, which simplifies FFI across web environments. For the D programming language, the dub package manager integrates FFI workflows by managing dependencies on C libraries and automating builds for projects that use D's native extern(C) declarations to interface with external code. These tools collectively address common FFI challenges by providing header parsing, automated type-safe wrappers, and callback mechanisms, with language-specific integrations available in ecosystems like Python's scientific stack.

Challenges

Performance and Overhead

Foreign function interfaces (FFIs) introduce several sources of runtime overhead that can impact overall application . Marshalling data between incompatible type systems and memory representations across languages often requires copying or transformation, leading to significant computational costs, especially for complex structures like strings or arrays. Context switching between managed s (e.g., garbage-collected languages) and native code involves saving and restoring state, such as frames and registers, which adds ; in implementations like Go's cgo, this primarily involves low-ns switching overhead. Dynamic loading of foreign libraries at runtime incurs initial from resolving symbols and linking, typically on the order of microseconds to milliseconds depending on library size and system load. To mitigate these overheads, developers employ techniques like data transfer, where pointers or buffers are passed directly without duplication, reducing marshalling costs for large datasets. Inlining simple foreign calls—treating them as native via optimizations—eliminates transition overhead for trivial functions, as seen in low-level FFIs like LuaJIT's. tools, such as those integrated into language runtimes (e.g., Python's cProfile with CFFI extensions), help identify hotspots, enabling targeted optimizations like batching multiple calls to amortize setup costs. Benchmarks illustrate these impacts: in Python's CFFI for high-performance computing tasks, small data transfers show significant latency increases compared to native C due to translation overhead, but large transfers show negligible differences. Java's JNI exhibits approximately 20% slowdown for compute-intensive operations like Base64 decoding, attributable to marshalling and state transitions. For complex calls involving non-trivial data, overall slowdowns range from 10-50%, underscoring the need for careful design. A key in FFIs arises between and : enforcing bounds checking or memory isolation at the interface prevents errors like buffer overflows but introduces additional runtime costs. For instance, Rust's FFI with encapsulated safe wrappers achieves with minimal overhead, as demonstrated in various benchmarks, compared to unchecked calls, by limiting checks to boundary crossings rather than pervasive . This balance favors speed in performance-critical paths while preserving correctness, though it requires language-specific mechanisms to avoid excessive penalties.

Security and Safety Issues

Foreign function interfaces (FFIs) introduce significant security risks due to the inherent challenges in bridging disparate language runtimes and memory models, particularly when type mismatches occur between the calling and called languages. For instance, buffer overflows can arise when data passed through an FFI exceeds allocated bounds because of incompatible size assumptions, such as a C-style pointer being misinterpreted in a higher-level language without proper bounds checking. These mismatches often stem from unverified assumptions about data representation, leading to unintended memory corruption that attackers can exploit to execute arbitrary code. Injection attacks represent another critical in FFIs, especially when interfacing with untrusted foreign code from dynamic or scriptable libraries. In such scenarios, malformed inputs can be injected into the foreign function's execution context, allowing attackers to alter or execute malicious payloads if the FFI lacks robust . This risk is amplified in polyglot environments where foreign code from third-party sources bypasses the host language's boundaries. Privilege escalation poses a further in mixed-language systems facilitated by FFIs, as native code invocations can inadvertently grant elevated access to resources that the host language restricts. For example, an FFI call to a native might elevate privileges if the interface does not enforce the same model as the calling environment, enabling attackers to bypass restrictions or access sensitive system calls. Memory management pitfalls, such as dangling pointers across language boundaries, can exacerbate these escalations by allowing unauthorized data access. To mitigate these risks, developers employ safety measures like sandboxing, which isolates foreign code execution to prevent propagation of faults or exploits. provides a prominent example through its memory and fault mechanisms, ensuring that FFI interactions with host environments remain contained without direct access to resources. Input validation at the FFI boundary is equally essential, involving checks for data types and sizes to prevent mismatches; type-based s, such as those proposed for verifying foreign calls, automate much of this assurance. Additionally, safe bindings in languages like encapsulate unsafe FFI operations within verified wrappers, enforcing invariants like ownership and borrowing to avoid common pitfalls without exposing raw pointers to user code. Notable incidents underscore the real-world impact of FFI vulnerabilities. Historical exploits in the (JNI) have led to JVM breaches by leveraging memory corruption in native code, such as uninitialized instances or buffer overflows that allow within the trusted JVM context. Multi-language security patches reveal persistent vulnerabilities in polyglot applications involving FFIs.

Historical Development

Origins and Early Examples

The concept of foreign function interfaces (FFIs) originated in the early 1970s amid the development of system programming languages designed for interoperability with low-level code. BCPL, created by Martin Richards in the mid-1960s, influenced early efforts in cross-language interaction, but it was the evolution toward C—devised by Dennis Ritchie at Bell Labs between 1969 and 1973—that established foundational interop patterns for Unix. Early C implementations on the PDP-11 facilitated direct calls to assembly routines for system tasks, such as device I/O and memory management, enabling programs written in C to interface seamlessly with machine-specific code without full recompilation. This approach addressed the need for efficiency in resource-constrained environments, marking an initial step toward structured FFI mechanisms. By the 1980s, FFIs became more explicit in high-level languages seeking to leverage C's portability and system access. In Lisp implementations, particularly during the prelude to Common Lisp standardization (1980–1984), researchers at (CMU) and other institutions developed general foreign function call mechanisms to invoke C procedures from environments. These efforts, contemporaneous with the ORBIT compiler for , allowed inter-language procedure calls by integrating -specific optimizations with mainstream techniques, facilitating access to C libraries for performance-critical operations like numerical computations. Similarly, Smalltalk, originating at Xerox PARC in the early 1970s, incorporated primitive calls from its inception; Smalltalk-72 (1972) used "CODE" tokens followed by integers (e.g., CODE 51 for subtraction) to invoke approximately 50 native routines for arithmetic, graphics, and I/O, directly interfacing with hardware like the via . By Smalltalk-76 (1976), these evolved into explicit "primitive:" declarations in methods, enabling fallback to Smalltalk code if native calls failed, and supporting system library interactions for tasks such as bit-block transfers (BitBlt). A key milestone in FFI portability occurred in the late with the introduction of dynamic linking in systems, exemplified by 4.0's dlopen interface in 1988. This allowed runtime loading of shared object files (e.g., .so libraries) and symbol resolution via functions like dlsym, decoupling applications from static linking and enabling modular extensions in C and compatible languages. These innovations built on earlier Unix dynamic loading concepts but provided a standardized runtime mechanism for FFI. Standardization efforts in the culminated in POSIX.1-2001, which formally specified dlopen, dlclose, dlsym, and dlerror for portable dynamic linking across Unix variants, ensuring consistent behavior for inter-language calls in multi-vendor environments.

Modern Evolution

In the 2000s, the rise of scripting languages spurred innovations in FFIs tailored for dynamic environments, enabling seamless integration with C libraries without extensive boilerplate. Python's ctypes module, initially released as a third-party library in 2003 by Thomas Heller, provided a straightforward way to load shared libraries and call C functions directly from Python code using compatible data types. This approach gained prominence when ctypes was incorporated into Python's standard library with version 2.5 in 2006, simplifying foreign calls and reducing reliance on tools like . Similarly, the Ruby FFI gem, first released in 2008, extended these capabilities to Ruby by allowing programmatic loading of dynamic libraries and binding functions, fostering easier extension of Ruby applications with native code. Java's (JNI), established earlier in 1997, matured during this decade through JVM optimizations and enhanced tooling in JDK releases like 1.5 (2004), which improved performance for native interactions and supported broader enterprise adoption. The and early introduced paradigms emphasizing safety, portability, and cross-platform compatibility in FFIs, driven by the growth of web and . , announced in 2015 and first shipped in March 2017, established the wasm32 (ABI) to enable secure, high-performance foreign function calls within browsers, allowing compiled languages like C++ and to interoperate with without risks. , reaching stable release 1.0 in 2015, integrated FFI support from its inception, leveraging ownership and borrowing rules to ensure across language boundaries when calling C code via extern blocks. Go's cgo mechanism, available since Go 1.0 in 2012, saw significant enhancements in the and , including better cross-compilation support and, in Go 1.24 (February 2025), new C function annotations like #cgo noescape to optimize runtime performance and reduce overhead in mixed Go-C programs. These developments addressed longstanding FFI challenges in concurrent and distributed systems. By the mid-2020s, FFIs evolved to support emerging domains like and , filling interoperability gaps with standardized and system interfaces. 's C , introduced in 2015 and refined through subsequent releases, serves as a core wrapper for foreign function bindings, enabling languages like and to invoke operations via simple C-compatible calls for model inference and training. In quantum computing, bridges such as QisDAX (developed around 2023) provide FFI-like interfaces between high-level frameworks like and hardware-specific abstractions for trapped-ion devices, facilitating transpilation and execution of quantum circuits. Additionally, the System Interface (WASI), evolving from its 2019 preview to version 0.2 in 2023 and beyond, extended wasm32 capabilities to non-web environments by defining portable system calls, thus enabling secure FFIs for serverless and up to 2025.

References

  1. [1]
    [PDF] IMPROVING QUALITY OF SOFTWARE WITH FOREIGN FUNCTION ...
    A Foreign Function Interface (FFI) is a mechanism that allows software written in one host programming language to directly use another foreign programming ...
  2. [2]
  3. [3]
    Introduction
    ### Definition and Purpose of JNI
  4. [4]
    Platform Invoke (P/Invoke) - .NET - Microsoft Learn
    May 10, 2024 · P/Invoke is a technology that allows you to access structs, callbacks, and functions in unmanaged libraries from your managed code.
  5. [5]
    Chapter 8 Foreign Function Interface - Haskell.org
    The Foreign Function Interface (FFI) has two purposes: it enables (1) to describe in Haskell the interface to foreign language functionality and (2) to use from ...
  6. [6]
    Checking type safety of foreign function calls - ACM Digital Library
    ... programming errors. In this article, we study the problem of enforcing type ... Foreign Function Interface between Coq and CProceedings of the ACM on ...Abstract · Information & Contributors · Cited By
  7. [7]
    libffi - Sourceware
    A foreign function interface is the popular name for the interface that allows code written in one language to call code written in another language. The libffi ...
  8. [8]
    [PDF] A modular foreign function interface
    A modular foreign function interface. Jeremy Yallop, David Sheets and Anil Madhavapeddy. Docker, Inc, and. University of Cambridge Computer Laboratory. Abstract.
  9. [9]
    [PDF] Reasoning About Foreign Function Interfaces Without Modelling the ...
    A foreign function interface (FFI) is a framework in which code written in one language (called the host language) may call code written in another language ( ...
  10. [10]
    Rust FFI and bindgen: Integrating Embedded C Code in Rust
    Jan 16, 2023 · In this post, FFI is explained and a step by step tutorial is provided going over an example creating Rust interfaces for the C-based STM32 HAL libraries.
  11. [11]
    Polyglot FFI Documentation
    Welcome to Polyglot FFI! This tool automatically generates FFI (Foreign Function Interface) bindings between programming languages, eliminating the tedious ...
  12. [12]
    1. Extending Python with C or C++ — Python 3.14.0 documentation
    These modules let you write Python code to interface with C code and are more portable between implementations of Python than writing and compiling a C ...2. Defining Extension Types · Extensions · Parsing arguments
  13. [13]
    FFI Library - LuaJIT
    The FFI library allows calling external C functions and using C data structures from pure Lua code. The FFI library largely obviates the need to write ...
  14. [14]
    The Racket Foreign Interface
    Furthermore, since most APIs consist mostly of functions, the foreign interface is sometimes called a foreign function interface, abbreviated FFI. 1 ...Missing: origin | Show results with:origin
  15. [15]
    Does Java 18 finally have a better alternative to JNI? - Okta Developer
    Apr 8, 2022 · A foreign function interface is the ability to call functions or ... The term originated from common LISP, but it's known by different ...
  16. [16]
    12 Foreign Language Interface - SWI-Prolog
    Foreign Language Interface ... So we have two neglected issues by the ISO core standard, multi-threading and foreign function interface, and of course all ...
  17. [17]
    32.3. The Foreign Function Call Facility - CLISP - SourceForge
    This facility, also known as “Foreign Language Interface ... All symbols relating to the foreign function interface are exported from the package “FFI”.
  18. [18]
    External Function Interface - Manmrk +-------------------------------------+
    External Function Interface Functions. The following sections explain the functions for registering and using external functions. RexxRegisterFunctionDll.
  19. [19]
    [PDF] An OpenModelica Java External Function Interface Supporting ...
    An OpenModelica Java External Function Interface. Supporting MetaProgramming. Martin Sjölund, Peter Fritzson. PELAB Programming Environment Lab, Dept.
  20. [20]
    Native interoperability ABI support - .NET - Microsoft Learn
    May 27, 2025 · The Java Virtual Machine (JVM) defines a foreign function interface (FFI) in C to interoperate with other platforms. Interoperability ...Missing: Invoke | Show results with:Invoke
  21. [21]
    Introduction (libffi: the portable foreign function interface library)
    The ' libffi ' library provides a portable, high level programming interface to various calling conventions. This allows a programmer to call any function ...
  22. [22]
    12 Foreign Function and Memory API - Java - Oracle Help Center
    The Foreign Function and Memory (FFM) API enables Java programs to interoperate with code and data outside the Java runtime. This API enables Java programs ...
  23. [23]
    About the Common Object Request Broker Architecture Specification Version 3.0
    ### Summary of CORBA from https://www.omg.org/spec/CORBA/3.0/About-CORBA
  24. [24]
    Remote Procedure Calls vs. Local Procedure Calls - Baeldung
    Mar 18, 2024 · In this tutorial, we'll discuss two popular procedure calls: local and remote. We'll also explore the core differences between them.Missing: FFI | Show results with:FFI
  25. [25]
    Simplified Wrapper and Interface Generator
    ### Summary of SWIG and its Relation to FFI and Bindings
  26. [26]
    A modular foreign function interface - ScienceDirect.com
    Oct 15, 2018 · We propose a modular approach to binding foreign functions that separates description from mechanism.
  27. [27]
    C interop using dart:ffi
    Sep 15, 2025 · FFI stands for foreign function interface. Other terms for similar functionality include native interface and language bindings. API ...
  28. [28]
    The challenge of building a Foreign Function Interface
    Dec 21, 2018 · A Foreign Function Interface (FFI) is a mechanism for one programming language to make use of another programming language, usually C.<|separator|>
  29. [29]
    dlopen
    ### Summary of dlopen Function
  30. [30]
    [PDF] Foreign-Function Interfaces for Garbage-Collected Programming ...
    A foreign-function interface provides a high-level lan- guage with access to low-level programming languages and negoti- ates between the inside and the outside ...
  31. [31]
    LoadLibraryA function (libloaderapi.h) - Win32 apps - Microsoft Learn
    Feb 9, 2023 · LoadLibrary can be used to load a library module into the address space of the process and return a handle that can be used in GetProcAddress to ...Missing: FFI | Show results with:FFI
  32. [32]
  33. [33]
    GetProcAddress function (libloaderapi.h) - Win32 apps
    Feb 6, 2024 · Retrieves the address of an exported function (also known as a procedure) or variable from the specified dynamic-link library (DLL).Missing: FFI | Show results with:FFI
  34. [34]
    [PDF] Calling conventions - Agner Fog
    Feb 1, 2023 · The System V ABI for. 64-bit Unix systems requires alignment by 32. The System V ABI for 32-bit Unix does not mention __m256, but tests show ...
  35. [35]
    __cdecl | Microsoft Learn
    Aug 3, 2021 · The __cdecl calling convention creates larger executables than __stdcall, because it requires each function call to include stack cleanup code.
  36. [36]
    __stdcall | Microsoft Learn
    Feb 10, 2025 · The __stdcall calling convention is used to call Win32 API functions. The callee cleans the stack, so the compiler makes vararg functions __cdecl.Syntax · Remarks
  37. [37]
    __fastcall | Microsoft Learn
    Sep 15, 2023 · The __fastcall calling convention specifies that arguments to functions are to be passed in registers, when possible.
  38. [38]
    [PDF] System V Application Binary Interface - x86-64
    Sep 13, 2002 · function.5 If a calling function wants to preserve such a register value across a function call, it must save the value in its local stack frame ...
  39. [39]
    FFI - The Rustonomicon - Rust Documentation
    Foreign Function Interface. Introduction. This guide will use the snappy compression/decompression library as an introduction to writing bindings for foreign ...Missing: history | Show results with:history<|separator|>
  40. [40]
    [PDF] Unified FFI - Calling Foreign Functions from Pharo
    Feb 12, 2020 · A Foreign Function Interface (FFI) is a programming language mechanism that allows software written in one language to use resources ...
  41. [41]
    [PDF] Analyzing Memory Ownership Patterns in C Libraries - cs.wisc.edu
    A key aspect of the ownership model is recognizing which library functions transfer ownership of resources; this allows the high-level language run-time system ...
  42. [42]
    Chapter 4: JNI Functions
    ... JNI functions NewLocalRef or NewGlobalRef . ... The other options give the programmer more control over memory management and should be used with extreme care.
  43. [43]
    JEP 454: Foreign Function & Memory API - OpenJDK
    Jun 22, 2023 · JEP 454 introduces an API for Java to interact with code and data outside the JVM, enabling control of foreign memory and calling foreign ...
  44. [44]
    Java Native Interface< (JNI)
    Java Native Interface (JNI) is a standard programming interface for writing Java native methods and embedding the Java virtual machine into native applications.
  45. [45]
    Introduction - The bindgen User Guide
    bindgen automatically generates Rust FFI bindings to C and C++ libraries. For example, given the C header cool.h.Add bindgen as a Build... · Requirements · Library Usage with build.rs · Allowlisting
  46. [46]
    Ruby FFI - GitHub
    Ruby-FFI is a gem for programmatically loading dynamically-linked native libraries, binding functions within them, and calling those functions from Ruby code.Issues 133 · Pull requests 26 · Security · Actions
  47. [47]
    cgo command - cmd/cgo - Go Packages
    Cgo enables the creation of Go packages that call C code. Using cgo with the go command ¶. To use cgo write normal Go code that imports a pseudo-package "C" ...
  48. [48]
    Simplified Wrapper and Interface Generator
    SWIG is a software development tool that connects programs written in C and C++ with a variety of high-level programming languages. SWIG is used with different ...Tutorial · Documentation · Survey · SWIG Features
  49. [49]
    SWIG Documentation, Presentations, and Papers
    In this tutorial, the creator of SWIG gives the inside story on what SWIG is, how it works, and how it is put together - PyCon March 2008. Interfacing C/C++ and ...
  50. [50]
    Cython: C-Extensions for Python
    Cython is an optimising static compiler for both the Python programming language and the extended Cython programming language (based on Pyrex).About Cython · Support Cython! · DocumentationMissing: interop | Show results with:interop
  51. [51]
    Interfacing with External C Code - Cython's Documentation
    Just as a Cython module can be used as a bridge to allow Python code to call C code, it can also be used to allow C code to call Python code. External ...Missing: interop | Show results with:interop
  52. [52]
    CFFI documentation — CFFI 2.0.0 documentation
    C Foreign Function Interface for Python. Interact with almost any C code from Python, based on C-like declarations that you can often copy-paste from header ...Documentation · CFFI 1.15.1 documentation · CFFI 1.14.6 documentation · Overview
  53. [53]
    Introduction - The `wasm-bindgen` Guide - Rust and WebAssembly
    Introduction. This book is about wasm-bindgen , a Rust library and CLI tool that facilitate high-level interactions between Wasm modules and JavaScript.
  54. [54]
    Intro to DUB - DUB Documentation
    DUB is the official package manager for the D programming language, providing simple and configurable cross-platform builds. DUB is well integrated in various ...Missing: FFI support
  55. [55]
    DUB package registry - D Programming Language
    Lyla is a simple, stable ORM for D using C APIs for SQLite/PostgreSQL. No metaprogramming, no extra dependencies—just direct, predictable database mapping.Missing: FFI | Show results with:FFI
  56. [56]
    Secure by Design Alert: Eliminating Buffer Overflow Vulnerabilities
    Feb 12, 2025 · Buffer overflow vulnerabilities are a prevalent type of memory safety software design defect that regularly lead to system compromise. The ...
  57. [57]
    Resolving Type Mismatch in Rust Interoperability Issues - MoldStud
    Apr 17, 2025 · Ensure that fields are ordered the same way, have matching types, and utilize the same calling conventions. Utilize FFI (Foreign Function ...<|control11|><|separator|>
  58. [58]
    Software Vulnerability Analysis Across Programming Language and ...
    Mar 26, 2025 · Syscall fuzzing identifies privilege escalation cases when memory is modified between fetches. Hybrid analysis: Hybrid techniques integrate data ...
  59. [59]
    [PDF] Securing Mixed Rust with Hardware Capabilities - NUS Computing
    In this work, our goal is to create a system that can detect run- time violations of Rust principles in mixed Rust code, which consists of both safe and unsafe ...
  60. [60]
    [PDF] pkru-safe-automatically-locking-down-the-heap-between ... - SciSpace
    Apr 8, 2022 · We present PKRU-Safe, the first intra-process isolation scheme for heap data in mixed-language environments that does not require OS ...
  61. [61]
    Security - WebAssembly
    WebAssembly security uses sandboxing, fault isolation, control-flow integrity, and protected call stacks. It aims to protect users and provide safe development ...Missing: FFI | Show results with:FFI
  62. [62]
    [PDF] Provably-Safe Multilingual Software Sandboxing using WebAssembly
    We review software-fault isolation (Section 2.1) and Wasm. (Section 2.2), before discussing Wasm's unique suitability for multi-lingual, cross-platform ...<|separator|>
  63. [63]
    [PDF] Checking Type Safety of Foreign Function Calls
    Abstract. We present a multi-lingual type inference system for checking type safety across a foreign function interface. The goal of our system is.<|control11|><|separator|>
  64. [64]
    Type-based input validation assurance in Rust FFI
    Executive summary: We propose to explore using types in operating system source code as a mean to get assurance on security properties.
  65. [65]
    [PDF] Exploiting Memory Corruption Vulnerabilities in the Java Runtime
    Dec 15, 2011 · The existence of a working exploit for a particular vulnerability removes the ambiguity of whether or not it could actually be exploited.Missing: breaches | Show results with:breaches
  66. [66]
    [PDF] Safe Java Native Interface - cs.Princeton
    An exploitable vulnerability in the. JVM. not allow our exploit to work. However, when given the right security privileges, we believe that our exploit can en-.Missing: historical breaches
  67. [67]
    [PDF] An Empirical Study of Multi-Language Security Patches in Open ...
    Abstract. Vulnerabilities in software repositories written in multiple programming languages present a major challenge to modern software.
  68. [68]
  69. [69]
    [PDF] The Evolution of Lisp - Dreamsongs
    and elsewhere to develop general “foreign function call” mechanisms for Common Lisp.) 2.9 Prelude to Common Lisp: 1980–1984. In the Spring of 1981, the ...
  70. [70]
    [PDF] The Evolution of Smalltalk
    Primitive behavior was invoked by the token CODE followed by an integer; this. Proc. ACM Program. Lang., Vol. 4, No. HOPL, Article 85. Publication date: June ...
  71. [71]
    Dynamic linking best practices - begriffs.com
    Jul 4, 2021 · The design typically used nowadays for dynamic linking (in BSD, MacOS, and Linux) came from SunOS in 1988. The paper Shared Libraries in SunOS ...Missing: 1980s | Show results with:1980s
  72. [72]
    dlopen
    The dlopen() function shall make the symbols (function identifiers and data object identifiers) in the executable object file specified by file available to ...Missing: origins | Show results with:origins
  73. [73]
    Ctypes — SciPy Cookbook documentation - Read the Docs
    May 5, 2006 · ctypes is an advanced Foreign Function Interface package for Python 2.3 and higher. It is included in the standard library for Python 2.5.
  74. [74]
    Install TensorFlow for C
    TensorFlow provides a C API that can be used to build bindings for other languages. The API is defined in c_api.h and designed for simplicity and uniformity.
  75. [75]
    [PDF] An Open Source Bridge from Qiskit to Trapped-Ion Quantum Devices
    QisDAX is a bridge between Qiskit and DAX, providing interfaces for Qiskit programs and transpiling them to the DAX abstraction.Missing: foreign | Show results with:foreign