| How to extend C programs with Guile | ||
|---|---|---|
| <<< Previous | Getting Started | Next >>> |
The example shows many of the basic features of a Guile-extended C program at work. It starts up the Guile interpreter. It loads in a Scheme file. It looks up a function from the Guile interpreter. And, it calls the function.
These actions will be part of the common work of most Guile-extended C programs. These fundamental actions of creating libraries in Scheme and then calling them from C are basic to the successful use of Guile.
The function scm_init_guile at the top of the C program kicks off the Guile interpreter.
Any Guile program has to use either of two functions to initialize the Guile interpreter. The one shown in the example, scm_init_guile has a cleaner syntax, but, may not be possible depending of the C compiler. The other, scm_boot_guilehas a messier syntax, but, is more easily ported from one C compiler to another.
To my mind, this is the preferred method of starting up Guile. It only requires the one line and it is very clean and readable. The function is requires to set up the memory management of the Guile interpreter.
The command should come first in the main().
When Guile is initialized in this way, the command-line variables, argc and argv can be translated into Guile variables using scm_set_program_arguments. See section FIXME.
This is the most portable way of initializing Guile. It is possible that for some non-GCC C compilers scm_init_guile may fail to execute as expected. The function scm_boot_guile should be available to a wider array of C compilers.
Thus if the program is likely to be compiled on a non-GCC platform, scm_boot_guile is recommended and possibly required.
Here is the main.c of the previous example rewritten to use scm_boot_guile to initialization the Guile interpreter.
#include <stdio.h>
#include <stdlib.h>
#include <libguile.h>
static void inner_main (void *closure, int argc, char **argv);
int main (int argc, char *argv[])
{
scm_boot_guile (argc, argv, inner_main, 0);
// Never gets here
return(EXIT_SUCCESS);
}
static void inner_main (void *closure, int argc, char **argv)
{
SCM func_symbol;
SCM func;
// Load the scheme function definitions
scm_c_primitive_load ("script.scm");
func_symbol = scm_c_lookup("do-hello");
func = scm_variable_ref(func_symbol);
scm_call_0 (func);
exit(EXIT_SUCCESS);
}
|
In the sample program, after having initialized Guile, the next step is to load a scheme program. The sample program then loads in a scheme file using the following line
scm_c_primitive_load("script.scm"); |
The naming of the function may seem puzzling at first. The ``c'' indicates that this scheme library function takes a C-type variable, and does not indicate that this function loads C code into scheme. In this case, the C-type variable is the C string that contains a filename. And although this function calls itself ``primitive,'' there isn't an ``advanced'' or ``elegant'' version of this command.
This line encapsulates a lot of functionality. Guile opens the file, reads it, and executes the commands therein.
In our example script script.scm, a function has been defined. When it is loaded using scm_c_primitive_load, the function becomes available to the top-level environment.
Guile, like C, has varying levels of scope. In C, a variable or function can be defined to be global, only visible within a single source code file, or only visible within a function. The Guile analog to the C global scope is the scheme top-level environment. Guile also has other environments, other levels of scope.
In the hello_world example, the Guile script only defines a function to be called later.
A script does not have to contain itself to defining functions and variables. It can also contain code meant to be executed when the script is loaded. By appending the following line to the top of the Guile script, the script will output this helpful message during the scm_c_primitive_load command.
(display "I am loaded...") |
After having initialized Guile and loaded the definition of the single function, the next lines of the C program call that function. This is done in three steps.
First, it is necessary to look up the function by name. The scm_c_lookup function is used for that purpose. Again, the ``c'' in the function name indicates that this Guile function takes a C-type variable as an argument, which, in this case, is a C string containing the name of the Guile function.
Looking up the name is only half the battle. The result of the lookup operation is a variable that points to the function, not the function itself. To get the function, the result of the lookup operation needs to be dereferenced. The scm_variable_ref function is used for the dereferencing. It returns the actual function pointer.
Lastly, the function pointer is used to call the function. The scm_call_0 is used to call the function with zero arguments.
| <<< Previous | Home | Next >>> |
| Simple Guile Example | Up | Something Went Wrong |