Next: , Previous: Memory allocation and garbage collection, Up: GH


19.11 Calling Scheme procedures from C

Many of the Scheme primitives are available in the gh_ interface; they take and return objects of type SCM, and one could basically use them to write C code that mimics Scheme code.

I will list these routines here without much explanation, since what they do is the same as documented in R5RS. But I will point out that when a procedure takes a variable number of arguments (such as gh_list), you should pass the constant SCM_UNDEFINED from C to signify the end of the list.

— C Function: SCM gh_not (SCM x)

Return #t iff x is #f, else return #f.

— C Function: SCM gh_define (char *name, SCM val)

Corresponds to the Scheme (define name val): it binds a value to the given name (which is a C string). Returns the new object.

Pairs and lists

— C Function: SCM gh_cons (SCM a, SCM b)
— C Function: SCM gh_list (SCM l0, SCM l1, ... , SCM_UNDEFINED)

These correspond to the Scheme (cons a b) and (list l0 l1 ...) procedures. Note that gh_list is a C macro that invokes scm_listify.

— C Function: SCM gh_car (SCM obj)
— C Function: SCM gh_cdr (SCM obj)
... — C Function: SCM gh_car (SCM obj)

Likewise gh_cdr through gh_cXr, where X can be replaced by combinations of “a” and “d” up to length four. These correspond to the Scheme (car ls), (cdr ls), etc.

— C Function: SCM gh_set_car_x (SCM pair, SCM value)

Modifies the CAR of pair to be value. This is equivalent to the Scheme procedure (set-car! ...).

— C Function: SCM gh_set_cdr_x (SCM pair, SCM value)

Modifies the CDR of pair to be value. This is equivalent to the Scheme procedure (set-cdr! ...).

— C Function: unsigned long gh_length (SCM ls)

Returns the length of the list.

— C Function: SCM gh_append (SCM args)
— C Function: SCM gh_append2 (SCM l1, SCM l2)
— C Function: SCM gh_append3 (SCM l1, SCM l2, l3)
— C Function: SCM gh_append4 (SCM l1, SCM l2, l3, l4)

gh_append takes args, which is a list of lists (list1 list2 ...), and returns a list containing all the elements of the individual lists.

A typical invocation of gh_append to append 5 lists together would be

            gh_append(gh_list(l1, l2, l3, l4, l5, SCM_UNDEFINED));

The functions gh_append2, gh_append2, gh_append3 and gh_append4 are convenience routines to make it easier for C programs to form the list of lists that goes as an argument to gh_append.

— C Function: SCM gh_reverse (SCM ls)

Returns a new list that has the same elements as ls but in the reverse order. Note that this is implemented as a macro which calls scm_reverse.

— C Function: SCM gh_list_tail (SCM ls, SCM k)

Returns the sublist of ls with the last k elements.

— C Function: SCM gh_list_ref (SCM ls, SCM k)

Returns the kth element of the list ls.

— C Function: SCM gh_memq (SCM x, SCM ls)
— C Function: SCM gh_memv (SCM x, SCM ls)
— C Function: SCM gh_member (SCM x, SCM ls)

These functions return the first sublist of ls whose CAR is x. They correspond to (memq x ls), (memv x ls) and (member x ls), and hence use (respectively) eq?, eqv? and equal? to do comparisons.

If x does not appear in ls, the value SCM_BOOL_F (not the empty list) is returned.

Note that these functions are implemented as macros which call scm_memq, scm_memv and scm_member respectively.

— C Function: SCM gh_assq (SCM x, SCM alist)
— C Function: SCM gh_assv (SCM x, SCM alist)
— C Function: SCM gh_assoc (SCM x, SCM alist)

These functions search an association list (list of pairs) alist for the first pair whose CAR is x, and they return that pair.

If no pair in alist has x as its CAR, the value SCM_BOOL_F (not the empty list) is returned.

Note that these functions are implemented as macros which call scm_assq, scm_assv and scm_assoc respectively.

Symbols

Vectors

— C Function: SCM gh_make_vector (SCM n, SCM fill)
— C Function: SCM gh_vector (SCM ls)
— C Function: SCM gh_vector_ref (SCM v, SCM i)
— C Function: SCM gh_vector_set_x (SCM v, SCM i, SCM val)
— C Function: unsigned long gh_vector_length (SCM v)
— C Function: SCM gh_list_to_vector (SCM ls)

These correspond to the Scheme (make-vector n fill), (vector a b c ...) (vector-ref v i) (vector-set v i value) (vector-length v) (list->vector ls) procedures.

The correspondence is not perfect for gh_vector: this routine takes a list ls instead of the individual list elements, thus making it identical to gh_list_to_vector.

There is also a difference in gh_vector_length: the value returned is a C unsigned long instead of an SCM object.

