info > L(1)

๐Ÿ“š libffi

๐Ÿš€ Quick Reference

Use CaseCommandDescription
๐ŸŽฏ Prepare a call interfaceffi_prep_cif(cif, abi, nargs, rtype, argtypes)Initializes a ffi_cif for calling a function with fixed args
๐ŸŽฏ Prepare a variadic call interfaceffi_prep_cif_var(cif, abi, nfixed, ntotal, rtype, argtypes)Initializes a ffi_cif for a variadic function call
๐Ÿ“ž Call a functionffi_call(cif, fn, rvalue, avalues)Invokes the function described by cif
๐Ÿ”’ Allocate closure memoryffi_closure_alloc(size, &code)Allocates writable+executable memory for a closure
๐Ÿ”’ Free closure memoryffi_closure_free(writable)Frees memory allocated by ffi_closure_alloc
๐Ÿ”’ Prepare a closure functionffi_prep_closure_loc(closure, cif, fun, user_data, codeloc)Prepares a closure that can be called as a function
๐Ÿ“ Get struct member offsetsffi_get_struct_offsets(abi, struct_type, offsets)Computes offsets of each element in a structure type

๐Ÿ”ฐ Introduction

Compilers for high level languages generate code that follow certain conventions. These conventions are necessary, in part, for separate compilation to work. One such convention is the "calling convention". The calling convention is a set of assumptions made by the compiler about where function arguments will be found on entry to a function. A calling convention also specifies where the return value for a function is found. The calling convention is also sometimes called the "ABI" or "Application Binary Interface".

Some programs may not know at the time of compilation what arguments are to be passed to a function. For instance, an interpreter may be told at run-time about the number and types of arguments used to call a given function. 'Libffi' can be used in such programs to provide a bridge from the interpreter program to compiled code.

The 'libffi' library provides a portable, high level programming interface to various calling conventions. This allows a programmer to call any function specified by a call interface description at run time.

FFI stands for Foreign Function Interface. 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' library really only provides the lowest, machine dependent layer of a fully featured foreign function interface. A layer must exist above 'libffi' that handles type conversions for values passed between the two languages.

๐Ÿ“– Using libffi

๐Ÿ”‘ The Basics

'Libffi' assumes that you have a pointer to the function you wish to call and that you know the number and types of arguments to pass it, as well as the return type of the function.

The first thing you must do is create an 'ffi_cif' object that matches the signature of the function you wish to call. This is a separate step because it is common to make multiple calls using a single 'ffi_cif'. The "cif" in 'ffi_cif' stands for Call InterFace. To prepare a call interface object, use the function 'ffi_prep_cif'.

๐Ÿ”ง Function: ffi_status ffi_prep_cif (ffi_cif *CIF, ffi_abi ABI, unsigned int NARGS, ffi_type *RTYPE, ffi_type **ARGTYPES) This initializes CIF according to the given parameters.

If the function being called is variadic (varargs) then ffi_prep_cif_var must be used instead of ffi_prep_cif.

๐Ÿ”ง Function: ffi_status ffi_prep_cif_var (ffi_cif *CIF, ffi_abi ABI, unsigned int NFIXEDARGS, unsigned int NTOTALARGS, ffi_type *RTYPE, ffi_type **ARGTYPES) This initializes CIF according to the given parameters for a call to a variadic function. In general its operation is the same as for ffi_prep_cif except that:

Note that different cif's must be prepped for calls to the same function when different numbers of arguments are passed. Also a call to ffi_prep_cif_var with NFIXEDARGS=NTOTALARGS is NOT equivalent to a call to ffi_prep_cif.

โ˜๏ธ Note that the resulting ffi_cif holds pointers to all the ffi_type objects used during initialization. You must ensure that these type objects have a lifetime at least as long as that of the ffi_cif.

To call a function using an initialized ffi_cif, use the ffi_call function:

๐Ÿ“ž Function: void ffi_call (ffi_cif *CIF, void *FN, void *RVALUE, void **AVALUES) This calls the function FN according to the description given in CIF. CIF must have already been prepared using ffi_prep_cif.

