infix is a modern, lightweight C library that lets you call any C function or create C callbacks at runtime, using simple, human-readable strings to describe the function's signature.
It's designed to be the simplest way to add a dynamic Foreign Function Interface (FFI) to your project, whether you're building a language runtime, a plugin system, or just need to call functions from a dynamically loaded library.

Key Features
- Human-Readable Signatures: Describe complex C functions with an intuitive string format (e.g.,
"({double, double}, int) -> *char").
- Forward & Reverse Calls: Call C functions ("forward") and create C function pointers that call back into your code ("reverse").
- Simple Integration: Add a single C file and a header directory to your project to get started. No complex dependencies.
- Type Registry: Define, reuse, and link complex, recursive, and mutually-dependent structs by name.
- Security-First Design: Hardened against vulnerabilities with Write XOR Execute (W^X) memory, guard pages, and fuzz testing.
- High Performance: A Just-in-Time (JIT) compiler generates optimized machine code trampolines, making calls nearly as fast as a direct C call after the initial setup.
Full Documentation
How It Works: A Quick Example
The heart of infix is its signature string. Here’s how you would call a simple C function:
#include <stdio.h>
int add(
int a,
int b) {
return a + b; }
const char* signature = "(int, int) -> int";
int a = 10, b = 32;
void*
args[] = { &a, &b };
int result;
printf("Result: %d\n", result);
return 0;
}
void * args[]
Definition 202_in_structs.c:64
int main(void)
Definition 821_threading_bare.c:81
static int add(int a, int b)
Definition Ch04_ThreadSafety.c:25
void(* infix_cif_func)(void *, void **)
A function pointer type for a bound forward trampoline.
Definition infix.h:371
c23_nodiscard infix_status infix_forward_create(infix_forward_t **, const char *, void *, infix_registry_t *)
Creates a "bound" forward trampoline from a signature string.
Definition trampoline.c:919
c23_nodiscard infix_cif_func infix_forward_get_code(infix_forward_t *)
Gets the callable function pointer from a bound forward trampoline.
Definition trampoline.c:288
void infix_forward_destroy(infix_forward_t *)
Destroys a forward trampoline and frees all associated memory.
Definition trampoline.c:523
The public interface for the infix FFI library.
Internal definition of a forward trampoline handle.
Definition infix_internals.h:94
Creating Callbacks
infix can also generate native C function pointers that call back into your code. This is perfect for interfacing with C libraries that expect callbacks, like qsort.
#include <stdlib.h>
int compare_integers(const void* a, const void* b) {
return (*(const int*)a - *(const int*)b);
}
void run_qsort_example() {
const char* cmp_sig = "(*void, *void) -> int";
int numbers[] = { 5, 1, 4, 2, 3 };
qsort(numbers, 5, sizeof(int), my_comparator);
}
c23_nodiscard infix_status infix_reverse_create_callback(infix_reverse_t **, const char *, void *, infix_registry_t *)
Creates a type-safe reverse trampoline (callback).
Definition trampoline.c:932
c23_nodiscard void * infix_reverse_get_code(const infix_reverse_t *)
Gets the native, callable C function pointer from a reverse trampoline.
Definition trampoline.c:813
void infix_reverse_destroy(infix_reverse_t *)
Destroys a reverse trampoline and frees all associated memory.
Definition trampoline.c:794
Internal definition of a reverse trampoline (callback/closure) handle.
Definition infix_internals.h:121
Getting Started
The easiest way to use infix is to add its source directly to your project.
- Copy the
src/ and include/ directories into your project.
- Add
src/infix.c to your build system's list of source files.
- Add the
include/ directory to your include paths.
#include <infix/infix.h> in your code.
For more advanced build options, including building as a standalone library with CMake or xmake, see the Building and Integration Guide.
Project Philosophy
infix is built on three core principles:
- Security First: An FFI library with a JIT is a prime target for vulnerabilities. We defend against these with a multi-layered approach, including strict W^X memory, hardened integer arithmetic, and continuous fuzz testing.
- Performance by Design: FFI overhead should be minimal.
infix separates the one-time generation cost from the near-zero call-time cost, making it exceptionally fast in high-performance applications when trampolines are cached.
- Simplicity and Portability: Platform- and ABI-specific logic is strictly isolated, making the library easy to maintain, simple to integrate, and straightforward to port to new architectures.
Platform Support
infix is rigorously tested on a wide array of operating systems, compilers, and architectures with every commit.
| OS | Version | Architecture | Compiler | Status |
| DragonflyBSD | 6.4.0 | x86-64 | GCC | |
| FreeBSD | 14.3 | x86-64 | GCC | |
| 14.3 | AArch64 | GCC | |
| 14.3 | x86-64 | Clang | |
| 14.3 | AArch64 | Clang | |
| macOS | Sequoia | AArch64 | Clang | |
| Sequoia | AArch64 | GCC | |
| NetBSD | 10.1 | AArch64 | GCC | |
| 10.1 | x86-64 | GCC | |
| OmniOS | r151052 | x86-64 | GCC | |
| OpenBSD | 7.7 | AArch64 | Clang | |
| 7.7 | AArch64 | GCC | |
| 7.7 | x86-64 | Clang | |
| 7.7 | x86-64 | Clang | |
| Solaris | 11.4 | x86-64 | GCC | |
| Ubuntu | 24.04 | AArch64 | Clang | |
| 24.04 | AArch64 | GCC | |
| 24.04 | x86-64 | Clang | |
| 24.04 | x86-64 | GCC | |
| Windows | Server 2025 | AArch64 | Clang | |
| Server 2025 | AArch64 | GCC | |
| Server 2025 | AArch64 | MSVC | |
| Server 2025 | x86-64 | Clang | |
| Server 2025 | x86-64 | GCC | |
| Server 2025 | x86-64 | MSVC | |
In addition to the CI platforms tested here on Github, I can verify infix builds and passes unit tests on Android/Termux.
Licenses
To maximize usability for all, infix is dual-licensed under the [Artistic License 2.0](LICENSE-A2) and the [MIT License](LICENSE-MIT). You may choose to use the code under the terms of either license.
At your discretion, all standalone documentation (.md), explanatory text, Doxygen-style documentation blocks, comments, and code examples contained within this repository may be used, modified, and distributed under the terms of the [Creative Commons Attribution 4.0 International License (CC BY 4.0)](LICENSE-CC). I encourage you to share and adapt the documentation for any purpose (generating an API reference website, creating tutorials, etc.), as long as you give appropriate credit.