GOLF(2gg)

NAME
Server-API - Golf documentation (API)

DESCRIPTION
Golf can be used in extended-mode, where non-Golf code or libraries can be linked with your application.

Such code can be from a library (see --llflag and --cflag options in gg), or can be written directly as C code, i.e. files with .c and .h extension together with your Golf application. To do this, use call-extended statement.

Any function with C linkage can be used provided:

    • its parameters are (by value or reference) only of type: "int64_t" (number type in Golf), "bool" (bool type in Golf) or "char *" (string type in Golf).

    • it must not return any value (i.e. it must have a "void" return type).

When allocating strings in extended code, you must use Golf memory management functions. These functions are based on standard C library (such as malloc or free), but are not compatible with them because Golf manages such memory on top of the standard C library.

The functions you can use are:

    • char *gg_strdup (char *s) which creates a copy of a null-terminated string "s". A pointer to memory data is returned.

    • char *gg_strdupl (char *s, gg_num from, gg_num l) which creates a copy of memory data pointed to by "s", starting from byte "from" of length "l". Note that "from" is indexed from 0. A pointer to memory data is returned.

    • void *gg_malloc(size_t size) which allocates memory of size "s" and returns a pointer to it.

    • void *gg_calloc(size_t nmemb, size_t size) allocates "nmemb" blocks of memory (each of size "size") and returns a pointer to it. Memory is initialized to all zero bytes.

    • num gg_mem_get_id (void *ptr) returns Golf memory handle for memory "ptr".

    • void *gg_realloc(gg_num r, size_t size) reallocates memory identified with Golf memory handle "r" (see gg_mem_get_id()) to a new size of "size" and returns a pointer to it. Note that you can only reallocate the memory you created with gg_malloc() and gg_calloc() - do not attempt to reallocate Golf memory passed to your function. Golf in general never reallocates any existing memory in any statement.

    • void gg_mem_set_len (gg_num r, gg_num len) sets the length of memory identified with Golf memory handle "r" to "len" bytes. Note that all Golf memory must have a null-byte at the end for consistency, regardless of whether such memory holds pure binary data or an actual null-delimited string. So for example, a string "abc" would have "len" set to 4 to include a null byte, and binary data "\xFF\x00\x01" (which consists of 3 bytes, the middle of which is a null byte) would have "len" also set to 4 and you would place an extra zero byte at the end of it even if it's not part of the actual useful data. Note that whatever memory length you set, it must be lesser or equal to the length of memory you have actually allocated.

    • num gg_mem_get_len (gg_num r) returns the length of memory identified with Golf memory handle "r". The length returned is 1 bytes less than the memory set by gg_mem_set_len(), so for example for string "abc" the return value would be 3, as it would be for "\xFF\x00\x01".

You can use gg_malloc(), gg_calloc() and gg_realloc() to create new Golf-compatible memory - and assuming you have set the last byte of any such memory to a null byte, the resulting memory will be properly sized for Golf usage.

If you have memory that's already provided from elsewhere, you can use gg_strdup() or gg_strdupl() to create a copy of it that's compatible with Golf.

If Golf memory you created with these functions has extra unused bytes, you can use either gg_realloc() to reduce its footprint, or you can use gg_mem_set_len() to set its length.

Note that if you use C code included with a Golf project, you must include "golf.h" file in each of them. You do not need to manually include any other ".h" files (header files), as they will be automatically picked up.

EXAMPLES
Place the following files in a separate directory for demonstration purposes.

In this example, "example.golf" will use C functions from "example.c", and "example.h" will have declarations of those functions. File "example.c" implements a factorial function, as well as a function that will store the factorial result in an output message that's allocated and passed back to your Golf code:

        #include "golf.h"

        void get_factorial(gg_num f, gg_num *res)
        {
            *res = 1;
            gg_num i;
            for (i = 2; i <= f; i++) {
                *res *= i;
            }
        }

        #define MEMSIZE 200
        void fact_msg (gg_num i, char **res)
        {
            // golf rule: outgoing string must NOT free or realloc its incoming value
            // all else is allowed
            char *r = gg_malloc (MEMSIZE);
            gg_num f;
            get_factorial (i, &f);
            gg_num bw = snprintf(r, MEMSIZE, "Factorial value (message from C function) is %ld", f) + 1;
            // reduce memory footprint to match the memory used (including the null byte)
            // you can also use gg_mem_set_len() with bw as length for higher performance
            // (but also higher memory usage)
            *res = gg_realloc (gg_mem_get_id(r), bw);
        }

File "example.h" declares the above functions:

        void get_factorial(gg_num f, gg_num *res);
        void fact_msg (gg_num i, char **res);

File "example.golf" will call the above functions and display the results:

        extended-mode

        begin-handler /example public

            set-number fact
            call-extended get_factorial (10, &fact)
            @Factorial is <<print-out fact>>

            set-string res
            call-extended fact_msg (10, &res)
            print-out res
            @
        end-handler

Create application "example":

        sudo mgrg -i -u $(whoami) example

Make the application:

        gg -q

Run it:

        gg -r --req="/example" --exec --silent-header

The output is, as expected:

        Factorial is 3628800
        Factorial value (message from C function) is 362880

SEE ALSO
 API

Client-API Server-API See all documentation