infix
A JIT-Powered FFI Library for C
Loading...
Searching...
No Matches
<tt>infix</tt> API Quick Reference

This document provides a concise reference for the public API of the infix library. It's designed to be a quick lookup for developers who are already familiar with the library's concepts.

For practical, in-depth examples, please see the Cookbook.

Table of Contents

  • 1. High-Level Signature API
    • Forward Trampolines (Calling C)
    • Reverse Trampolines (Callbacks & Closures)
  • 2. Error Handling API
    • The Error Handling Pattern
    • Common Error Categories
  • 3. Introspection API
    • Getting Callable Code
    • Inspecting Trampoline Properties
    • Inspecting Type Properties
  • 4. Named Type Registry API
    • Creation and Population
    • Registry Introspection & Iteration
  • 5. Dynamic Library & Globals API
  • 6. Manual API (Advanced)
    • Manual Trampoline Creation
    • Manual Type Creation
  • 7. Memory Management (Arenas)

1. High-Level Signature API

These are the primary, recommended functions for creating trampolines from human-readable signature strings.

Forward Trampolines (Calling C)

<tt>infix_forward_create</tt>

Creates a high-performance "bound" trampoline compiled for a specific C function. This is the fastest way to call the same function repeatedly. This function creates a private memory arena for the trampoline and performs a deep copy of all type metadata, ensuring it is a self-contained object.

infix_forward_t** out_trampoline,
const char* signature,
void* target_function,
);
infix_registry_t * registry
Definition 008_registry_introspection.c:35
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
infix_status
Enumerates the possible status codes returned by infix API functions.
Definition infix.h:389
Internal definition of a forward trampoline handle.
Definition infix_internals.h:94
Internal definition of a named type registry.
Definition infix_internals.h:175

<tt>infix_forward_create_unbound</tt>

Creates a more flexible "unbound" trampoline for a given signature. The target function is provided at call time, allowing you to reuse one trampoline for multiple functions with the same signature. Like infix_forward_create, this function creates a private arena for the trampoline.

infix_forward_t** out_trampoline,
const char* signature,
);
c23_nodiscard infix_status infix_forward_create_unbound(infix_forward_t **, const char *, infix_registry_t *)
Creates an "unbound" forward trampoline from a signature string.
Definition trampoline.c:926

<tt>infix_forward_create_in_arena</tt> (Advanced)

Creates a "bound" forward trampoline that allocates its internal metadata from a user-provided arena. When the target_arena is the same one used by a registry, this function will share pointers to named types instead of deep-copying them, significantly saving memory and improving creation performance.

infix_forward_t** out_trampoline,
infix_arena_t* target_arena,
const char* signature,
void* target_function,
);
c23_nodiscard infix_status infix_forward_create_in_arena(infix_forward_t **, infix_arena_t *, const char *, void *, infix_registry_t *)
Creates a "bound" forward trampoline within a user-provided arena.
Definition trampoline.c:832
Internal definition of a memory arena.
Definition infix_internals.h:146

Reverse Trampolines (Callbacks & Closures)

<tt>infix_reverse_create_callback</tt>

Creates a reverse trampoline for a type-safe C function. This is the easiest way to create a callback for a C library like qsort. This function creates a private memory arena for the callback context.

infix_reverse_t** out_context,
const char* signature,
void* user_callback_fn,
);
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
Internal definition of a reverse trampoline (callback/closure) handle.
Definition infix_internals.h:121

<tt>infix_reverse_create_closure</tt>

Creates a reverse trampoline with a generic handler. This is the ideal choice for creating stateful callbacks or for language bindings, as it gives you low-level control and a user_data pointer to maintain state. This function creates a private memory arena for the closure context.

infix_reverse_t** out_context,
const char* signature,
infix_closure_handler_fn user_callback_fn,
void* user_data,
);
c23_nodiscard infix_status infix_reverse_create_closure(infix_reverse_t **, const char *, infix_closure_handler_fn, void *, infix_registry_t *)
Creates a generic reverse trampoline (closure) for stateful callbacks.
Definition trampoline.c:962
void(* infix_closure_handler_fn)(infix_context_t *, void *, void **)
A function pointer type for a generic closure handler.
Definition infix.h:384

2. Error Handling API

Error handling in infix is designed to be both detailed and thread-safe. All detailed error information is stored in thread-local storage, so an error in one thread won't affect another.

The Error Handling Pattern

The basic pattern is to always check the infix_status return value of an API function. If it's anything other than INFIX_SUCCESS, you can get more details.

infix_error_details_t infix_get_last_error(void)
Retrieves detailed information about the last error that occurred on the current thread.
Definition error.c:270
Provides detailed, thread-local information about the last error that occurred.
Definition infix.h:1360

This function returns a copy of an infix_error_details_t struct, which contains everything you need to know about what went wrong:

  • category: A high-level category like INFIX_CATEGORY_PARSER.
  • code: A specific error code like INFIX_CODE_UNEXPECTED_TOKEN.
  • position: For parser errors, the exact character position in the signature string where the error occurred.
  • message: A detailed, human-readable error message.

Common Error Categories

Parser Errors (<tt>INFIX_CATEGORY_PARSER</tt>)

