This is the info manual for g-wrap, covering versions 1.3.*.

**********************************
NOTE: THESE DOCS ARE NOT FINISHED.
**********************************

I'm including them in the hope that they're at least somewhat useful, but they have only been partially converted to reflect the major changes that have happened recently.  There may be very misleading or just rough bits as you get further in, and the part still documents the old version.  Caveat emptor.  I hope to finish revising them soon.

Copying
*******

Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995
Free Software Foundation, Inc.
675 Mass Ave, Cambridge, MA 02139, USA

Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation.

NO WARRANTY

BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

Introduction
************

Caveats
=======

 1. I'd like to state right up front that g-wrap is to some extent an experimental work.  It seems useful, but it is certainly not elegant, at least not yet, and maybe not ever, and it's somehat hard for me to say whether that's a statement about the problem, or the current solution.

 2. I'm a little concerned that g-wrap is suffering from mission-creep.

 3. All of these things are my (rlb's) fault, not Christopher's :>

Overview
========

Given a definition of the types and prototypes for a given C interface, G-wrap will automatically generate the C code that provides access to that interface and its types from the Scheme level.

To use g-wrap, you must make sure it knows how to handle all of the C types that the functions you will be calling take as arguments and return as values, and you must also tell g-wrap about the C prototypes of these functions.  Since g-wrap already knows about quite a few of the common C types, for many simple C APIs, you may not need to add any custom type specifications.

G-wrap is implemented as a Guile module, and so its interface is a programmatic one.  You tell g-wrap about your functions and types, and ask it to generate wrappers for you by calling the functions exported from the g-wrap module.

As a simple example, if you wanted to wrap a C API that contained only one function with a prototype like this

       int frob(int x, double y);

a complete g-wrap specification would look like this:

       (use-modules (g-wrap))
       (use-modules (g-wrap gw-standard-spec))

       (let ((mod (gw:new-wrapset "my-g-wrap-wrapset")))
         (gw:wrapset-depends-on mod "gw-standard")
         (gw:wrap-function
          mod
          'frob
          '<gw:int> "frob" '((<gw:int> x) (<gw:double> y))
          "Return the result of frobbing x and y.")

Once g-wrap has seen this specification, the code for the wrappers can be generated with this call:

       (gw:generate-wrapset "my-g-wrap-wrapset")

This will produce C code that when either compiled into a static Guile executable, or built as a shared library and dynamically loaded from Guile will define a Scheme function named frob which you can call as expected:

       (frob 4 2.3)

When it comes to defining how C types should be handled, g-wrap is very flexible.  G-wrap provides a fairly generic underlying infrastructure which can then be customized for particular purposes by teaching it how to generate code for a given type or wrapset.  You can take explicit control over what code is generated in the wrapper module (The term "wrapper module" will always be used to indicate the collection of C code that is generated as the wrapper for a given C API.  It may or may not have any correlation to a Guile module.  When a Guile module is meant, the term Guile module will be used explicitly.) to handle arguments and return values of a given type (both for their initialization and cleanup), what code is generated to handle the wrapper module's global initialization, and what code is generated to provide global declarations.  G-wrap can also spit out a fully functional, dynamically-loadable Guile module if you like (so technically, (use-modules (g-wrapped ncurses)) is now possible, and (with a minor tweak to re-enable some code) g-wrap can generate html docs for the wrapper interface.

At the lowest level, there is a "most generic wrapper type" from which all other wrapper types are derived, and g-wrap comes with a few of these more specialized wrapper types pre-defined.  This set should cover most of the common cases, but you can extend this set if needed.  The wrapper types currently available by default include:

normal (native)
     a wrapper type to handle C types which can be represented most appropriately on the Scheme side by a conversion directly to a native Scheme type.

non-native
     a wrapper type to handle "non-native" objects, that is, C types which can not, or should not be represented on the Scheme side by a conversion to a native Scheme representation, or types for which preserving the C-side pointer equivalency is important.  Instances of this wrapper type are represented at runtime by a Guile SMOB containing the actual C pointer.

enumeration
     a wrapper type to handle C enumerations which automatically grabs the right C-side values at runtime.

Further, g-wrap now has a first pass at an implementation that should allow you to define types in one wrapper module that can then be used by other wrapper modules.  So as an example, you should be able to define a glib wrapper module that provides wrapper specifications for GList*'s that other wrapper modules can then import and use in their own wrapper function prototypes for argument and result types.  The goal is for this to allow different wrapper modules to be able to safely exchange data among their wrapped functions when they share common wrapped types.

As mentioned, g-wrap itself is now implemented as a purely Scheme-code Guile module, and no longer uses globals.  This means that you you can now wrap functions for multiple modules on the fly from any invocation of guile.

Why Create a Wrapper Generator?
===============================

When accessing a given foreign API from a variety of target languages, the description of the foreign API is a common bit of information that will be needed by the infrastructure supporting each of the target languages.  Further, since the internal mechanisms by which a given target language can access a foreign API are often in flux, it makes sense to consider automatically generating the "glue code" that binds the library API and the target language together.  This means that whenever the foreign function access mechanisms in a target language change, only g-wrap (or some similar tool) will need to be updated. Then all of the relevant glue code can be trivially re-generated.  This is the job that g-wrap was designed to handle.

In truth, one of the primary goals of g-wrap is also to acumulate as many language independent definitions of various APIs as possible, so that interfaces for other languages may be generated automatically, whether by g-wrap, or some other program.

The original motivation for g-wrap came from Aubrey Jaffer's suggestion to Christopher Lee that using Scheme to parse a language neutral API specification and generate glue code would be a good way to address this problem for Scheme interpreters.  G-wrap may well evolve beyond that to support other languages, but for now, it only handles access to C APIs from Guile.

In fact, the original implementation of g-wrap was much more declarative than programmatic.  The API specification files were not executable Scheme code, but rather declarative Scheme forms.  In the long run, this might be preferable, if g-wrap decides to move in the direction of language independence, or an alternate possibility is to design a language neutral API spec file (as gnome-guile is trying to do) and then just have a translator from that to native g-wrap calls.

g-wrap can be found at ftp://ftp.gnucash.org/pub/g-wrap/.

Usage
*****

A More Detailed Example.
========================

In this chapter we'll walk through the process of wrapping an incresingly complex C API.  In the process, we'll try to hit all the important g-wrap features.

You'll see how to define a wrapper module, add new types to it (when the default set of types isn't sufficient), wrap the C-side functions, and then generate the Guile wrapper code from the wrapper module definition.

To start, let's presume you want to wrap a C interface that initially looks like this:

       char*  join_strings(char *a, char *b);
       double seconds_since_dow(unsigned int day_of_the_week);

and you want to call your wrapper module ``miscutils''.

To define your module, you need to create a wrapper specification, which is just a file (or files) of scheme code that calls g-wrap functions to create the wrapper module.  Conventionally, if you're creating a wrapper module named "foo", the wrapper-module specification file would be named foo-spec.scm.

Creating a Wrapper Module
=========================

Inside the wrapper module specification file, the first thing you have to do is create the wrapper module.  This is handled with a call to the function gw:new-module, but before that, you have to tell Guile that you want to use g-wrap functions with a call to (use-modules (g-wrap)).  So the most trivial wrapper module possible would look something like this:

       (let ((mod (gw:new-module "miscutils")))
         #t)

However, this module won't let you do much.  In particular, a newly created wrapper module doesn't know about any wrapped types.  In general you'll probably want to be able to use the standard set of g-wrap wrapped types which include support for int, double, strings, etc.  If so, then you need to add a call to gw:module-depends-on like so:

       (let ((mod (gw:new-module "miscutils")))
         (gw:module-depends-on mod "gw-runtime")
         #t)

Now you can start wrapping functions using the default set of wrapped types with calls to gw:wrap-function.  To wrap join_strings and seconds_since, you would want to say something like this:

       (let ((mod (gw:new-module "miscutils")))

         (gw:module-depends-on mod "gw-runtime")

         (gw:wrap-function
          mod
          'join_strings
          '<gw:char*> "join_strings" '((<gw:char*> a) (<gw:char*> b))
          "Return a string consisting of a followed by b.")

         (gw:wrap-function
          mod
          'seconds-since-dow
          '<gw:double> "seconds_since_dow" '((<gw:unsigned-int> day-of-week))
          "Given day-of-week (ranging 1-7), return elapsed time since then."))

gw:wrap-function's arguments in order are

 1. the module to which the function wrapper should be added.

 2. the symbol which should be bound to the wrapped function in Scheme at runtime.

 3. the symbol naming the g-wrap wrapped type of the C function result.

 4. a string giving the C function's name.

 5. a list of the C function's arguments where each element is of the form (g-wrapped-type arg-name-symbol).

 6. a string describing the function.

Actually, the example given above won't work because g-wrap has no definition for char*'s.  There is no <gw:char*> wrapped type.  The reason is that specifying char* alone doesn't provide enough information about the allocation semantics of the argument or return value.  G-wrap needs to know whether a char* argument that's passed in to a function should be considered to be "owned" by the function after the C function returns, or should be considered caller owned, and hence safe for deletion if appropriate.  So g-wrap requires you to be explicit, and provides two different types for string type arguments and return values: <gw:m-chars-caller-owned> and <gw:m-chars-callee-owned>.  The "m" stands for malloc, since it's conceivable that for some C functions, the argument or result might need to be allocated/freed via some other mechanism.

So, for our example API, let's presume that join_strings takes two strings that are owned by the caller and returns a newly allocated string that will also be owned by the caller.  Given that, the correct way to wrap our example API would be:

       (let ((mod (gw:new-module "miscutils")))

         (gw:module-depends-on mod "gw-runtime")

         (gw:wrap-function
          mod
          'join-strings
          '<gw:m-chars-caller-owned> "join_strings"
          '((<gw:m-chars-caller-owned> a) (<gw:m-chars-caller-owned> b))
          "Return a string consisting of a followed by b.")

         (gw:wrap-function
          mod
          'seconds-since-dow
          '<gw:double> "seconds_since_dow" '((<gw:unsigned-int> day-of-week))
          "Given day-of-week (ranging 1-7), return elapsed time since then."))

At this point, we have a wrapper module named "miscutils" that wraps our two C functions so that when the wrapper module's C code is generated, compiled, and then loaded back into Guile, we should be able to call these C functions normally.  Presuming you set miscutils up as a g-wrap module of that name, you could use it like this:

       guile> (use-modules (miscutils))
       guile> (join-strings "out" "let")
       "outlet"
       guile> (seconds-since-dow 1)
       3099.232
       guile>

Defining New Wrapped Types
==========================

Though g-wrap already provides a number of wrapped types in the gw-runtime library, there will be many cases where you will need to define your own wrapped types.

As an example, let's presume someone has added a fine-grained, wide ranging, time type to miscutils along with a function that uses that type like this:

FIXME: Add an overview of how g-wrap thinks about types -- i.e. using a template-like process with ccodegens inserting content in important places.

       typedef Timespec64 {
         long long seconds;
         long int nanoseconds;
       } timespec_64;

       Timespec64 elapsed_time(Timespec64 start, Timespec64 finish);

and let's further presume that we've decided that you want to represent Timespec64 values on the scheme side using a cons pair where the car will be the seconds and the cdr will be the nanoseconds. (Though you should probably consider using the time type from SRFI-19 http://srfi.schemers.org/srfi-19/ instead.)

Since you've decided to use a native Scheme representation for the type, you'll want to define it as an instance of the g-wrap "normal" or "native" wrapper type.  This primarily involves telling g-wrap how to translate from the C representation of the type to the C representation and vice-versa.

The way you do this, is by declaring your new wrapped type and specifying a set of C-code generator functions (or "ccodegens") that will handle producing the C code inside your function wrappers that will handle the translations.

The first thing you need for your new type is a g-wrap name.  For this example, we'll use <miscutils:timespec-64>.  Note that whatever name you pick here will actually be bound to a value at runtime.  The reason for this will become clear later.

To begin, you have to add your new type to your module.  Presume that the following code is inside the body of the "let" defined in our previous examples.  i.e. mod is bound to the miscutils g-wrap module you're creating.

       (let ((wt (gw:wrap-type mod
                               '<miscutils:timespec-64>
                               "Timespec64"
                               "const Timespec64")))
         #t)

The above bit of code does nothing more than create a new (empty) wrapped type.  In order to make this type useful, you have to define some relevant ccodegens.  Let's start with one that will tell g-wrap how to check instances of this type that are passed in as arguments from the Scheme side.  Presume this code is placed where the #t is in the "let" above.

         (gw:type-set-scm-arg-type-test-ccodegen!
          wt
          (lambda (param)
            (list
             "msu_scm_timespec_64_p(" (gw:param-get-scm-name param) ")")))

A ccodegen is just a lambda that generates a list where each element in the list may either be a sub-list or a string, basically a tree of strings.  In the end, this list will be flattened into one long string and inserted into the C code being generated for the wrapper module.

The scm-arg-type-test-ccodegen is always called with just one argument, a representation of the function parameter whose type should be checked. gw:param-get-scm-name is an accessor for these parameter representations that will return the name of the C variable that will be holding the Scheme value passed as an argument to any function with a parameter of this wrapped type.  The C code returned by your scm-arg-type-test-ccodegen should check this Scheme value, and return a non-zero value if the argument is of the correct type.  The above ccodegen presumes that the C function msu_scm_timesepec_64_p has been defined and returns non-zero if the given SCM is a pair and both elements are integers.

At this point g-wrap knows how to check the type of incoming SCM arguments, but it doesn't know how to convert between the C and Scheme representations of your Timespec64 values.  To teach it, you need to define a pre-call-arg-ccodegen.  This ccodegen is used to generate C code in the wrapper functions that will be executed after all of the Scheme values passed as arguments to the wrapped function have been checked by their respective test code (generated by their respective scm-arg-type-test-ccodegen functions), but before the call to the C function being wrapped.

When you specify a pre-call-arg-ccodegen, it will be called with one argument.  As with your scm-arg-type-test-ccodegen, this argument will be a representation of the function parameter that's being processed, and the code you generate with this ccodegen will, in most cases, just be responsible for converting from the Scheme representation for the argument into a C representation that can be passed to the C function that's being wrapped.  In addition to the function used above, gw:param-get-scm-name, you can also ask the param for the name of the C variable that will be used in the call to the C function that's being wrapped by calling gw:param-get-c-name.

So in our Timespec64 example, we might defined our pre-call ccodegen like this:

         (gw:type-set-pre-call-arg-ccodegen!
          wt
          (lambda (param)
            (let* ((scm-name (gw:param-get-scm-name param))
                   (c-name (gw:param-get-c-name param)))
              (list
               c-name
               " = msu_scm_timespec64_to_c_timespec64(" scm-name ");\n"))))

As you can see this ccodegen grabs the Scheme name and the C names of the param and then assignes the C value to be the result of converting the scheme value with the hypothetical msu_scm_timespec64_to_c_timespec64 function.  You can do other things in your pre-call ccodegen, but making sure that a C representation of the Scheme value ends up in the variable named "c-name" is usually the critical thing.

Note too that if you don't like the "tree of strings" approach to generating the C code, you can always rewrite the code like this: (This could result in a loss in portability across Scheme implementations, though right now g-wrap only works with Guile, and may never be ported anywhere else.)

         (gw:type-set-pre-call-arg-ccodegen!
          wt
          (lambda (param)
            (simple-format #f
                           "~A = ~A;\n"
                           (gw:param-get-scm-name param)
                           (gw:param-get-c-name param))))

STOPPED HERE BELOW UNFINISHED...

         (gw:type-set-call-ccodegen!
          wt
          (lambda (standard-c-call-gen result func-call-code)
            (list (gw:result-get-c-name result) " = " func-call-code ";\n")))

       (define (add-standard-result-handlers! type c->scm-converter)
         (define (standard-pre-handler result)
           (let* ((ret-type-name (gw:result-get-proper-c-type-name result))
                  (ret-var-name (gw:result-get-c-name result)))
             (list "{\n"
                   "    " ret-type-name " " ret-var-name ";\n")))

         (gw:type-set-pre-call-result-ccodegen! type standard-pre-handler)

         (gw:type-set-post-call-result-ccodegen!
          type
          (lambda (result)
            (let* ((scm-name (gw:result-get-scm-name result))
                   (c-name (gw:result-get-c-name result)))
              (list
               (c->scm-converter scm-name c-name)
               "  }\n")))))

         (add-standard-result-handlers!
          wt
          (lambda (scm-name c-name)
            (let ((old-func
                   (lambda (x)
                     (list "gnc_timespec2timepair(" x ")"))))
              (list scm-name
                    " = "
                    (old-func c-name)
                    ";\n")))))

Also, note that although there are a bunch of ccodegens you can define for a type, many are optional.

Note that though the code here is C-code, you can also in-line scheme code in many cases with a special construct...

Wrapping C Functions
====================

Generating the Wrapper Code
===========================

Using the Wrapped Interface
===========================

Extending G-wrap
****************

Other Internal Details
======================

Adding New Wrapper Types
========================

Reference
*********

Wrapper Module Operations
=========================

Defining Wrapped Types
======================

Defining New Wrapper Types
==========================

Wrapping Functions
==================

Wrapper Types Available by Default
==================================

Wrapped Types Available by Default
==================================

Functions for describing C code to import to the interpreter
************************************************************

These Scheme functions are used to describe the library to be interfaced to the interpreter.  Use of these functions should allow the library to be described in a manner which is independent from the details of any particular Scheme interpreter's implementation.  An example of the use of these functions is given in Example of a library description.

Defining a new function
=======================

Manually defining functions
---------------------------

 -- Function: new-function scheme-name ret-type c-name param-list description

     Exports a C-function to the Scheme interpreter.  C-NAME must be a string naming the function to be exported.  SCHEME-NAME must be a symbol naming the corresponding function to be provided at the Scheme level.  RET-TYPE must be a symbol or a list of the form (TYPE-SYM . OPTIONS) which describes the function's return type, and PARAM-LIST describes the function's parameters. PARAM-LIST must be a list where each element is also a list of the form (TYPE-SYM ARG-NAME . OPTIONS).  For both the return value and the arguments, TYPE-SYM is a symbol of a type assigned using NEW-TYPE, ADD-TYPE or GWRAP-C-ASSUME-TYPES-WRAPPED, and OPTIONS must be symbols. Currently 'cleanup and 'no-cleanup are the only available options and they are used to override the default cleanup behaviors on a per-argument/return-value basis.  See the discussion of 'cleanup in the make-complex-c-type documentation for details.

     DESCRIPTION must be a string, and will be added to the automatically generated documentation file.

     Examples:

          (new-function
           'eig-dsyev
           'void "eig_dsyev" '((MAT A) (MAT Z) (VEC w))
           "calculates eigenvectors Z and eigenvalues w
          of real symmetric matrix A")

     This writes a wrapper function which accepts three arguments, checks them to make sure they are of types MAT, MAT, and VEC, converts the parameters to the corresponding C-types, then calls the C function eig_dsyev on the converted arguments.  The wrapper function returns an "unspecified" value because the return type is void---otherwise the return value of the C function would be converted to a Scheme value and returned.  The wrapper-function is bound to the Scheme symbol eig-dsyev.

     For Guile
      This command also adds a pair of the form (SCHEME-SYM . DESCRIPTION) to a list exported to the Guile interpreter as *gw:descriptions* which describes the function.

     In the example above, the following pair is then added to *gw:descriptions* when the interpreter is initialized (or when the module is dynamically linked to the interpreter):

          (eig-dsyev .
          "(eig-dsyev A Z w)
            A is a MAT, Z is a MAT, w is a VEC.
            no return value.
          calculates eigenvectors Z and eigenvalues w
          of real symmetric matrix A")

     The following example depicts the use of the cleanup options:

          (new-function
           'some-function
           '(some-type no-cleanup)
           "some_function"
           '((some-other-type x cleanup) (yet-another-type y 'no-cleanup))
           "Do something to x and y to produce an answer of type some-type.")

Scanning source code for functions to export
--------------------------------------------

 -- Function: gwrap-scan-source-file filename

     This command looks through FILENAME for ANSI function declarations that are preceded by a special comment, and does some simplistic parsing to find out enough about each function to write a wrapper function for it. To export a function, simply add the following comment before an ANSI function declaration (note, the /*[ must be the first characters on the line, no indenting):

          /*[EXPORT FLAGS]
           DESCRIPTION
           */

     where DESCRIPTION is a short description of what the function does, and FLAGS (usually left empty) can indicate that g-wrap should override its default assumptions about return type, parameter types, or function name.

     If FLAGS contains:

       * (name NEW-NAME) the function is exported as NEW-NAME.

       * (types ((N NEW-TYPE) ...)) the type of the N-th parameter (the first parameter is 0) is assumed to be NEW-TYPE.

       * (ret-type NEW-TYPE) the return type of the function is assumed to be NEW-TYPE.

     Up to three characters of each line of DESCRIPTION are ignored if they are space or '*' characters.

     For example, if this function definition is in lmatrix.c,

          /*[EXPORT (ret-type RETVEC0)]
           * out := A.x
           */
          VEC *mv_mlt(VEC *v_out, MAT *A, VEC *x) {
            ....
          }

     then these lines in the library description file

          (set! type-translations
                (append '((VEC* VEC) (MAT* MAT)) type-translations))
          (gwrap-scan-source-file "lmatrix.c")

     will be equivalent to

          (new-function
           'mv-mlt
           'VEC "mv_mlt" '((VEC v-out) (MAT A) (VEC x))
           "out := A.x")

Adding a new type
=================

 -- Function: add-type scheme-sym c-name fn-to-scm fn-from-scm fn-isa
     Defines a new Scheme type corresponding to C-type C-NAME, and associates it with symbol SCHEME-SYM. Objects of this type are printed with C-function C-PRINT-NAME, deallocated by C-function C-DIE-NAME, and checked for equality with C-function C-EQ-NAME.

     Scheme-sym should be a symbol, and the other arguments should be strings.

 -- Function: new-type scheme-sym c-name c-print-fn c-die-fn c-eq-fn [options ...]
     As does add-type, this command defines a new Scheme type corresponding to C-type C-NAME, and associates it with symbol SCHEME-SYM. SCHEME-SYM can then be used as a type parameter in functions new-constant and new-function. In addition, a function called C-NAME? is generated to test if any Scheme object is an object of this type.

     new-type also documents the type in documentation file.  If (doc DESCRIPTION) is passed as an option, DESCRIPTION is used to document the type.

     Example:

          (new-type 'MAT  "MAT"  "MAT_print"  "m_free"  "MAT_eq")

       * A Scheme function MAT? is defined to test to see if a Scheme value has this type.

       * C functions must be provided for performing the tasks of performing the basic jobs which the interpreter needs to perform for Scheme objects. In this example, MAT_print writes the representation of the matrix to a port, MAT_die deallocates the matrix, MAT_eq checks for equality of matrices. See C code needed for adding new types to see how to write these functions.

       * This allows MATs to be used as function parameters and as return values.

       * For Guile, this creates a new smob type for holding (MAT*) pointers, and for RScheme it creates a new object-class for the type.

Defining a new constant
=======================

 -- Function: new-constant sym-name type varb
     Defines a constant with C value VARB and C-type TYPE, and export it into the interpreter with Scheme-name SYM-NAME. SYM-NAME and VARB must be strings.

     If (doc DESCRIPTION) is passed as an option, DESCRIPTION is used to document the constant in the documentation file.

     Example:

          (new-constant 'MNULL  'MAT  "NULL" '(doc "null matrix"))

     This adds a value to the interpreter which is the NULL pointers, wrapped as a MAT value, and bound to symbol MNULL.

Other functions needed for describing the library glue code
===========================================================

 -- Function: gwrap-open-module fname [options ...]
     For Guile

     Opens a text file with name FNAME.c, and a Guile initialization function void init_FNAME(void). FNAME must be a string. Also generates a text file with name FNAME.h which contains declarations of functions and variables which may be needed by other code, and a file FNAME.html which contains documentation about the exported functions, types, and constants.

     If (c++? #t) is passed as an option, a C++ file (FNAME.cc) is generated instead of a C file (FNAME.c).

     If (guile-module LST) is passed as an option, then g-wrap generates code for a (dynamically linkable) module, where the module-path is LST.  If this option is #f, no module is generated.

     If (guile-prefix NAME) is passed as an option NAME indicates a prefix that will be appended to the guile-side names.  This may be useful if you don't want to create a module.

     If (call-on-init FN-NAME) is passed as an option (FN-NAME should be the name of a function of type void FN-NAME(void)), FN-NAME is called when the Scheme interpreter initializes the library wrapper.

     For RScheme

     Creates code for generating an RScheme module named fname. This includes a file FNAME.scm of glue-code, and an RScheme module control file FNAME.mcf which tells the RScheme module compiler how to build/compile the module.

     Option (c-files ("FILE1.C" ...)) puts code in the module control file which tells the RScheme module compiler to compile the specified C files into the module.

     Option (h-files ("FILE1.H" ...)) puts code in the module control file which tells the RScheme module compiler to use the header files when compiling code into the module.

     Option (rs-scm-files ("FILE1" ...)) puts code in the module control file which tells the RScheme module compiler to compile compile the specified Scheme files into the module.

     Option (rs-mods ("MOD1" ...)) indicates that the module will use types, functions, or constants from the specified RScheme modules.

     For example,

           (gwrap-open-module "cmat"
                              ; name of Guile module
                              '(guile-module (math matrix cmat))
                              ; extra C files to compile into RS module
                              '(c-files ("cmat_gw_fns.c"))
                              ; extra RScheme modules to include
                              '(rs-mods ("mathlib"))
                              ; extra Scheme files to compile into RS mod
                              '(rs-scm-files ("matrix.scm")))

 -- Function: gwrap-include-local-header x
     The C version of the glue code needs to include local header file "X".

 -- Function: gwrap-include-global-header x
     The C version of the glue code needs to include global header file "X".

 -- Function: gwrap-generate-wrapped-header x
     Generate a C header file for all of the wrapped functions and store it in the file named "X".  This can be useful if you want the g-wrap file to be the ultmate authority about the API.  G-wrap will include documentation in the header file derived from the new-function documentation strings.

 -- Function: gwrap-assume-types-wrapped lst [options ...]
     Assume that types have been defined in another G-wrap file, so that they may be used as parameters in the current G-wrap file. LST is a list of pairs of the form (SCHEME-SYM C-NAME) where SCHEME-SYM is a symbol for the type which will be used to for defining parameter types in calls to 'new-function', and C-NAME is a string indicating the name of the object type in C.

 -- Function: gwrap-close-module
     Specify end of module description, causing the glue-code and related files to be generated.

Example of a library description
================================

     ;;; -*- scheme -*-
     ;;; This file generates the glue code for interfacing the the cmatrix
     ;;;  library to Guile (I've shortened it for the sake of example)
     (set! type-translations
           (append '((VEC* VEC) (MAT* MAT)) type-translations))

     (gwrap-open-module "cmat"
                        ; name of Guile module
                        '(guile-module (math matrix cmat))
                        ; extra C files to compile into the RScheme module
                        '(c-files ("cmat_gw_fns.c"))
                        ; extra RScheme modules to include
                        '(rs-mods ("mathlib"))
                        ; extra Scheme files to compile into RScheme module
                        '(rs-scm-files ("matrix.scm")))
     (gwrap-include-global-header "cmat.h")

     ;; New types to wrap with smobs
     (new-type
      'MAT  "MAT"  "MAT_print"  "m_free"  "MAT_eq"
      '(doc
        "2D matrix of double precision floats"))

     ;; Some constants:
     (new-constant 'MNULL  'MAT  "NULL" '(doc "null matrix"))

     ;; Functions to export to Scheme
     (new-function
      'm-rows
      'int "M_ROWS_CHECKED" '((MAT m))
      "returns number of rows in m")
     (new-function
      'm-cols
      'int "M_COLS_CHECKED" '((MAT m))
      "returns number of columns in m")

     ;; Scan some files to automatically export some functions
     (let ((scan-in-cmatrix-dir
            (lambda (x)
             (gwrap-scan-source-file
              (string-append "../../chrlib/cmatrix/" x)))))
       (for-each scan-in-cmatrix-dir '("cmat_basefns" "cmat_stats.c")))

     (gwrap-close-module)

C code needed for adding new types
**********************************

When you add a new type to the interpreter, you will need to supply the names of three functions.  One function prints a representation of an object of that type, another is called to deallocate the object when it is garbage-collected, and the third is called to compare two objects of that type for equality.

Utility functions
=================

These functions, prototyped in g-wrap.h and implemented for each interpreter which g-wrap supports, can be used in the glue functions for writing strings to Scheme ports and raising Scheme errors.

 -- Function: void gw_puts (char* STR, GWSCM PORT)
     Writes string STR to Scheme port PORT.

 -- Function: void gw_error (char* MESSAGE)
     Raises a Scheme error with string MESSAGE.

Printing object representations
===============================

The function for printing a representation of the object should have a declaration similar to this:

     void PRINT_FN_NAME (TYPE* obj, GWSCM port, int writingp);

The first parameter accepts a pointer to the object to be printed, the second parameter accepts a Scheme value representing the Scheme port to write to, and the final argument indicates whether the object is being printed with display (writingp==0) or write (writingp!=0).  The function gw_puts(char*,GWSCM) can be used to write a string to the port.

Here is an example of a function used for printing a matrix type:

     void MAT_print(MAT *m, GWSCM scmport, int writingp) {
       int i, j;
       char buff[80];

       if ( !m ) {  gw_puts("MNULL",scmport); return; }
       if ( writingp ) {
         sprintf(buff,"(MAT %d %d (", m->m, m->n);
         gw_puts(buff, scmport);
       } else {
         gw_puts("\n", scmport);
       }
       for ( i = 0; i < m->m; i++ ) {
         if ( !writingp ) { gw_puts("[ ", scmport); }
         for ( j = 0; j < m->n; j++ ) {
           sprintf(buff,"%lf ", m->me[i][j]);
           gw_puts(buff, scmport);
         }
         if ( !writingp ) { gw_puts("]\n", scmport); }
       }
       if ( writingp ) { gw_puts(")) ", scmport); }
     }

Function for deallocating an object
===================================

The function for deallocating a pointer to an object on garbage collection should have a single argument---a pointer to the object to be deallocated.

An example of such a function declaration:

     void m_free(MAT *);

Function for object comparisons
===============================

The function for checking the equality of two objects should have a declaration like

     int EQUAL_FN_NAME(TYPE* OBJ1, TYPE* OBJ2);

It should return 0 for false (not equal), and 1 for true (equal).

Here is an example from the matrix object type:

     int MAT_equal(MAT *m1, MAT *m2) {
       int i, j;

       if ( !m1 || !m2 )                           { return ( m1 == m2 ); }
       if ( ! (m1->m == m2->m && m1->n == m2->n) ) { return 0; }
       for ( i = 0; i < m1->m; i++ ) {
         for ( j = 0; j < m1->n; j++ ) {
           if ( m1->me[i][j] != m2->me[i][j] ) { return 0; }
         }
       }
       return 1;
     }

Generating and using the glue code
**********************************

Generating the glue code
========================

The command g-wrap will generate the wrappers for a given target language.  It may be invoked as follows:

For Guile:

g-wrap --target guile --api c interface-spec.gwp

For RScheme:

g-wrap --target rscheme --api c interface-spec.gwp

In both cases, g-wrap will generate a number of files containing the glue code, documention, etc.  In the guile case, presuming that the .gwp file names the output module interface-spec and also requests an automatically generated C header named interface-spec-autogen.h, the following files would be generated:

interface-spec.h
     glue code header

interface-spec.c
     glue code

interface-spec.html
     glue code and API documentation

interface-spec-autogen.h
     automatically generated header for the underlying C API

Interfacing the library and glue code to the interpreter
========================================================

The methods for integrating support for a g-wrapped API into various target languages vary, so these will have to be dealt with on a case by case basis.

At the moment only the primitive tool g-wrap-config is documented here. It can provide the information needed for linking g-wrap into a target executable for each of the languages g-wrap supports (presuming linking even makes sense).  Consider this entire area one that's still under development, so expect the details to change.

Right now code can be statically linked to the interpreters, or loaded dynamically as shared libraries.  To find out which libraries are required use the g-wrap-config command.  It may be invoked as follows:

g-wrap-config --version
     show version information

g-wrap-config --help
     show this message

g-wrap-config --c-compile-args LANGUAGE
     C compile args for LANGUAGE

g-wrap-config --c-link-args LANGUAGE
     C link args for LANGUAGE

g-wrap-config --c-static-link-args LANGUAGE
     C static link args for LANGUAGE

where (at the moment) LANGUAGE may be either rscheme or guile.  Examples for each of the target languages will be available in the distribution.

This infrastructure is probably not sufficient in the long run if g-wrap is extended to support many languages, but it's a start, and it handles the current scope fairly well.

Coping With Old Guile Versions
==============================

The guile interface for dealing with pointers was changed between version 1.3 and subsequent releases (including 1.3.4), and g-wrap was changed to use the new interface.  However, as some older distributions still use guile 1.3 it has been necessary to keep the option of the old interface available.  If you only use 1.3.4 or later versions of guile, you can safely ignore this section.

To use the old interface, make sure the C constant GWRAP_OLD_GUILE_SMOB is defined when compiling the generated C file.

If you are using autoconf, a macro AC_GWRAP_CHECK_GUILE, with no arguments, is provided in g-wrap.m4.  It checkes which version of guile is available, and if necessary sets GWRAP_OLD_STYLE_SMOB.  If you use it, make sure to include the line

     #undef GWRAP_OLD_STYLE_SMOB

in either acconfig.h, or config.h.in, depending on how you are using autoconf. Of course, if you do this, you must ensure config.h is #included when you compile the generated C file!

For more details on autoconf see its extensive documentation.

NOTE: we can't guarantee that old versions of guile will be supported forever. We will try to ensure that most of the versions currently being distributed work, but we're not in a position to keep multiple layers of compatability code.

Types available by default
**************************

By default g-wrap supports the following types.  Each may be used as the TYPE-SYM in calls to new-function:

Guile Types
===========

void
     nothing, on both the C and Scheme sides.

char
     a C `char' and a Scheme character.

int
     a C `int' and a Scheme number.

unsigned-int
     a C `unsigned int' and a Scheme number.

unsigned-long
     a C `unsigned long' and a Scheme number.

unsigned-long-long
     a C `unsigned long long' and a Scheme number.

float
     a C `float' and a Scheme number.

double
     a C `double' and a Scheme number.

bool
     a C `int' and a Scheme boolean.

string-as-symbol
     a C `char *' and a Scheme symbol.  This type lets you pass symbols to C as strings and get them back as symbols.  Note that by default it is assumed that C returns freshly malloced strings, so they'll be deleted immediately.  You can override this on a per function basis with the 'no-cleanup option.  For details see the description of make-complex-c-type in the section on Defining basic Scheme/C types.  WARNING, this type is new and subject to change. Don't rely on it unless you're willing to possibly have to rewrite your spec file a bit when things stablize.

const-string
     a C `char *' and a Scheme string.  This type lets you pass strings from Scheme to C and back, but bear in mind that by default, it takes the conservative (but leaky) position of assuming that the C code might store for later use any strings passed in as arguments, and might pass back as return values strings that are shared elsewhere, or for some other reason cannot be disposed of.  This means that g-wrap will not, by default free the strings it allocates to pass to the underlying C function as parameters, and it will not free any string that the C function might return.  You can override this behavior on a per function basis with the 'cleanup option; for details see the description of make-complex-c-type in the section on Defining basic Scheme/C types.  WARNING, the cleanup functionality is new and subject to change.  Don't rely on it unless you're willing to possibly have to rewrite your spec file a bit when things stablize.

     FIXME: we need a node covering memory allocation.  Combine it with the final node discussing garbage collection.  In the end we need a more general approach in g-wrap.

tSCM
     This is a ``transparent'' type that allows you to pass a Scheme object directly to a C function, or receive one as a return value through the standard Guile SCM type.

The Guile side also supports pointer tokens and pointer arrays. For more information, see Pointer Tokens and Pointer Arrays.

Pointer Tokens and Pointer Arrays
---------------------------------

WARNING: Like the ``cleanup'' functionality, pointer tokens and pointer arrays should be considered highly experimental and subject to change up until at least 1.X of g-wrap is released.  Don't use this unless you're willing to have to re-write everything that depends on it later.  It is currently being tested in GnuCash, but isn't claimed to be ready for prime-time.  Further, in it's final incarnation, we probably need a more coherent mechanism.  As it stands this is a first draft, and things are added as needed.

That said, pointer tokens and pointer arrays provide a method for handling C pointers as arguments and return values.  Pointer tokens handle pointers to C structures and pointer arrays handle C arrays of pointers.

Pointer Tokens
..............

Before deciding to use pointer tokens, please see the warning here Pointer Tokens and Pointer Arrays.

Pointer tokens provide a method for handling pointers to C structures. For example, if you had a C function that took as an argument a Lead* and returned a Gold*, you could tell g-wrap how to handle these pointers and related functions.

     (make-pointer-token-type 'Lead* "Lead*")
     (make-pointer-token-type 'Gold* "Gold*")
     (new-function
      'frobnicate
      'Gold* "frobnicate" '((Lead* lead))
      "Frobnicate.")

The calls to make-pointer-token-type tell g-wrap to create a Scheme level object for each type that can hold the lower level C pointer at the Scheme level.  Pointer token objects are represented as opaque objects (SMOBs actually).  You can pass them around to wrapped C functions, and there are some support functions for manipulating them that are detailed below.  You can't directly create pointer tokens at the Scheme level.  Right now, they're only created as the return values of C level functions.

Null pointers are just represented by #f.  If a wrapped function tries to return a null pointer, g-wrap will convert it to #f, and if you pass in #f to a function that expects a pointer token then g-wrap will arrange for a null pointer to be passed to the underlying wrapped function.

The pointer token items themselves are garbage collected, as you would expect, but the pointers they contain are never touched directly by the g-wrap subsystems, so it's up to you (or the functions being called) to handle de-allocation of the associated C-level Foo* pointers.  This will usually be handled by some sequence like this:

     (define bar (c-func-to-create-foo-pointer))
     (c-func-to-manipulate-foo-pointer bar)
     (c-func-to-destroy-foo-pointer bar)

FIXME: There are also some functions available at the C level for manuipulating pointer tokens from there, but at the moment those functions are not documented.

Pointer Arrays
..............

Before deciding to use pointer arrays, please see the warning here Pointer Tokens and Pointer Arrays.

Pointer arrays provide a method for handling arrays of C pointers to structures.  At the moment, pointer arrays presume null terminated arrays of pointers at the C level.  This is a result of the fact that they were originally implemented to handle an interface that uses null terminated arrays heavily.  Eventually pointer arrays will be extended to handle both null terminated and non-null terminated arrays, probably with two separate types.  This may mean backward-incompatible API renaming/changes, so be warned.

Null array pointers are just represented by #f.  If a wrapped function tries to return a null array pointer, g-wrap will convert it to #f, and if you pass in #f to a function that expects a pointer array then g-wrap will arrange for a null array pointer to be passed to the underlying wrapped function.

As an example, pretend you have a C function that takes as an argument an array of Lead* items (i.e. it has an argument of C type Lead**) and returns an array of Gold* items, you can tell g-wrap how to handle these pointers and related functions like this:

     (make-pointer-array-type 'Lead** "Lead**")
     (make-pointer-array-type 'Gold** "Gold**")
     (new-function
      'frobnicate
      'Gold** "frobnicate" '((Lead** lead))
      "Frobnicate.")

The calls to make-pointer-array-type tell g-wrap to create a Scheme level object for each type that can hold the lower level C pointer array at the Scheme level.  At the Scheme level, pointer array objects are represented as opaque objects (SMOBs actually).  You can pass them around to wrapped C functions, and there are some support functions for manipulating them that are detailed below, but you can't directly create pointer arrays at the Scheme level.  Right now, they're only created as the return values of C level functions.

The pointer array items themselves are garbage collected, as you would expect, but the pointers they contain are never touched directly by the g-wrap subsystems, so it's up to you (or the functions being called) to handle de-allocation of the associated C-level Foo** array objects.  This will usually be handled by some sequence like this:

     (define bar (c-func-to-create-foo-array))
     (c-func-to-manipulate-foo-arrays bar)
     (c-func-to-destroy-foo-arrays bar)

G-wrap will handle arranging for the Scheme level pointer wrappers to be cleaned up by the garbage collector.

In addition to passing pointer arrays as parameters and receiving them as return values, the following functions are available at the Scheme level.  Note that right now, as mentioned above, all of the code presumes that the pointer arrays are null terminated, so if your C code's not set up to work thi way, then you can't use this functionality just yet.

 -- Function: pointer-array-ref pointer-array index

     Returns a pointer-token representing the C level pointer at the given index in the pointer-array (uses zero-indexing).

     Right now there is no range checking on the index, so you can ask for a bogus pointer.

 -- Function: pointer-array-length pointer-array

     Returns the number of items in the pointer-array.

FIXME: There are also some functions available at the C level for manuipulating pointer tokens from there, but at the moment those functions are not documented.

RScheme Types
=============

FIXME: not documented yet...

Extending g-wrap and porting it to other Scheme implementations
***************************************************************

To expand the ability of g-wrap to generate glue code for a given interpreter, you may want to add support for more Scheme data types. This is (usually) a simple process if you understand the internal details of how the interpreter deals with the type in question.

Defining basic Scheme/C types
=============================

For calling C functions from Scheme, a mechanism is needed for checking the type of Scheme values, converting Scheme values to C values, and converting C values to Scheme values.  The function make-c-type is used for making a type-description object which represents how to do this for a given Scheme implementation.

 -- Function: make-c-type c-name fn-convert-to-scm fn-convert-from-scm fn-scm-is-a
     C-NAME is a string indicating the name of the type in C. FN-CONVERT-TO-SCM is a function which generates an expression to convert a C value of this type to a Scheme value. FN-CONVERT-FROM-SCM is a function which generates an expression convert a Scheme value into a C value of this type. FN-SCM-IS-A is a function which generates a check for whether a Scheme value can be converted to this type of C value.  It returns 0 for false and a non-zero value for true.

     The ``expressions'' generated for output to C code are strings, or lists or trees of strings.

 -- Function: add-new-type scheme-sym the-type
     Associates a type-description object, such as that generated by make-c-type, to a symbol so that symbol may be used to refer to a type in a parameter of a function such as (new-function ...).

 -- Function: add-type scheme-sym c-type-str fn-to-scm fn-from-scm fn-isa
     This both defines the type-description and assigns it to a symbol.

     A simple example of how an integer type corresponding to an immediate number in the Guile might be defined:

          (add-type 'int "int"
                      ;fn-convert-to-scm
                      (lambda (x) (list "SCM_MAKINUM(" x ")"))
                      ;fn-convert-from-scm
                      (lambda (x) (list "SCM_INUM(" x ")"))
                      ;fn-scm-is-a
                      (lambda (x) (list "SCM_INUMP(" x ")")))

     An example of how type void (used for specifying no return value for a function) might be defined for the Guile interpreter.

          (add-type 'void "void"
                      ;fn-convert-to-scm
                      (lambda (x) "SCM_UNSPECIFIED")
                      ;fn-convert-from-scm
                      (lambda (x) "(void)")
                      ;fn-scm-is-a
                      (lambda (x) 1))

 -- Function: get-type scheme-sym
     Returns the type-description object associated with a symbol.

 -- Function: make-complex-c-type c-name fn-convert-to-scm fn-convert-from-scm fn-scm-is-a c-cleanup-arg-default? c-cleanup-ret-default? fn-c-cleanup

     WARNING: This function, and the related "cleanup" system should be considered highly experimental and subject to change up until at least 1.X of g-wrap is released.  Don't use this unless you're willing to have to re-write everything that depends on it later.  It is currently being tested in GnuCash, but isn't claimed to be ready for prime-time. Further, in it's final incarnation, it will probably be a more general mechanism...

     This function creates a new g-wrap type corresponding to the C-type C-NAME.  Unlike NEW-TYPE, this function does not have any affect unless you use ADD-NEW-TYPE to tell g-wrap to add the type to its list of known types.

     The parameters have the following purposes:

     c-name
          the name of the type as far as C is concerned.

     fn-convert-to-scm
          a function returning the C code to be used to convert this type from a C representation to a Scheme representation.

     fn-convert-from-scm
          a function returning the C code to be used to convert this type from a Scheme representation to a C representation.

     fn-scm-is-a
          a function returning the C code to be used to test if a Scheme object is of this type.

     c-cleanup-arg-default?
          should arguments of this type have their C representations (the ones created for the purpose of the C-side function call) be cleaned up just after the call by default?

     c-cleanup-ret-default?
          should return values of this type have their C representations (the ones returned by a C-side function call) cleaned up just after they are converted to Scheme, but before the wrapper code returns to Scheme by default?

     fn-c-cleanup
          a function returning the C code to be used to clean up (destroy, delete, free, whatever) C representations of this type.

     To understand what the cleanup-related arguments do, consider a typical wrapper call-sequence.  First the Scheme wrapper function is called. Then all of the Scheme arguments are converted to C representations using the convert-to-scm functions, then the C function is called with these arguments, and finally, the return value, if any is converted from its C representation back to a Scheme value and returned from the wrapper.

     The cleanup arguments control the final disposition of the C representations of the given type when used as arguments and return values.  If an argument is marked as 'cleanup, then just after the C function returns, the argument will be cleaned up using the c-cleanup function provided by FN-C-CLEANUP.  The same thing happens to the C representation of the return value just after it has been converted to a Scheme representation, and just before the wrapper returns.

     An argument or return value is considered to be "marked as 'cleanup" if either C-CLEANUP-ARG-DEFAULT? or C-CLEANUP-RET-DEFAULT? is not #f respectively, or if the argument or return value is marked 'cleanup in the options to NEW-FUNCTION.  For more details see Defining a new function.

     Deciding when cleanup is appropriate depends on the semantics of both the type in question and of a given C function.  What's really at issue here is the "ownership" of the C level data involved.  For example, imagine you have a C function that takes a string pointer as an argument and expects that at the time of the call, it becomes the "owner" of that pointer, and perhaps it takes that pointer and stores it in a hash table for later use.  If that particular argument were marked as 'cleanup in g-wrap, as soon as the C function was called, g-wrap would arrange for it to be freed, leaving the pointer in the hash table dangling.  So for this particular hypothetical function, the argument in question needs to be marked as 'no-cleanup, either as the type default (probably not a good idea for strings in general), or in the NEW-FUNCTION declaration.  For more details see Defining a new function.

     Similar considerations apply to return values.  If you had a C function that returned a constant string pointer from some static or global table, then it wouldn't be appropriate for the return value to be marked 'cleanup.

     Conversely there may also be types for which 'no-cleanup makes the most sense as a default, and then 'cleanup would need to be used in calls to NEW-FUNCTION occasionally.  For more details see Defining a new function.

     Example:

          (add-new-type
           'bar
           (make-complex-c-type
            "bar"
            ;; fn-convert-to-scm
            (lambda (x) (list "bar2scm(" x ")"))
            ;; fn-convert-from-scm
            (lambda (x) (list "scm2bar(" x ")"))
            ;; fn-scm-is-a
            (lambda (x) (list "bar_p(" x ")"))
            ;; c-cleanup-arg-default?
            #t
            ;; c-cleanup-ret-default?
            #t
            ;; fn-c-cleanup
            (lambda (x) (list "free_bar(" x ")"))))

Additional issues
*****************

The most difficult issue with wrapping a C library for use with a Scheme interpreter seems to be the issue of memory management.  g-wrap does not try to deal much with this issue because it is a messy one.  One assumption made by the code generator is that objects are maintained in the Scheme world---when the interpreter no longer references an object, it may be garbage-collected and de-allocated.  Another assumption is that any object returned by a call to a C function is a new object which the interpreter will wrap in a new Scheme object.  If this is not true, then it is possible for multiple Scheme objects to refer to a single C object, and serious errors can occur.  I have written code which uses some fancy tricks to get around this problem for certain specific cases, but there is no simple way to deal with this problem in general without the C library to have specific support for helping the interpreter out.  Future versions of g-wrap may incorporate some support for helping the C library cooperate with this issue by storing the Scheme representation of an object inside the object itself.