๐Ÿงช Simple Example

Here is a trivial example that calls 'puts' a few times.

#include <stdio.h>
#include <ffi.h>

int main()
{
  ffi_cif cif;
  ffi_type *args[1];
  void *values[1];
  char *s;
  ffi_arg rc;

  /* Initialize the argument info vectors */
  args[0] = &ffi_type_pointer;
  values[0] = &s;

  /* Initialize the cif */
  if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
                   &ffi_type_sint, args) == FFI_OK)
    {
      s = "Hello World!";
      ffi_call(&cif, puts, &rc, values);
      /* rc now holds the result of the call to puts */

      /* values holds a pointer to the function's arg, so to
         call puts() again all we need to do is change the
         value of s */
      s = "This is cool!";
      ffi_call(&cif, puts, &rc, values);
    }

  return 0;
}

๐Ÿ“ฆ Types

๐Ÿ—๏ธ Primitive Types

'Libffi' provides built-in type descriptors:

Each is of type ffi_type, take the address when passing to ffi_prep_cif.

๐Ÿ›๏ธ Structures

Create a new ffi_type object for a structure:

๐Ÿ“ฆ Data type: ffi_type

No special support for bit-fields; manage manually.

The size and alignment fields filled in by ffi_prep_cif or ffi_prep_cif_var.

๐Ÿ“ Size and Alignment

libffi sets size and alignment for you, but there are caveats:

Example usage:

ffi_type *desired_type;
ffi_abi desired_abi;
...
ffi_cif cif;
if (ffi_prep_cif (&cif, desired_abi, 0, desired_type, NULL) == FFI_OK)
  {
    size_t size = desired_type->size;
    unsigned short alignment = desired_type->alignment;
  }

Also provides ffi_get_struct_offsets:

๐Ÿ”ง Function: ffi_status ffi_get_struct_offsets (ffi_abi abi, ffi_type *struct_type, size_t *offsets) Computes offsets of each element of the given structure type. Returns FFI_OK on success, FFI_BAD_ABI if ABI invalid, FFI_BAD_TYPEDEF if struct_type invalid.

๐Ÿ“š Arrays, Unions, and Enumerations

Arrays

Emulate arrays using FFI_TYPE_STRUCT with as many members as elements.

ffi_type array_type;
ffi_type **elements
int i;

elements = malloc ((n + 1) * sizeof (ffi_type *));
for (i = 0; i < n; ++i)
  elements[i] = array_element_type;
elements[n] = NULL;

array_type.size = array_type.alignment = 0;
array_type.type = FFI_TYPE_STRUCT;
array_type.elements = elements;

Arrays cannot be passed/returned by value in C; this is for referencing members of real structs. Using as argument/return type may not cause errors but may be confusing.

Unions

Emulate unions using FFI_TYPE_STRUCT. Ensure size and alignment match real union requirements. Example uses ffi_prep_cif to lay out each element type:

ffi_abi desired_abi;
ffi_type union_type;
ffi_type **union_elements;

int i;
ffi_type element_types[2];

element_types[1] = NULL;

union_type.size = union_type.alignment = 0;
union_type.type = FFI_TYPE_STRUCT;
union_type.elements = element_types;

for (i = 0; union_elements[i]; ++i)
  {
    ffi_cif cif;
    if (ffi_prep_cif (&cif, desired_abi, 0, union_elements[i], NULL) == FFI_OK)
      {
        if (union_elements[i]->size > union_type.size)
          {
            union_type.size = union_elements[i];
            size = union_elements[i]->size;
          }
        if (union_elements[i]->alignment > union_type.alignment)
          union_type.alignment = union_elements[i]->alignment;
      }
  }
Enumerations

No special support. The underlying integral type cannot be determined by libffi; depends on values or compiler flags like -fshort-enums. See GCC documentation for details.

๐Ÿ“ Type Example

Describing the tm struct from time.h:

