6.29.1 Calling C functions

Once a C function is declared (see see Declaring C Functions), you can call it as follows: You push the arguments on the stack(s), and then call the word for the C function. The arguments have to be pushed in the same order as the arguments appear in the C documentation (i.e., the first argument is deepest on the stack). Integer and pointer arguments have to be pushed on the data stack, floating-point arguments on the FP stack; these arguments are consumed by the called C function.

On returning from the C function, the return value, if any, resides on the appropriate stack: an integer return value is pushed on the data stack, an FP return value on the FP stack, and a void return value results in not pushing anything. Note that most C functions have a return value, even if that is often not used in C; in Forth, you have to drop this return value explicitly if you do not use it.

The C interface automatically converts between the C type and the Forth type as necessary, on a best-effort basis (in some cases, there may be some loss).

As an example, consider the POSIX function lseek():

off_t lseek(int fd, off_t offset, int whence);

This function takes three integer arguments, and returns an integer argument, so a Forth call for setting the current file offset to the start of the file could look like this:

fd @ 0 SEEK_SET lseek -1 = if
  ... \ error handling
then

You might be worried that an off_t does not fit into a cell, so you could not pass larger offsets to lseek, and might get only a part of the return values. In that case, in your declaration of the function (see Declaring C Functions) you should declare it to use double-cells for the off_t argument and return value, and maybe give the resulting Forth word a different name, like dlseek; the result could be called like this:

fd @ 0. SEEK_SET dlseek -1. d= if
  ... \ error handling
then

Passing and returning structs or unions is currently not supported by our interface37.

Calling functions with a variable number of arguments (variadic functions, e.g., printf()) is only supported by having you declare one function-calling word for each argument pattern, and calling the appropriate word for the desired pattern.


Footnotes

(37)

If you know the calling convention of your C compiler, you usually can call such functions in some way, but that way is usually not portable between platforms, and sometimes not even between C compilers.