— C Function: unsigned long gh_uniform_vector_length (SCM v)

Return the length of uniform vector v.

— C Function: SCM gh_uniform_vector_ref (SCM v, SCM ilist)

Get the given element from a uniform vector v; ilist is a list (or possibly a single integer) of indices, and its length is the dimension of the uniform vector.

— C Macro: SCM gh_vector_to_list (SCM vector)

Return a newly allocated list of the objects contained in the elements of vector.

Procedures

— C Function: SCM gh_apply (SCM proc, SCM args)

Call the Scheme procedure proc, with the elements of args as arguments. args must be a proper list.

— C Function: SCM gh_call0 (SCM proc)
— C Function: SCM gh_call1 (SCM proc, SCM arg)
— C Function: SCM gh_call2 (SCM proc, SCM arg1, SCM arg2)
— C Function: SCM gh_call3 (SCM proc, SCM arg1, SCM arg2, SCM arg3)

Call the Scheme procedure proc with no arguments (gh_call0), one argument (gh_call1), and so on. You can get the same effect by wrapping the arguments up into a list, and calling gh_apply; Guile provides these functions for convenience.

— C Function: SCM gh_catch (SCM key, SCM thunk, SCM handler)
— C Function: SCM gh_throw (SCM key, SCM args)

Corresponds to the Scheme catch and throw procedures, which in Guile are provided as primitives.

[TODO] gh_standard_handler(void *data, SCM tag, SCM throw_args)

— C Function: SCM gh_is_eq (SCM a, SCM b)
— C Function: SCM gh_is_eqv (SCM a, SCM b)
— C Function: SCM gh_is_equal (SCM a, SCM b)

These correspond to the Scheme eq?, eqv? and equal? predicates.

— C Function: int gh_obj_length (SCM obj)

Returns the raw object length.

Data lookup

The GH interface can access the Guile top-level obarrays directly, or consult the module system in various ways. See the hello-guile program for a working example of the following two functions:

— C Function: SCM gh_lookup (const char *sname)

Look up a symbol with a given name sname in the Guile top-level, and return the object to which it is bound, or SCM_UNDEFINED.

— C Function: SCM gh_module_lookup (SCM m, const char *sname)

Look up a symbol with a given name in module m, which may be a vector (obarray implementation satisfying SCM_VECTORP), a list of symbols, a string that can be scm_read as a list of symbols, or #f. In the latter case, consult the Guile top-level and return the object to which the symbol is bound. In the other cases, use scm_module_ref on a list of symbols (constructed if necessary) and return the value of the given name in the module named by that list. Signal error if either the specified module is not loaded, or if the given name is not found in the module.

Example Program: hello-guile.c

/* hello-guile.c --- list features one per line or lookup variable values
 *
 * Copyright (C) 2002, 2007, 2008 Thien-Thi Nguyen
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this software; see the file COPYING.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

/* Usage: hello-guile
   Usage: hello-guile VARIABLE
   Usage: hello-guile -m MODULE VARIABLE
   Usage: hello-guile -l MODULE VARIABLE

   This example basically shows how to use gh_lookup and gh_module_lookup,
   as well as the gh_enter booting mechanism (there are others).  The intent
   is to stay within the "GH" interface.

   The "-m" option looks for VARIABLE in MODULE (but note that if MODULE is
   not loaded an error is signalled).  The "-l" variant loads MODULE first
   before doing the lookup.  See Makefile.am rule `installcheck-local' in this
   directory for example invocations.  */

#include <stdlib.h>
#include <string.h>
#include <guile/gh.h>

static void
hello_guile (int argc, char **argv)
{
  if (1 == argc)
    {
      SCM features = gh_lookup ("*features*");

      while (! gh_null_p (features))
        {
          gh_display (gh_car (features));
          gh_newline ();
          features = gh_cdr (features);
        }
    }
  else
    {
      char *modulename = "(guile-user)";
      int idx = 1;

      /* Handle "-m MODULE" option.  */
      if ('-' == argv[1][0] && 'm' == argv[1][1])
        {
          modulename = argv[2];
          idx += 2;
        }

      /* Handle "-l MODULE" option.  */
      if ('-' == argv[1][0] && 'l' == argv[1][1])
        {
          char *use_modules = malloc (255 + strlen (argv[2]));

          sprintf (use_modules, "(use-modules %s)", argv[2]);
          gh_eval_str (use_modules);
          modulename = argv[2];
          idx += 2;
        }

      gh_display (gh_module_lookup (gh_str02scm (modulename), argv[idx]));
      gh_newline ();
    }
}

int
main (int argc, char **argv)
{
  gh_enter (argc, argv, hello_guile);
  return EXIT_SUCCESS;                  /* never reached */
}

/* hello-guile.c ends here */