What it means: There is a syntax error in a signature string you provided. How to handle: This is the most common type of error. You can use the position and message from the error details to provide a rich diagnostic to the user, much like a compiler would.

// Example: Handling a parser error
infix_status status = infix_type_from_signature(&type, &arena, "{int, ^double}", NULL);
fprintf(stderr, "Error parsing signature:\n");
fprintf(stderr, " %s\n", "{int, ^double}");
fprintf(stderr, " %*s^\n", (int)err.position, ""); // Print a caret
fprintf(stderr, "Details: %s\n", err.message);
}
infix_arena_t * arena
Definition 005_layouts.c:68
infix_status status
Definition 103_unions.c:66
size_t position
Definition infix.h:1363
c23_nodiscard infix_status infix_type_from_signature(infix_type **, infix_arena_t **, const char *, infix_registry_t *)
Parses a signature string representing a single data type.
Definition signature.c:1026
char message[256]
Definition infix.h:1365
@ INFIX_SUCCESS
Definition infix.h:390

Allocation Errors (<tt>INFIX_CATEGORY_ALLOCATION</tt>)

What it means: The library failed to allocate memory, either from the standard heap (malloc) or from the OS for executable JIT code (mmap/VirtualAlloc). This usually means the system is out of memory. How to handle: There is often little you can do to recover. The best course of action is to log the error and terminate the process gracefully.

ABI & Layout Errors (<tt>INFIX_CATEGORY_ABI</tt>)

What it means: This is a more subtle category of error related to the function's structure.

  • You used a named type (e.g., @Point) in a signature but didn't provide a registry, or the name wasn't found.
  • You tried to create an invalid type, like a struct containing a void member.
  • A type was too large or complex for the target architecture's ABI to handle (e.g., a struct larger than the maximum safe stack allocation size). How to handle: Double-check your signature strings and type definitions in the registry. Ensure you are passing the correct registry handle to the creation function.

General & Library Errors

What it means: This is a catch-all for other issues.

  • You passed an invalid argument to an API function (e.g., NULL where a valid pointer was required).
  • When using the dynamic library API, the requested library (.so, .dll) could not be found or a symbol lookup failed. How to handle: For library errors, ensure the shared library file is in the expected location (e.g., the current directory, or a system path). For other errors, review the arguments you are passing to the infix function call.

3. Introspection API

Functions for inspecting the properties of trampolines and types at runtime.

Getting Callable Code

Inspecting Trampoline Properties

These functions work for both infix_forward_t* and infix_reverse_t* handles.

*(Note: The infix_reverse_* variants have the same function signatures.)*

Inspecting Type Properties


4. Named Type Registry API

APIs for defining, storing, reusing, and inspecting complex types by name.

Creation and Population

Registry Introspection & Iteration

These functions allow you to iterate through all of the fully defined types within a registry.


5. Dynamic Library & Globals API

Cross-platform functions for loading shared libraries and accessing exported symbols.


6. Manual API (Advanced)

A lower-level API for creating trampolines from programmatically-built infix_type objects, bypassing the string parser.

Manual Trampoline Creation

These functions mirror the high-level API but take infix_type objects instead of signature strings.

  • infix_status infix_forward_create_manual(...)
  • infix_status infix_forward_create_unbound_manual(...)
  • infix_status infix_reverse_create_callback_manual(...)
  • infix_status infix_reverse_create_closure_manual(...)

Manual Type Creation

These functions are the building blocks for creating infix_type objects programmatically. All new types must be allocated from a user-provided arena.

  • infix_type* infix_type_create_primitive(infix_primitive_type_id id): Returns a static descriptor for a primitive type like int or double. Does not require an arena.
  • infix_type* infix_type_create_pointer(void): Returns a static descriptor for a generic void*. Does not require an arena.
  • infix_type* infix_type_create_void(void): Returns the static descriptor for void. Does not require an arena.
  • infix_status infix_type_create_pointer_to(infix_arena_t* arena, ...): Creates a new pointer type that points to a specific other type.
  • infix_status infix_type_create_struct(infix_arena_t* arena, ...): Creates a new struct, automatically calculating member offsets and padding.
  • infix_status infix_type_create_packed_struct(infix_arena_t* arena, ...): Creates a struct with a user-specified size, alignment, and member offsets.
  • infix_status infix_type_create_union(infix_arena_t* arena, ...): Creates a new union, calculating its size and alignment based on its members.
  • infix_status infix_type_create_array(infix_arena_t* arena, ...): Creates a new fixed-size array type.
  • infix_status infix_type_create_enum(infix_arena_t* arena, ...): Creates a new enum type with a specified underlying integer type.
  • infix_status infix_type_create_complex(infix_arena_t* arena, ...): Creates a new C99 _Complex number type.
  • infix_status infix_type_create_vector(infix_arena_t* arena, ...): Creates a new SIMD vector type.
  • infix_status infix_type_create_named_reference(infix_arena_t* arena, ...): Creates a placeholder for a named type that will be resolved by a registry.
  • infix_struct_member infix_type_create_member(...): A factory function to create a member object for use with infix_type_create_struct or _union.

7. Memory Management (Arenas)

APIs for the fast, region-based arena allocator used by the Manual API. The internal arena implementation supports chaining to grow as needed, so you do not need to worry about the initial size for most use cases.