struct tm {
    int tm_sec;
    int tm_min;
    int tm_hour;
    int tm_mday;
    int tm_mon;
    int tm_year;
    int tm_wday;
    int tm_yday;
    int tm_isdst;
    /* Those are for future use. */
    long int __tm_gmtoff__;
    __const char *__tm_zone__;
};
{
  ffi_type tm_type;
  ffi_type *tm_type_elements[12];
  int i;

  tm_type.size = tm_type.alignment = 0;
  tm_type.type = FFI_TYPE_STRUCT;
  tm_type.elements = &tm_type_elements;

  for (i = 0; i < 9; i++)
      tm_type_elements[i] = &ffi_type_sint;

  tm_type_elements[9] = &ffi_type_slong;
  tm_type_elements[10] = &ffi_type_pointer;
  tm_type_elements[11] = NULL;

  /* tm_type can now be used to represent tm argument types and
     return types for ffi_prep_cif() */
}

๐ŸŒ€ Complex Types

libffi supports C99 complex types (_Complex float, _Complex double, _Complex long double) via built-in descriptors ffi_type_complex_float, ffi_type_complex_double, ffi_type_complex_longdouble.

Custom complex types like _Complex int can be defined using ffi_type:

See Complex Type Example for platform-independent size/alignment determination. On platforms without complex support, ffi_prep_cif and ffi_prep_args abort on encountering a complex type.

๐Ÿ”ฌ Complex Type Example

#include <stdio.h>
#include <ffi.h>
#include <complex.h>

void complex_fn(_Complex float cf,
                _Complex double cd,
                _Complex long double cld)
{
  printf("cf=%f+%fi\ncd=%f+%fi\ncld=%f+%fi\n",
         (float)creal (cf), (float)cimag (cf),
         (float)creal (cd), (float)cimag (cd),
         (float)creal (cld), (float)cimag (cld));
}

int main()
{
  ffi_cif cif;
  ffi_type *args[3];
  void *values[3];
  _Complex float cf;
  _Complex double cd;
  _Complex long double cld;

  /* Initialize the argument info vectors */
  args[0] = &ffi_type_complex_float;
  args[1] = &ffi_type_complex_double;
  args[2] = &ffi_type_complex_longdouble;
  values[0] = &cf;
  values[1] = &cd;
  values[2] = &cld;

  /* Initialize the cif */
  if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3,
                   &ffi_type_void, args) == FFI_OK)
    {
      cf = 1.0 + 20.0 * I;
      cd = 300.0 + 4000.0 * I;
      cld = 50000.0 + 600000.0 * I;
      /* Call the function */
      ffi_call(&cif, (void (*)(void))complex_fn, 0, values);
    }

  return 0;
}

Example for defining custom complex type descriptor:

/*
 * This macro can be used to define new complex type descriptors
 * in a platform independent way.
 *
 * name: Name of the new descriptor is ffi_type_complex_<name>.
 * type: The C base type of the complex type.
 */
#define FFI_COMPLEX_TYPEDEF(name, type, ffitype)             \
  static ffi_type *ffi_elements_complex_##name [2] = {      \
    (ffi_type *)(&ffitype), NULL                             \
  };                                                        \
  struct struct_align_complex_##name {                      \
    char c;                                                  \
    _Complex type x;                                         \
  };                                                        \
  ffi_type ffi_type_complex_##name = {                      \
    sizeof(_Complex type),                                   \
    offsetof(struct struct_align_complex_##name, x),         \
    FFI_TYPE_COMPLEX,                                        \
    (ffi_type **)ffi_elements_complex_##name                 \
  }

/* Define new complex type descriptors using the macro: */
/* ffi_type_complex_sint */
FFI_COMPLEX_TYPEDEF(sint, int, ffi_type_sint);
/* ffi_type_complex_uchar */
FFI_COMPLEX_TYPEDEF(uchar, unsigned char, ffi_type_uint8);

New type descriptors can be used like built-in ones.

๐Ÿ”€ Multiple ABIs

A given platform may provide multiple ABIs (e.g., x86 has stdcall and fastcall). libffi provides some support, necessarily platform-specific.

๐Ÿ”’ The Closure API

Write a generic function (function that can accept any combination of arguments). Useful for interpreters or wrappers. Check FFI_CLOSURES define for platform support.

