namespace eval Cookbook {
    variable _ruff_preamble {

        While using CFFI to wrap a few ad-hoc functions is fairly
        straightforward, wrapping a large API into a complete package can be
        more involved as decisions how C types are translated to script level
        annotations. This page provides some recipes for mapping C declarations
        to CFFI declarations depending on the declaration context (parameter,
        struct field etc.).

        ## Defining a function

        A function definition consists of three components.

        ``` -caption "Function definition syntax" diagram ditaa
        +------------------+ +-----------+ +--------------+
        |Calling convention+ +Return type+ +Parameter list|
        +------------------+ +-----------+ +--------------+
        ```

        Sections below detail definition of each.

        ### Calling convention

        Check the header file or documentation of the function for the expected
        calling convention. Generally, this is only an issue if the application
        supports the 32-bit Windows platform. Note the function calling
        convention may be defined through a macro such as `WINAPI` etc. Most
        Windows OS API's are defined using the stdcall convention. The default C
        language calling convention is either unspecified or `_cdecl` in C
        header files. Most third party API's are defined using this convention.
        CFFI does not support any calling convention other than these two.

        ``` -caption "Calling convention syntax" diagram
        LIB function RETURNTYPE PARAMLIST
        LIB stdcall RETURNTYPE PARAMLIST
        ```

        * Define using `stdcall` if the function is defined on 32-bit Windows
        using `__stdcall` or its equivalent. Note on other platforms, including
        64-bit Windows, this is treated as equivalent to `function`

        * Define using `function` otherwise after ensuring it does not use
        some other esoteric platform-specific convention (rare).

        **Examples**

        C

        ```
        WINAPI DWORD GetCurrentProcessId(void);
        int getpid(void);
        ```

        CFFI

        ```
        KERNEL32 stdcall GetCurrentProcessId ulong {}
        LIBC function getpid int {}
        ```

        Note `WINAPI` in the Windows SDK headers maps to `__stdcall`.

        ### Return type declaration

        #### Void returns

        ``` -caption "Syntax for void return type" diagram
        void
        ```

        The `void` return type does not permit any annotations.

        **Examples**

        C

        ```
        void tzset(void)
        ```

        CFFI

        ```
        LIBC function tzset void {}
        ```

        #### Integer returns

        ``` -caption "Syntax for integer return types" diagram
                   +-         +-      -+ -+ +-           +-                 -+ -+
        schar      | {enum E} | bitmask|  | | zero       | lasterror         |  |
        uchar      +-         +-      -+ -+ | nonzero    | winerror          |  |
        short                               | positive   | errno             |  |
        ushort                              | nonnegative| {onerror HANDLER} |  |
        int                                 +-           +-                 -+ -+
        uint
        long
        ulong
        longlong
        ulonglong
        ```

        * If the returned values are constrained to a set and a symbolic
        representation is preferred, optionally add the `enum` attribute with
        the enumeration defined as a literal or separately through the
        [::cffi::enum] command.

        * If a symbolic representation is preferred as above and the value is
        actually a bit mask, optionally add the `bitmask` attribute to have
        the value returned as a list of symbols from the enumeration.

        * If return values may indicate error conditions, add an error checking
        annotation like `zero`, `nonzero` etc.

        * If a error checking annotation is added and additional detail
        is available from the system, add `lasterror`, `winerror` or `errno`
        as appropriate. If error information is available through some other
        API, add the `onerror` handler. This may also be used to filter errors
        or convert error conditions to success.


        **Examples**

        C

        ```
        int open(const char *pathname, int flags);
        ```

        CFFI

        ```
XXX        LIBC open

        ```


        #### Floating point returns

        ``` -caption "Syntax for floating point return types" diagram
        float
        double
        ```

        Floating point types `float` and `double` do not permit any annotations
        on return type declarations.

        **Examples**

        C

        ```
        double sin(double x);
        ```

        CFFI

        ```
        LIBM function sin double {x double}
        ```


        #### Pointer returns

        Pointer return values may be dealt with at the script level either as
        raw pointers or as implicitly dereferenced values.

        * Declare the function as returning a raw pointer if the returned
        pointers point to resources that have to be freeing at a later point.
        If typed as implicitly dereferenced values, the raw pointer will
        not be available for freeing.

        * Declare the function as returning an implicitly dereferenced value
        if the returned pointers point to some internal or static storage that
        does not need to be freed. An example is the `strerror` C runtime library
        function. Note that implicitly dereferenced types are a convenience;
        they may be typed as raw pointers instead while the reverse will likely
        produce memory leaks.

        The type declarations for raw and implicitly dereferenced pointers are
        separately described below.

        ##### Raw pointers

        ``` -caption "Syntax for raw pointer return type" diagram
                      +-      -+ +-                 -+
        pointer       | counted| | nullok            |
        pointer.TAG   | unsafe | | lasterror         |
                      +-      -+ | errno             |
                                 | {onerror HANDLER} |
                                 +-                 -+
        ```

        * The `TAG` is optional but recommended wherever possible for additional
        [tag-based][::Concepts::Pointer tags] type checks. If the pointer's
        target type is a struct, it is is recommended, but not mandatory, that
        the tag used be the name of the struct instance command. This makes it
        convenient to access the referenced memory using the struct
        [methods][::cffi::Struct].

        * By default, pointers returned from functions are marked as
        [safe pointers][::Concepts::Pointer safety]. This is appropriate for
        unique pointers that are returned for allocated resources and are only valid
        until they are deallocated through a corresponding *free* function.
        A variation is when the pointer returned is not unique as is the case
        for reference counted resources. In this case the pointer should be
        annotated as `counted`. For cases where neither of the above apply, for
        example there is no clear transfer of ownership or freeing, or pointers
        are internal to the API, there are two choices. First, it can be defaulted as
        a safe pointer. In this case, since there is no *free* function, the
        [::cffi::pointer dispose] command must be called at the appropriate time
        by the application to unregister the pointer. Alternatively, the
        `unsafe` annotation can be added to the declaration. In this case,
        there is no need to unregister the pointer but it can only be used
        in places (arguments and struct fields) that also have the `unsafe`
        annotation. For more details on pointer management and safety,
        see [Pointer safety][::Concepts::Pointer safety].

        * Irrespective of the pointer safety annotations, NULL pointers returned
        from functions will by default raise a generic *Pointer is NULL* exception.
        As for integer return values, if additional information is available from
        the system or API, the type can be annoted with `lasterror`, `errno`
        or `onerror`. On the other hand, if a NULL pointer is a valid return
        value, the `nullok` annotation will suppress the exception and return
        a NULL pointer at the script level.

        **Examples**

        C

        ```
        void *malloc(size_t sz);
        FILE *fopen(const char *pathname, const char *mode);
        git_tree_entry *git_tree_entry_byname(git_tree *, const char *filename);
        ```

        CFFI

        ```
        LIBC malloc {pointer errno} {sz size_t}
        LIBC fopen {pointer.FILE errno} {pathname string mode string}
        LIBGIT git_tree_entry_byname {pointer.git_tree_entry unsafe} {
            pTree {pointer.git_tree counted}
            filename string
            }
        ```

        The `unsafe` and `counted` annotations on `git_tree_entry_byname` arise
        from the libgit2 API. The returned pointer is internal to libgit2 and
        hence marked as unsafe while `git_tree` structs are reference counted.

        ##### Implicitly dereferenced pointers

        Raw pointers at script level, while as versatile as their C counterparts,
        are not as convenient to use as plain old values. Additional steps are
        needed to access the memory as script level values. Declaring pointer
        return types as implicitly dereferenced obviates the need for this
        additional step. As stated earlier, implicit dereferencing should only
        be done when there is no need for the pointer value itself for freeing
        later.

        For types **other than pointers to character (or unicode) strings**, the
        CFFI declaration has the form

        ``` -caption "Syntax for implicitly dereferenced pointers" diagram
                  +-      -+
        TYPE byref| nullok |
                  +-      -+
        ```

        where `TYPE` may be one of the numeric types or a `STRUCT`.
        The `byref` annotation on the return type declaration denotes that
        the function return value is nominally a pointer that references
        the true function result.

        **Examples**

        C

        ```
        struct git_oid *git_tree_oid(git_tree *pTree);
        ```

        CFFI

        ```
        LIBGIT function git_tree_oid {struct.git_oid byref} {pTree pointer.git_tree}
        ```

        A call to the `git_tree_oid` function will then return the `git_oid`
        struct (assumed defined previously with [::cffi::Struct]) in its
        script level dictionary form. The actual C level pointer is not
        accessible but not needed as it is internal to the `git_tree` and
        not to be freed or manipulated.

        As for raw pointers, a null pointer return will raise an exception
        by default. The `nullok` annotation may suppress the exception in the
        case that `TYPE` is a struct with defaults defined for all fields
        (possibly with the `-clear` option). In that the dictionary
        corresponding to a struct value with all fields defaulted is returned.
        For all other types and structs with at least one field without a
        default, an exception is raised irrespective of `nullok`.

        For C pointers typed as `char *` which return pointers to character
        strings, the implicit dereference syntax is

        ``` -caption "Syntax for character string return types" diagram
              +-      -+
        STRING| nullok |
              +-      -+
        ```

        The `byref` is not present because `string` and `unistring` are
        already implicit pointers,
        (`string byref` would correspond to `char **`, not `char *`).
        An optional `nullok` annotation will cause a NULL pointer return
        to be mapped to the empty string instead of generating an exception.

        Note that if `STRING` is `string`, an encoding identifier may be
        optionally attached, e.g. `string.utf-8`.

        **Examples**

        C

        ```
        const char *strerror(int);
        char *strstr(const char *haystack, const char *needle);
        ```

        CFFI

        ```
        LIBC function strerror string {error_code int}
        LIBC function strstr {string nullok} {haystack string needle string}
        ```

        Note the definition of `strstr` to return an empty string if the
        needle is not found instead of raising an exception.


        #### Struct returns

        ``` -caption "Syntax for struct return type" diagram
        struct.STRUCT
        ```

        A struct function return type does not permit any annotations.
        `STRUCT` must be a previously defined [::Struct][::Concepts::Structs].
        Returning a struct by value is rarely seen in C API's.


        **Examples**

        C

        ```
        typedef struct {
            int quot;
            int rem;
        } div_t;
        div_t div (int numer, int denom);
        ```

        CFFI

        ```
        Struct create div_t {quot int rem int}
        LIBC function struct.div_t {numer int denom int}
        ```

        ### Parameter declaration

        Parameters to a C function may be used to pass values to the function
        (input parameters), retrieve values from the function (output parameters),
        or (input-output parameters).

        Scalar values and structs that are passed by value are always input
        parameters. Input parameters may also be passed by reference via a pointer,
        generally with a `const` attribute to indicate the function does not
        modify the referenced value.

        Output and input-output parameters are always passed to C function
        as pointers to a location where the value is stored. At the script level
        the argument is the name of the variable where the value is stored and
        not the value itself.

        #### Integer parameters

        ##### Integer input parameters

        ``` -caption "Syntax for integer input parameters" diagram
                  +- -+ +-   -+ +-      -+ +-     -+ +-         -+ +-               -+
        schar     |in | |byref| |{enum E}| |bitmask| |{default N}| |lasterror        |
        uchar     +- -+ +-   -+ +-      -+ +-     -+ +-         -+ |winerror         |
        short                                                      |errno            |
        ushort                                                     |{onerror HANDLER}|
        int                                                        +-               -+
        uint
        long
        ulong
        longlong
        ulonglong
        ```

        * The `in` annotation is optional because it is the default if none of
        `out`, `retval` or `inout` annotations is present.

        * The `byref` annotation should be specified iff the value is being
        passed by reference, i.e. the function parameter is a pointer to the
        value (e.g. `int *` at the C level). This is very rare for integer
        values that are input only. In either case, whether the `byref`
        parameter is present or not, the value at script level is still
        specified directly and not through a variable.

        * Add the `enum` annotation to pass
        [enumeration][::Concepts::Enumerations] symbolic values for readability
        purposes. Note integer values will still be accepted.

        * If the parameter holds a bit mask, add the `bitmask` annotation which
        allows the argument to be a list of integers which will be bitwise
        OR-ed to construct the value passed to the function. May be combined
        with `enum` to pass a list of symbols.

        * The `default` annotation may be used to supply a default value to
        be passed if no argument is supplied for the parameter when the function
        is invoked. All succeeding parameter in the parameter list must also
        have default annotations.

        * Error handling annotations like `errno` may be present but are
        ignored. This is to permit the same aliases to be used in both return
        and parameter declarations.


        **Examples**

        C

        ```
        int SetHandleInformation(void * hObject, unsigned long dwMask, unsigned long dwFlags);
        ```

        CFFI

        ```
        cffi::enum define HANDLE_FLAGS {INHERIT 1 PROTECT_FROM_CLOSE 2}
        KERNEL32 stdcall SetHandleInformation {int nonzero lasterror} {
            hObject pointer
            dwMask {ulong {enum HANDLE_FLAGS} bitmask}
            dwFlags {ulong {enum HANDLE_FLAGS} bitmask}
        }
        ```


        ##### Output and input-output integer parameters

        ``` -caption "Syntax for integer output and input-output parameters" diagram
                        +-      -+ +-     -+ +-          -+ +-               -+
        schar     out   |{enum E}| |bitmask| |storeonerror| |lasterror        |
        uchar     inout +-      -+ +-     -+ |storealways | |winerror         |
        short     retval                     +-          -+ |errno            |
        ushort                                              |{onerror HANDLER}|
        int                                                 +-               -+
        uint
        long
        ulong
        longlong
        ulonglong
        ```

        * Output and in-out parameters in C are always passed as pointers
        to the location where output value is to be stored. Thus `out` and
        `inout` always imply `byref` which is redundant and need not be specified.

        * The script level argument corresponding to `out` and `inout` parameters
        are the name of the variable to which the output value is to be assigned.
        For `inout` parameters this must exist at the time of function call and
        hold a valid value for the type.

        * Use the `retval` annotation for output parameters where you want the
        output parameter value from the function to be returned as the
        function result in lieu of the actual function return value.
        See [Output parameters as function result][::Concepts::Output parameters as function result].

        * Add the `enum` annotation if output values are to be mapped to
        symbolic names for readability. Further, if the values returned
        are actually bitmasks, add `bitmask` to have the returned value
        transformed to a list of symbolic names.

        * If the function return value is subject to error checks
        (for example null pointer checks) and fails the checks, output
        values are not stored in variables as they may hold garbage values.
        The `storealways` annotation indicates the output value is
        valid regardless of function failure. The `storeonerror` annotation
        indicates the output value is valid **only** on function failure
        (for example an error code). See
        [Errors and output parameters][::Concepts::Errors and output parameters].

        * Error handling annotations like `errno` may be present but are
        ignored. This is to permit the same aliases to be used in both return
        and parameter declarations.

        **Examples**

        C

        ```
        int GetHandleInformation(void*  hObject, unsigned long *lpdwFlags);
        ```

        CFFI

        ```
        cffi::enum define HANDLE_FLAGS {INHERIT 1 PROTECT_FROM_CLOSE 2}
        KERNEL32 stdcall GetHandleInformation {int nonzero lasterror} {
            hObject pointer
            flags {ulong retval {enum HANDLE_FLAGS} bitmask}
        }
        ```

        # TODO
        double output parameter
        double modf (double x, double* intpart);


        #### Floating point parameters

        ##### Floating point input parameters

        ``` -caption "Syntax for floating point input parameters" diagram
               +- -+ +-   -+ +-         -+
        float  |in | |byref| |{default N}|
        double +- -+ +-   -+ +-         -+
        ```

        * The `in` annotation is optional because it is the default if none of
        `out`, `retval` or `inout` annotations is present.

        * The `byref` annotation should be specified iff the value is being
        passed by reference, i.e. the function parameter is a pointer to the
        value (e.g. `double *` at the C level). This is very rare for integer
        values that are input only. In either case, whether the `byref`
        parameter is present or not, the value at script level is still
        specified directly and not through a variable.

        * The `default` annotation may be used to supply a default value to
        be passed if no argument is supplied for the parameter when the function
        is invoked. All succeeding parameter in the parameter list must also
        have default annotations.

        **Examples**

        C

        ```
        double sin(double x);
        ```

        CFFI

        ```
        LIBM sin double {x double}
        ```

        ##### Out and in-out floating point parameters

        ``` -caption "Syntax for floating point output and input-output parameters" diagram
                        +-          -+
        float    out    |storeonerror|
        double   inout  |storealways |
                 retval +-          -+
        ```

        * Output and in-out parameters in C are always passed as pointers
        to the location where output value is to be stored. Thus `out` and
        `inout` always imply `byref` which is redundant and need not be specified.

        * The script level argument corresponding to `out` and `inout` parameters
        are the name of the variable to which the output value is to be assigned.
        For `inout` parameters this must exist at the time of function call and
        hold a valid value for the type.

        * Use the `retval` annotation for output parameters where you want the
        output parameter value from the function to be returned as the
        function result in lieu of the actual function return value.
        See [Output parameters as function result][::Concepts::Output parameters as function result].

        * If the function return value is subject to error checks
        (for example null pointer checks) and fails the checks, output
        values are not stored in variables as they may hold garbage values.
        The `storealways` annotation indicates the output value is
        valid regardless of function failure. The `storeonerror` annotation
        indicates the output value is valid **only** on function failure
        (for example an error code). See
        [Errors and output parameters][::Concepts::Errors and output parameters].


        #### Pointer parameters

        As for return values, pointer parameters to C functions can be dealt
        with either as raw pointers or as implicitly dereferenced values.

        In general, pointers that are only used in the C API to pass arguments
        by reference, for example to pass large or non-scalar input values
        (as for structs and arrays) or receive output values, can be declared
        as implicitly dereferenced. The CFFI declarations for these is
        described in other sections with use of the `byref` and `out` annotations.

        This section deals only with raw pointers where the pointer values are
        directly visible at the script level. This is necessary when the pointers
        reference resources that need to freed, or in more complex structures
        in memory with multiple indirections etc.

        ##### Raw pointer input parameters

        ``` -caption "Syntax for input raw pointer parameters" diagram
                    +- -+ +-   -+ +-     -+ +-              -+ +-    -+ +-              -+
        pointer     |in | |byref| |counted| |dispose         | |nullok| |{default PTRVAL}|
        pointer.TAG +- -+ +-   -+ |unsafe | |disposeonsuccess| +-    -+ +-              -+
                                  +-     -+ +-              -+
        ```

        * The `TAG` is optional but recommended wherever possible for additional
        [tag-based][::Concepts::Pointer tags] type checks. If the pointer's
        target type is a struct, it is is recommended, but not mandatory, that
        the tag used be the name of the struct instance command. This makes it
        convenient to access the referenced memory using the struct
        [methods][::cffi::Struct].

        * The `in` annotation is optional because it is the default if none of
        `out`, `retval` or `inout` annotations is present.

        * The `byref` annotation should be specified iff the pointer is being
        passed by reference, i.e. the function parameter is a pointer to a
        pointer. Generally, input parameters passed
        by reference will have `const` in the C parameter declaration.

        * By default, pointers passed into functions are expected to be
        registered as safe pointers. They may be alternatively be annotated with
        `counted` or `unsafe` if they are reference counted or unregistered.
        For more details on pointer management and safety, see
        [Pointer safety][::Concepts::Pointer safety].

        * When a C function releases the resource associated with a registered
        pointer (safe or counted), the pointer should be unregistered.
        The `dispose` annotation should be placed on the parameter annotation
        to convey to CFFI that the pointer should be unregistered. The
        `disposeonsuccess` annotation is similar except that the pointer
        is unregistered only in the case the function returns successfully.
        For more details on pointer management and safety, see
        [Pointer safety][::Concepts::Pointer safety].

        * CFFI assumes by default that functions do not accept NULL pointers
        and will raise an exception if an attempt is made to pass one. The
        `nullok` annotation indicates that the function allows for the pointer
        to be NULL.

        * The `default` annotation may be used to supply a default value to
        be passed if no argument is supplied for the parameter when the function
        is invoked. All succeeding parameter in the parameter list must also
        have default annotations.

        **Examples**

        C

        ```
        void free(void *ptr);
        void *realloc(void *ptr, size_t size);
        ```

        CFFI

        ```
        LIBC function free void {ptr {pointer dispose}}
        LIBC function realloc {pointer errno} {
            ptr {pointer disposeonsuccess}
            size size_t
        }
        ```

        ##### Raw pointer out and in-out parameters

        ``` -caption "Syntax for output and input-output raw pointer parameters" diagram
                     +-    -+ +-     -+ +-              -+ +-    -+ +-              -+ +-          -+
        pointer      |inout | |counted| |dispose         | |nullok| |{default PTRVAL}| |storealways |
        pointer.TAG  |out   | |unsafe | |disposeonsuccess| +-    -+ +-              -+ |storeonerror|
                     |retval| +-     -+ +-              -+                             +-          -+
                     +-    -+
        ```

        * Output parameters in C are always passed as pointers
        to the location where output value is to be stored. Thus `out`
        always implies `byref` which is redundant and need not be specified.

        * The script level argument corresponding to an `out` parameter
        is the name of the variable to which the output value is to be assigned.

        * Use the `retval` annotation for output parameters where you want the
        output parameter pointer value from the function to be returned as the
        function result in lieu of the actual function return value.
        See [Output parameters as function result][::Concepts::Output parameters as function result].

        * By default, pointers returned in out and in-out parameters
        are registered as safe pointers.
        They may be alternatively be annotated with
        `counted` or `unsafe` if they are to be registered as reference counted
        or not to be registered at all.
        For more details on pointer management and safety, see
        [Pointer safety][::Concepts::Pointer safety].

        * When a C function releases the resource associated with a registered
        pointer (safe or counted), the pointer should be unregistered.
        The `dispose` annotation should be placed on the parameter annotation
        to convey to CFFI that the pointer should be unregistered. The
        `disposeonsuccess` annotation is similar except that the pointer
        is unregistered only in the case the function returns successfully.
        The `dispose` and `disposeonsuccess` annotations is not valid with
        the `out` or `retval` annotations.
        For more details on pointer management and safety, see
        [Pointer safety][::Concepts::Pointer safety].

        * The `nullok` annotation indicates that pointers passed in and out
        of the function can be NULL. Without the annotation, an exception is
        raised if the pointer stored on output is NULL or in the case of `inout`
        the pointer passed in is NULL.

        * The `default` annotation may be used to supply a default pointer value to
        be passed if no argument is supplied for the parameter when the function
        is invoked. All succeeding parameter in the parameter list must also
        have default annotations. This annotation cannot be used with `out`
        and `retval` annotations.

        * If the function return value is subject to error checks
        (for example null pointer checks) and fails the checks, output
        values are not stored in variables as they may hold garbage values.
        The `storealways` annotation indicates the output value is
        valid regardless of function failure. The `storeonerror` annotation
        indicates the output value is valid **only** on function failure
        (for example an error code). See
        [Errors and output parameters][::Concepts::Errors and output parameters].

        **Examples**

        C

        ```
        int git_repository_open_bare(git_repository **out, const char *bare_path);
        int ConvertSidToStringSidA(SID *pSid, char **strSid);
        ```

        CFFI

        ```
        LIBGIT2 function git_repository_open_bare {int zero} {
            out {pointer.git_repository counted retval}
            string bare_path
        }
        ADVAPI32 stdcall ConvertSidToStringSidA {int nonzero lasterror} {
            pSid   pointer.SID
            strSid pointer
        }
        KERNEL32 stdcall LocalFree {pointer nullok} {p {pointer dispose}}
        ```

        In the `libgit2` example, `out` is annotated as `counted` because
        `git_repository` is a reference counted opaque structure. The `retval`
        annotation is added to have CFFI return the output parameter value as
        the result of the function.

        In the Win32 example, the returned pointer from `ConvertSidToStringSidW`
        needs to be freed with `LocalFree` and hence needs to be declared
        as a raw pointer. The string can be retrieved from the returned
        pointer with [::cffi::memory tostring] before freeing it.


        #### Struct parameters

        Struct values are represented as the script level as dictionaries.
        This requires their definition as described in
        [Structs][::Concepts::Structs] and [Defining structs].

        ##### Struct input parameters

        ``` -caption "Syntax for struct input parameters" diagram
                      +- -+ +-   -+ +-            -+ +-         -+
        struct.STRUCT |in | |byref| |{default DICT}| |nullifempty|
                      +- -+ +-   -+ +-            -+ +-         -+
        ```

        * The `in` annotation is optional because it is the default if none of
        `out`, `retval` or `inout` annotations is present.

        * The `byref` annotation should be specified iff the value is being
        passed by reference, i.e. the function parameter is a pointer to a
        struct value that is to be passed. Generally, input parameters passed
        by reference will have `const` in the C parameter declaration.
        Irrespective of this annotation, the argument is always a dictionary,
        not a pointer.

        * The `default` annotation may be used to supply a default value to
        be passed if no argument is supplied for the parameter when the function
        is invoked. All succeeding parameter in the parameter list must also
        have default annotations.

        * Some C functions accept a NULL pointer for optional parameters.
        The `nullifempty` annotation identifies such parameters. In this case,
        passing an empty dictionary as the script level argument will result
        in a NULL pointer being passed to the function. This annotation
        only makes sense in the presence of the `byref` annotation.

        **Examples**

        C

        ```
        int git_checkout_head(git_repository *repo, const git_checkout_options *opts);
        ```

        CFFI

        ```
        cffi::Struct create git_checkout_options {...}
        LIBGIT function git_checkout_head {int zero} {
            pRepo pointer.git_repository
            opts  {struct.git_checkout_options byref nullifempty}
        }
        ```

        ##### Output and input-output struct parameters

        ``` -caption "Syntax for struct output and input-output parameters" diagram
                             +-          -+
        struct.STRUCT out    |storeonerror|
                      inout  |storealways |
                      retval +-          -+
        ```

        * Output and in-out parameters in C are always passed as pointers
        to the location where output value is to be stored. Thus `out` and
        `inout` always imply `byref` which is redundant and need not be specified.

        * The script level argument corresponding to `out` and `inout` parameters
        are the name of the variable to which the output value is to be assigned.
        For `inout` parameters this must exist at the time of function call and
        hold a valid value for the type.

        * Use the `retval` annotation for output parameters where you want the
        output parameter value from the function to be returned as the
        function result in lieu of the actual function return value.
        See [Output parameters as function result][::Concepts::Output parameters as function result].

        * If the function return value is subject to error checks
        (for example null pointer checks) and fails the checks, output
        values are not stored in variables as they may hold garbage values.
        The `storealways` annotation indicates the output value is
        valid regardless of function failure. The `storeonerror` annotation
        indicates the output value is valid **only** on function failure
        (for example an error code). See
        [Errors and output parameters][::Concepts::Errors and output parameters].
        These annotations are rarely applicable to struct output parameters.

        **Examples**

        C

        ```
        int GetWindowRect(void *hWnd, RECT *lpRect);
        ```

        CFFI

        ```
        cffi::Struct create RECT {left int top int right int bottom int}
        LIBUSER32 stdcall GetWindowRect int {hwnd pointer rect {struct.RECT out}}
        ```

        #### String parameters

        ##### Input string parameters

        ``` -caption "Syntax for input character string parameters" diagram
                        +- -+ +-   -+ +-         -+
        string          |in | |byref| |nullifempty|
        string.ENCODING +- -+ +-   -+ +-         -+
        unistring
        ```

        * C does not have a string type and the `string` and `unistring` CFFI
        types map to pointers to nul terminated character strings: `char*` in
        the case of `string` and `Tcl_UniChar *` in the case of `unistring`. For
        input parameters, they have the `const` attribute.

        * The `in` annotation is optional because it is the default if none of
        `out`, `retval` or `inout` annotations is present.

        * For the `string` type an optional encoding may be specified and
        defaults to the system encoding. If a library API uses a specific
        encoding (commonly UTF-8), it may be convenient to define a type alias.

        * The `byref` annotation should be specified iff the value is being
        passed by reference, i.e. the function parameter is a pointer to the
        pointer to the character string (double indirection). This is rare for
        passing character string values that are input only. In either case,
        whether the `byref` parameter is present or not, the value at script
        level is still specified directly and not through a variable.

        * Some C functions accept a NULL pointer for optional parameters.
        The `nullifempty` annotation identifies such parameters. In this case,
        passing an empty string as the script level argument will result
        in a NULL pointer being passed to the function.

        **Examples**

        C

        ```
        int chdir(const char *path);
        ```

        CFFI

        ```
        LIBC function chdir {int zero errno} {path string}
        ```

        ##### Output and input-output string parameters

        Character strings are returned from C functions in one of two ways:

        * The C function expects the caller to supply a pointer to an array of
        characters. The size of this array may be a compile time constant or
        passed through another parameter to the function. The function then
        stores the string in this buffer. The C parameter declaration is
        of the form `char *buf` or `char buf[]`.

        * The C function expects the caller to pass a pointer to a memory
        location where it will store the pointer to a string that is either
        dynamically allocated or an internal static string. The C declaration
        is of the form `char **ptr_to_buf` reflecting the double indirection.

        The two are handled differently in CFFI as described below.

        **Output character arrays**

        ``` -caption "Syntax for character array output parameters" diagram
                          +-    -+ +-          -+
        chars[N]          |out   | |storealways |
        chars.ENCODING[N] |inout | |storeonerror|
        unichars[N]       |retval| +-          -+
                          +-    -+
        ```

        This is the first case described above where the C function expects
        a pointer to a character (or `Tcl_UniChar` in the case of `unichars`)
        array.

        * The script level argument corresponding to `out` and `inout` parameters
        are the name of the variable to which the output value is to be assigned.
        For `inout` parameters this must exist at the time of function call and
        hold a valid value for the type.

        * Use the `retval` annotation for output parameters where you want the
        output parameter value from the function to be returned as the
        function result in lieu of the actual function return value.
        See [Output parameters as function result][::Concepts::Output parameters as function result].

        * The array size `N` in the declaration may either be an integer constant
        or the name of a integer type parameter in the same function declaration.
        See [Dynamically sized arrays][::Concepts::Dynamically sized arrays].

        * If `ENCODING` is not specified, it defaults to the system encoding.

        * If the function return value is subject to error checks
        (for example null pointer checks) and fails the checks, output
        values are not stored in variables as they may hold garbage values.
        The `storealways` annotation indicates the output value is
        valid regardless of function failure. The `storeonerror` annotation
        indicates the output value is valid **only** on function failure
        (for example an error code). See
        [Errors and output parameters][::Concepts::Errors and output parameters].


        **Examples**

        C

        ```
        char *getcwd(char *buf, size_t size);
        ```

        CFFI

        ```
        LIBC function getcwd {string errno} {buf {chars[size] out} size size_t}
        ```

        **Output pointers to strings**

        The second case is when the C function parameter is a pointer to
        pointer to a character string (`char **`).

        How this is best handled depends on whether the returned pointer needs
        to be available at the script level as a raw pointer, possibly for later
        freeing. See [Pointer returns] for a more detailed discussion about
        raw pointers versus implicit dereferencing.
        If this is the case, see [Raw pointer out and in-out parameters] for
        appropriate declarations.

        If retention of the raw pointer is not required
        (for example, pointer to static storage), then its most convenient to
        implicitly declare it as an output parameter of

        ``` -caption "Syntax for output character string parameters" diagram
                        +-    -+ +-    -+ +-          -+
        string          |out   | |nullok| |storealways |
        string.ENCODING |retval| +-    -+ |storeonerror|
        unistring       +-    -+          +-          -+
        ```
        * Output parameters in C are always passed as pointers
        to the location where output value is to be stored. Thus `out`
        always implies `byref` which is redundant and need not be specified.

        * The script level argument corresponding to an `out` parameter
        is the name of the variable to which the output value is to be assigned.

        * Use the `retval` annotation for output parameters where you want the
        output parameter value from the function to be returned as the
        function result in lieu of the actual function return value.
        See [Output parameters as function result][::Concepts::Output parameters as function result].

        * If the function return value is subject to error checks
        (for example null pointer checks) and fails the checks, output
        values are not stored in variables as they may hold garbage values.
        The `storealways` annotation indicates the output value is
        valid regardless of function failure. The `storeonerror` annotation
        indicates the output value is valid **only** on function failure
        (for example an error code). See
        [Errors and output parameters][::Concepts::Errors and output parameters].
        These annotations are rarely applicable to struct output parameters.


        #### Binary string parameters

        Binary strings are similar to strings except that instead of treating
        pointers at the C level as character strings in Tcl, they treat them as
        binary strings so there is no character encoding/decoding transformation
        applied and nul characters have no special treatment.

        ##### Input binary string parameters

        ``` -caption "Syntax for input binary string parameters" diagram
               +- -+ +-   -+ +-         -+ +-               -+
        binary |in | |byref| |nullifempty| |{default DEFAULT}|
               +- -+ +-   -+ +-         -+ +-               -+
        ```

        * The usual C declarations that map to `binary` are `char *`,
        `unsigned char *` and `void *`. Further, input parameters have the
        `const` attribute.

        * The `in` annotation is optional because it is the default if none of
        `out`, `retval` or `inout` annotations is present.

        * The `byref` annotation should be specified iff the value is being
        passed by reference, i.e. the function parameter is a pointer to the
        pointer to the array of bytes string (double indirection). This is rare
        for passing binary values that are input only. In either case, whether
        the `byref` parameter is present or not, the value at script level is
        still specified directly and not through a variable.

        * Some C functions accept a NULL pointer for optional parameters. The
        `nullifempty` annotation identifies such parameters. In this case,
        passing an zero-length binary string as the script level argument will
        result in a NULL pointer being passed to the function.

        * The `default` annotation may be used to supply a default value to
        be passed if no argument is supplied for the parameter when the function
        is invoked. All succeeding parameter in the parameter list must also
        have default annotations.

        **Examples**

        C

        ```
        ssize_t write(int fd, const void *buf, size_t count);
        ```

        CFFI

        ```
        LIBC function write {ssize_t nonnegative errno} {
            fd int
            buf binary
            count size_t
        }
        ```


        ##### Output and input-output binary string parameters

        Binary strings are returned from C functions in one of two ways:

        * The C function expects the caller to supply a pointer to a memory
        block interpreted simply as an array of bytes. The size of this memory
        block may be a compile time constant or passed through another parameter
        to the function. The function then stores the data in this memory
        buffer. The C parameter declaration is generally one of `void *`, `char
        *buf`, `char buf[]` (or the unsigned variants).

        * The C function expects the caller to pass a pointer to a memory
        location where it will store the pointer to a block of memory that is
        either dynamically allocated or an internal buffer. The C
        declaration is of the form `char **`, `unsigned char **` or
        `void **` reflecting the double indirection.

        The two are handled differently in CFFI as described below.

        **Output byte arrays**

        ``` -caption "Syntax for byte array output parameters" diagram
                 +-    -+ +-          -+
        bytes[N] |out   | |storealways |
                 |inout | |storeonerror|
                 |retval| +-          -+
                 +-    -+
        ```

        This is the first case described above where the C function expects
        a pointer to a byte array.

        * The script level argument corresponding to `out` and `inout` parameters
        are the name of the variable to which the output value is to be assigned.
        For `inout` parameters this must exist at the time of function call and
        hold a Tcl binary string.

        * Use the `retval` annotation for output parameters where you want the
        output parameter value from the function to be returned as the
        function result in lieu of the actual function return value.
        See [Output parameters as function result][::Concepts::Output parameters as function result].

        * The array size `N` in the declaration may either be an integer constant
        or the name of a integer type parameter in the same function declaration.
        See [Dynamically sized arrays][::Concepts::Dynamically sized arrays].

        * If the function return value is subject to error checks
        (for example null pointer checks) and fails the checks, output
        values are not stored in variables as they may hold garbage values.
        The `storealways` annotation indicates the output value is
        valid regardless of function failure. The `storeonerror` annotation
        indicates the output value is valid **only** on function failure
        (for example an error code). See
        [Errors and output parameters][::Concepts::Errors and output parameters].

        The difference between an array declared as `bytes[N]` versus
        `schar[N]` or `uchars[N]` is that while both might be
        arrays of `char` or `unsigned char` at the C level, the former
        declaration will result in a Tcl binary string at the script
        level while the latter declarations will result in lists of
        integers.

        **Examples**

        C

        ```
        ssize_t read(int fd, void *buf, size_t count);
        ```

        CFFI

        ```
        LIBC function read {ssize_t nonnegative errno} {
            fd int
            buf bytes[count]
            count size_T
        }
        ```

        **Output pointers to binary strings**

        Another way of returning binary data is through a parameter that is a
        pointer to pointer to the data (`char **` etc.). This case has to
        be handled as [raw pointers][Raw pointer out and in-out parameters]
        since, unlike for character strings, there is no way for CFFI to know the
        size of the data being returned.


        #### Arrays as parameters

        ```
        TYPE[N] type specific annotations ...
        ```

        * Arrays in C are always passed by reference, as a pointer to the
        first element of the array. CFFI array type declarations therefore
        are implicitly annotated as `byref`.

        * The array size in the type declaration may be an integer constant
        or specified as the name of another parameter. See
        [Dynamically sized array][::Concepts::Dynamically sized arrays].

        * The annotations permitted on an array type declaration are those
        permitted for the base type. For example, integer array declarations
        may have the `enum` annotation.

        * At the script level, arrays are represented as lists except
        for the special cases of
        as [`chars`][String parameters] or [`bytes`][Binary string parameters]
        where they are character or binary strings.

        ## Defining structs

        Native C struct values may be dealt with at the script level either
        as Tcl dictionary values or kept in their native form and accessed
        through raw pointers. Both methods require the struct to be defined
        with [::cffi::Struct]. In the former case, the fields are accessed
        using Tcl's `dict` command. In the latter case, the [::cffi::Struct]
        accessor methods are used.

        ### Field type declarations

        The field type declarations in a [struct][::Concepts::Structs]
        definition, while similar to function parameter type declarations,
        differ from them in some respects.

        * The `void` and `binary` base types cannot be used in struct fields.

        * The annotations for each type are differ from those
        applicable in a parameter context.

        #### Integer fields

        ``` -caption "Syntax for integer fields" diagram
                  +-      -+ +-     -+ +-         -+ +-        -+ +-               -+
        schar     |{enum E}| |bitmask| |{default N}| |structsize| |lasterror        |
        uchar     +-      -+ +-     -+ +-         -+ +-        -+ |winerror         |
        short                                                     |errno            |
        ushort                                                    |{onerror HANDLER}|
        int                                                       +-               -+
        uint
        long
        ulong
        longlong
        ulonglong
        ```

        * If the `enum` annotation is present, the field is subject to
        mapping to symbols from the [enumeration][::Concepts::Enumerations].

        * If the `bitmask` annotation is present, the dictionary element
        for the field is treated a list of integers that are bitwise OR-ed
        to form the native field value.

        * The `default` annotation specifies a default value to be used when
        constructing a native struct from the dictionary representation if
        the dictionary does not contain a key for the field.

        * The `structsize` annotation specifies that the field should be
        defaulted to the size of the native struct.

        * Error handling annotations like `errno` may be present but are
        ignored. This is to permit the same aliases to be used in both function
        struct definitions.

        #### Floating point fields

        ``` -caption "Syntax for floating point fields"
               +-         -+
        float  |{default N}|
        double +-         -+
        ```

        * The `default` annotation specifies a default value to be used when
        constructing a native struct from the dictionary representation if
        the dictionary does not contain a key for the field.

        #### Pointer fields

        ``` -caption "Syntax for input raw pointer parameters" diagram
                    +-     -+ +-    -+ +-              -+
        pointer     |counted| |nullok| |{default PTRVAL}|
        pointer.TAG |unsafe | +-    -+ +-              -+
                    +-     -+
        ```

        * The `TAG` is optional but recommended wherever possible for additional
        [tag-based][::Concepts::Pointer tags] type checks. If the pointer's
        target type is a struct, it is is recommended, but not mandatory, that
        the tag used be the name of the struct instance command. This makes it
        convenient to access the referenced memory using the struct
        [methods][::cffi::Struct].

        * The `counted` and `unsafe` annotations have their usual meaning
        as described in [Pointer safety][::Concepts::Pointer safety].
        By default, when a native C struct is constructed from its script
        level dictionary representation, the pointer value for a field is
        expected to have been registered as a safe pointer and an exception is
        raised otherwise. Conversely, when a dictionary is constructed from a
        native C struct, as output from a function for example, the extracted
        pointer is registered as a safe pointer. This is often not the right
        model for embedded pointers in structs unlike pointers directly returned
        from functions with a clear resource allocation and freeing
        semantics. Thus use of the `unsafe` annotation should be strongly
        considered for field type declarations.

        * The `nullok` annotation should be applied to any field that can
        validly hold a NULL pointer. In the absence of an annotation,
        an exception is raised if an attempt is made to assign the
        field in a native struct a NULL pointer value.

        * Pointer fields that hold pointers to character strings may be
        alternatively declared as [string pointer fields][String pointer fields].

        #### String pointer fields

        ``` -caption "Syntax for string pointer fields" diagram
                        +-         -+
        string          |nullifempty|
        string.ENCODING +-         -+
        unistring
        ```

        * The `nullifempty` annotation may be used in cases where an empty
        string at the script level should be stored as a NULL pointer in the
        struct field.

        As for function parameters, fields that hold pointers to character
        strings can be more conveniently declared as one of the CFFI
        string types if the raw pointer is not required for freeing of resources
        or other purposes. There are is a restriction imposed when a struct
        field is declared as a string type. The struct definition may be used
        to pass and return parameters from functions but cannot be used
        with the [::cffi::Struct.new] or [::cffi::Struct.allocate] methods
        to allocate a native struct in memory.

        #### Character array fields

        ``` -caption "Syntax for character array fields" diagram

        chars[N]          +-               -+
        chars.ENCODING[N] |{default DEFAULT}|
        unichars[N]       +-               -+
        ```

        Like `string` and `unistring`, the `chars` and `unichars` CFFI types are
        character strings at the script level. However, while the former maps
        to pointers at the C level, `chars` and `unichars` map to
        `char[]` and `Tcl_UniChar[]` arrays.

        * The `default` annotation may be used to supply a default value to
        be stored in the native C struct if the dictionary representation
        does not have a key matching the field.

        * The array size `N` must be an positive integer constant and
        not dynamically sized as is permitted for array parameters.

        #### Byte array fields

        ``` -caption "Syntax for byte array fields" diagram

                 +-               -+
        bytes[N] |{default DEFAULT}|
                 +-               -+
        ```

        The difference between an array declared as `bytes[N]` versus
        `schar[N]` or `uchars[N]` is that while both might be
        arrays of `char` or `unsigned char` at the C level, the former
        declaration will result in a Tcl binary string at the script
        level while the latter declarations will result in lists of
        integers.

        * The `default` annotation may be used to supply a default value to
        be stored in the native C struct if the dictionary representation
        does not have a key matching the field.

        * The array size `N` must be an positive integer constant and
        not dynamically sized as is permitted for array parameters.

        #### Nested struct fields

        A struct definition may include a field that is declared as
        another struct.

        ``` -caption "Syntax for nested struct fields" diagram
                      +-         -+
        struct.STRUCT |{default DICT}|
                      +-         -+
        ```

        * A nested `STRUCT` struct may have a default value specified as a
        dictionary mapping field names of `STRUCT` to field values.

        #### Array fields

        ```
        TYPE[N] type specific annotations ...
        ```

        * The array size `N` must be an positive integer constant and
        not dynamically sized as is permitted for array parameters.

        * The annotations permitted on an array type declaration are those
        permitted for the base type. For example, integer array declarations
        may have the `enum` annotation.

        * At the script level, C arrays are represented as lists except
        for the special cases of
        as [`chars`][Character array fields] or [`bytes`][Byte array fields]
        where they are character or byte arrays.


        ## Tips and tricks

        **This section to be written**

        - duplicating structure or function definition
        - pointer casting - implicit and explicit
        - use raw pointers for large data to avoid copies
        - use memory get command to decode native memory in type-specific
        manner
        - use defaults, -clear, structsize for structs
    }

}
