6.29.2 Declaring C Functions

Before you can call lseek or dlseek, you have to declare it. The declaration consists of two parts:

The C part

is the C declaration of the function, or more typically and portably, a C-style #include of a file that contains the declaration of the C function.

The Forth part

declares the Forth types of the parameters and the Forth word name corresponding to the C function.

For the words lseek and dlseek mentioned earlier, the declarations are:

\c #define _FILE_OFFSET_BITS 64
\c #include <sys/types.h>
\c #include <unistd.h>
c-function lseek lseek n n n -- n
c-function dlseek lseek n d n -- d

The C part of the declarations is prefixed by \c, and the rest of the line is ordinary C code. You can use as many lines of C declarations as you like, and they are visible for all further function declarations.

The Forth part declares each interface word with c-function, followed by the Forth name of the word, the C name of the called function, and the stack effect of the word. The stack effect contains an arbitrary number of types of parameters, then --, and then exactly one type for the return value. The possible types are:

n

single-cell integer

a

address (single-cell)

d

double-cell integer

r

floating-point value

func

C function pointer

void

no value (used as return type for void functions)

To deal with variadic C functions, you can declare one Forth word for every pattern you want to use, e.g.:

\c #include <stdio.h>
c-function printf-nr printf a n r -- n
c-function printf-rn printf a r n -- n

Note that with C functions declared as variadic (or if you don’t provide a prototype), the C interface has no C type to convert to, so no automatic conversion happens, which may lead to portability problems in some cases. You can add the C type cast in curly braces after the Forth type. This also allows to pass e.g. structs to C functions, which in Forth cannot live on the stack.

c-function printfll printf a n{(long long)} -- n
c-function pass-struct pass_struct a{*(struct foo *)} -- n

This typecasting is not available to return values, as C does not allow typecasts for lvalues.

\c ( "rest-of-line" –  ) gforth-0.7 “backslash-c”

One line of C declarations for the C interface

c-function ( "forth-name" "c-name" "{type}" "—" "type" –  ) gforth-0.7 “c-function”

Define a Forth word forth-name. Forth-name has the specified stack effect and calls the C function c-name.

c-value ( "forth-name" "c-name" "—" "type" –  ) gforth-1.0 “c-value”

Define a Forth word forth-name. Forth-name has the specified stack effect and gives the C value of c-name.

c-variable ( "forth-name" "c-name" –  ) gforth-1.0 “c-variable”

Define a Forth word forth-name. Forth-name returns the address of c-name.

In order to work, this C interface invokes GCC at run-time and uses dynamic linking. If these features are not available, there are other, less convenient and less portable C interfaces in lib.fs and oldlib.fs. These interfaces are mostly undocumented and mostly incompatible with each other and with the documented C interface; you can find some examples for the lib.fs interface in lib.fs.