### 2.1 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.

  abi is the ABI to use; normally `FFI_DEFAULT_ABI` is what you want. Multiple ABIs for more information.

  nargs is the number of arguments that this function accepts.

  rtype is a pointer to an `ffi_type` structure that describes the return type of the function. See Types.

  argtypes is a vector of `ffi_type` pointers. argtypes must have nargs elements. If nargs is 0, this argument is ignored.

  `ffi_prep_cif` returns a `libffi` status code, of type `ffi_status`. This will be either `FFI_OK` if everything worked properly; `FFI_BAD_TYPEDEF` if one of the `ffi_type` objects is incorrect; or `FFI_BAD_ABI` if the abi parameter is invalid.

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:

  nfixedargs is the number of fixed arguments, prior to any variadic arguments. It must be greater than zero.

  ntotalargs the total number of arguments, including variadic and fixed arguments. argtypes must have this many elements.

  `ffi_prep_cif_var` will return `FFI_BAD_ARGTYPE` if any of the variable argument types are `ffi_type_float` (promote to `ffi_type_double` first), or any integer type small than an int (promote to an int-sized type first).

  Note that, different cif’s must be prepped for calls to the same function when different numbers of arguments are passed.

  Also note that a call to `ffi_prep_cif_var` with nfixedargs=nototalargs is NOT equivalent to a call to `ffi_prep_cif`.

Note that the resulting `ffi_cif` holds pointers to all the `ffi_type` objects that were 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`.

  rvalue is a pointer to a chunk of memory that will hold the result of the function call. This must be large enough to hold the result, no smaller than the system register size (generally 32 or 64 bits), and must be suitably aligned; it is the caller’s responsibility to ensure this. If cif declares that the function returns `void` (using `ffi_type_void`), then rvalue is ignored.

  In most situations, `libffi` will handle promotion according to the ABI. However, for historical reasons, there is a special case with return values that must be handled by your code. In particular, for integral (not `struct`) types that are narrower than the system register size, the return value will be widened by `libffi`. `libffi` provides a type, `ffi_arg`, that can be used as the return type. For example, if the CIF was defined with a return type of `char`, `libffi` will try to store a full `ffi_arg` into the return value.

  avalues is a vector of `void *` pointers that point to the memory locations holding the argument values for a call. If cif declares that the function has no arguments (i.e., nargs was 0), then avalues is ignored.

  Note that while the return value must be register-sized, arguments should exactly match their declared type. For example, if an argument is a `short`, then the entry in avalues should point to an object declared as `short`; but if the return type is `short`, then rvalue should point to an object declared as a larger type – usually `ffi_arg`.