๐Ÿ”ง Function: void *ffi_closure_alloc (size_t SIZE, void **CODE) Allocate SIZE bytes for a closure. Returns writable address, sets *CODE to executable address. SIZE should fit a ffi_closure object. ๐Ÿ”ง Function: void ffi_closure_free (void *WRITABLE) Free memory allocated by ffi_closure_alloc.

After allocating memory, construct a ffi_cif describing the function call, then prepare the closure:

๐Ÿ”ง Function: ffi_status ffi_prep_closure_loc (ffi_closure *CLOSURE, ffi_cif *CIF, void (*FUN)(ffi_cif *CIF, void *RET, void **ARGS, void *USER_DATA), void *USER_DATA, void *CODELOC)

Returns FFI_OK on success. After call, cast CODELOC to appropriate function pointer type.

๐Ÿ›‘ The older ffi_prep_closure is deprecated (cannot separate writable and executable addresses).

๐Ÿงฉ Closure Example

#include <stdio.h>
#include <ffi.h>

/* Acts like puts with the file given at time of enclosure. */
void puts_binding(ffi_cif *cif, void *ret, void* args[],
                  void *stream)
{
  *(ffi_arg *)ret = fputs(*(char **)args[0], (FILE *)stream);
}

typedef int (*puts_t)(char *);

int main()
{
  ffi_cif cif;
  ffi_type *args[1];
  ffi_closure *closure;

  void *bound_puts;
  int rc;

  /* Allocate closure and bound_puts */
  closure = ffi_closure_alloc(sizeof(ffi_closure), &bound_puts);

  if (closure)
    {
      /* Initialize the argument info vectors */
      args[0] = &ffi_type_pointer;

      /* Initialize the cif */
      if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
                       &ffi_type_sint, args) == FFI_OK)
        {
          /* Initialize the closure, setting stream to stdout */
          if (ffi_prep_closure_loc(closure, &cif, puts_binding,
                                   stdout, bound_puts) == FFI_OK)
            {
              rc = ((puts_t)bound_puts)("Hello World!");
              /* rc now holds the result of the call to fputs */
            }
        }
    }

  /* Deallocate both closure, and bound_puts */
  ffi_closure_free(closure);

  return 0;
}

๐Ÿ”’ Thread Safety

libffi is not completely thread-safe. Follow these rules:

๐Ÿ’พ Memory Usage

Memory allocated by ffi_closure_alloc and freed by ffi_closure_free comes from a different pool than malloc/free. libffi may map temporary files into multiple address-space locations for security. Search order for memory:

  1. Anonymous mapping (not file-backed)
  2. memfd_create() (if kernel supports)
  3. File in directory from LIBFFI_TMPDIR env var
  4. File in directory from TMPDIR env var
  5. File in /tmp
  6. File in /var/tmp
  7. File in /dev/shm
  8. File in user's home directory ($HOME)
  9. File in any directory listed in /etc/mtab
  10. File in any directory listed in /proc/mounts

If security settings prohibit all, ffi_closure_alloc fails.

โš ๏ธ Missing Features

Known missing features (patches welcome):

๐Ÿ“‘ Index

L(1)
๐Ÿ“š libffi ๐Ÿš€ Quick Reference ๐Ÿ”ฐ Introduction ๐Ÿ“– Using libffi
๐Ÿ”‘ The Basics ๐Ÿงช Simple Example ๐Ÿ“ฆ Types ๐Ÿ”€ Multiple ABIs ๐Ÿ”’ The Closure API ๐Ÿงฉ Closure Example ๐Ÿ”’ Thread Safety
๐Ÿ’พ Memory Usage โš ๏ธ Missing Features ๐Ÿ“‘ Index

Generated by phpman v4.9.22-1-g1b0fcb4 · Markdown · JSON · MCP Author: Che Dong Under GNU General Public License
2026-07-05 16:43 @216.73.216.52
CrawledBy Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; ClaudeBot/1.0; +claudebot@anthropic.com)
Valid XHTML 1.0 Transitional!Valid CSS!
Enhanced by LLM: deepseek-v4-pro / taotoken.net / www.chedong.com - original format

^_top_^