---
name: "ffi_prep_closure"
section: "3"
platform: "macos"
package: "pyobjc"
version: "63"
release: "macOS 26.5"
platforms: ["macos"]
url: "https://new.carta.tech/ffi_prep_closure"
---

# ffi\_prep\_closure(3)

Prepare a ffi\_closure for execution.

## NAME

**ffi\_prep\_closure** – Prepare a **ffi\_closure** for execution.

## SYNOPSIS

**#include \<ffi/ffi.h\>**

*ffi\_status*\

**ffi\_prep\_closure**(*ffi\_closure \*closure*, *ffi\_cif \*cif*, *void (\*fun)(ffi\_cif\*,void\*,void\*\*,void\*)*, *void \*user\_data*);

## DESCRIPTION

*closure* is prepared to execute *fun*. *cif* contains information describing the data types, sizes and alignments of the arguments to and return value from the function that will be called from *fun*, and must be initialized with **ffi\_prep\_cif** before it is used with **ffi\_prep\_closure**. *user\_data* may point to additional data to be used in *fun*. If no additional data is needed, *user\_data* may be **NULL**. When *closure* is invoked, *fun* is called with *cif*, an array of pointers to arguments, a pointer to a return value, and *user\_data*.

Some architectures do not allow the execution of data by default. In such cases, it is necessary to manually alter the permissions of the page that contains *closure* prior to its execution.

## RETURN VALUES

Upon successful completion, **ffi\_prep\_closure** returns **FFI\_OK**. If the ABI specified in *cif* does not refer to a valid ABI, **FFI\_BAD\_ABI** will be returned. Available ABIs are defined in **\<ffi/ppc-ffitarget.h\>** and **\<ffi/x86-ffitarget.h\>**.

## EXAMPLES

```
#define MACOSX  // for fficonfig.h on Darwin
#include <ffi/ffi.h>
#include <sys/mman.h>   // for mmap()
unsigned char
foo(unsigned int, float);
static void
foo_closure(ffi_cif*, void*, void**, void*);
int
main(int argc, const char **argv)
{
    ffi_cif cif;
    ffi_closure *closure;
    ffi_type *arg_types[2];
    ffi_arg result;
    ffi_status status;
    // Specify the data type of each argument. Available types are defined
    // in <ffi/ffi.h>.
    arg_types[0] = &ffi_type_uint;
    arg_types[1] = &ffi_type_float;
    // Allocate a page to hold the closure with read and write permissions.
    if ((closure = mmap(NULL, sizeof(ffi_closure), PROT_READ | PROT_WRITE,
        MAP_ANON | MAP_PRIVATE, -1, 0)) == (void*)-1)
    {
        // Check errno and handle the error.
    }
    // Prepare the ffi_cif structure.
    if ((status = ffi_prep_cif(&cif, FFI_DEFAULT_ABI,
        2, &ffi_type_uint8, arg_types)) != FFI_OK)
    {
        // Handle the ffi_status error.
    }
    // Prepare the ffi_closure structure.
    if ((status = ffi_prep_closure(closure, &cif, foo_closure, NULL)) != FFI_OK)
    {
        // Handle the ffi_status error.
    }
    // Ensure that the closure will execute on all architectures.
    if (mprotect(closure, sizeof(closure), PROT_READ | PROT_EXEC) == -1)
    {
        // Check errno and handle the error.
    }
    // The closure is now ready to be executed, and can be saved for later
    // execution if desired.
    // Invoke the closure.
    result = ((unsigned char(*)(float, unsigned int))closure)(42, 5.1);
    // Free the memory associated with the closure.
    if (munmap(closure, sizeof(closure)) == -1)
    {
        // Check errno and handle the error.
    }
    return 0;
}
// Invoking the closure transfers control to this function.
static void
foo_closure(ffi_cif* cif, void* result, void** args, void* userdata)
{
    // Access the arguments to be sent to foo().
    float arg1 = *(float*)args[0];
    unsigned int arg2 = *(unsigned int*)args[1];
    // Call foo() and save its return value.
    unsigned char ret_val = foo(arg1, arg2);
    // Copy the returned value into result. Because the return value of foo()
    // is smaller than sizeof(long), typecast it to ffi_arg. Use ffi_sarg
    // instead for signed types.
    *(ffi_arg*)result = (ffi_arg)ret_val;
}
// The closed-over function.
unsigned char
foo(unsigned int x, float y)
{
    unsigned char result = x - y;
    return result;
}
```

## SEE ALSO

[ffi(3)](/ffi/3.md), [ffi\_prep\_cif(3)](/ffi_prep_cif/3.md), [mmap(2)](/mmap/2.md), [munmap(2)](/munmap/2.md), [mprotect(2)](/mprotect/2.md)
