This is the info manual for G-Wrap, covering versions 1.9.*.

1 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.

2 Introduction
**************

2.1 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:

       (define-module (my-wrapset)
         #:use-modules (oop goops))
         #:use-modules (g-wrap))

         #:export (<my-wrapset>))

       (define-class <my-wrapset> (<gw-guile-wrapset>)
         #:id 'my-wrapset
         #:dependencies '(standard))

       (define-method (initialize (ws <my-wrapset>) initargs)
         (next-method)

         (wrap-function! ws
                         #:name 'frob
                         #:returns 'int
                         #:arguments '((int x) (double y))
                         #:c-name "frob"
                         #:description "Return the result of frobbing x and y."))

You can see that the specification is encapsulated in a Guile module
that exports a class - `<my-wrapset>' derived from `<gw-wrapset>'. A
wrapset is the G-Wrap counterpart to some API; it describes how the API
looks in C and provides additional information for the target language.
The wrapset above doesn't yet provide any such information; it is
_abstract_ and can be refined for every target language.

In the `define-class' statement, the wrapset defines its ID, a globally
unique identifier, and declares a dependency on the `standard' wrapset,
which provides the basic C types. In the `initialize' method, the
`frob' function is wrapped, providing all relevant data such as return
and argument types.

To refine the above wrapset for Guile, you derive from it and add the
necessary information:

     (define-module (my-guile-wrapset)
       #:use-module (oop goops)
       #:use-module (g-wrap)
       #:use-module (g-wrap guile)
       #:use-module (g-wrap guile ws standard)

       #:export (<my-guile-wrapset>)

     (define-class <my-guile-wrapset> (<my-wrapset> <gw-guile-wrapset>))

     (define-method (initialize (ws <my-guile-wrapset>) initargs)
       (next-method ws (append '(#:module (my-module)) initargs)))

We derive our Guile-specific wrapset from the generic wrapset
`<my-wrapset>' and the base class for all Guile wrapsets
`<gw-guile-wrapset>'. In `initialize', we tell G-Wrap that the wrapset
should eventually reside in the Guile module `my-module'.

Once G-Wrap has seen this specification, the code for the wrappers can
be generated with this code:

       (use-modules (g-wrap) (g-wrap guile) (my-guile-wrapset))
       (generate-wrapset 'guile 'my-wrapset "my-wrapset")

This will produce the C file `my-wrapset.c', that can be compiled into
a shared library which will, when loaded by Guile, 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 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.

At the lowest level, there is a "wrapping protocol" for types, which
you can plug into to describe how a type is converted from and to the
target language as well as other aspects of the type. G-Wrap comes with
a few of these more 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:

`basic'
     wrapper types to handle C types which can be represented most
     appropriately on the Scheme side by a conversion directly to a
     native Scheme type, e.g. `double' and `char'.

`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.

Furthermore, G-Wrap allows 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 implemented as purely Scheme-code Guile
modules.  This means that you you can wrap functions for multiple
modules on the fly from any invocation of Guile.

2.2 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 `http://www.nongnu.org/g-wrap/'.

3 Usage
*******

3.1 A More Detailed Example
===========================

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

You'll see how to define a wrapset, 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 wrapset 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 wrapset "miscutils".

To define your module, you need to create a wrapper specification,
which normally consists of deriving from the `<gw-wrapset>' class and
providing an `initialize' method that adds the to-be-wrapped functions
and types.  Conventionally, if you're creating a wrapper module named
"foo", the wrapset specification file would be named foo-spec.scm, or
placed in separate `ws/' subdirectory.

3.2 Creating a Wrapset
======================

Inside the wrapset specification file, the first thing you have to do
is create the wrapset class.  But before that, you have to tell Guile
that you'll use the GOOPS and G-Wrap modules. So the most trivial
wrapper module possible would look something like this:

       (use-modules (oop goops) (g-wrap) (g-wrap guile))

       (define-class <miscutils-wrapset> (<gw-guile-wrapset>)
         #:id 'miscutils)

       (define-method (initialize (ws <miscutils-wrapset>) initargs)
         (next-method ws (append '(#:module (miscutils)) initargs)))

Note how the Guile module that the wrapset should reside in is passed
to the `next-method' of `initialize' as a keyword argument.

However, this wrapset won't let you do much.  In particular, a newly
created wrapset 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 `#:dependencies' keyword argument to the
class definition:

       (define-class <miscutils-wrapset> (<gw-guile-wrapset>)
         #:id 'miscutils
         #:dependencies '(standard))

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

       (define-method (initialize (ws <miscutils-wrapset>) initargs)
         (next-method ws (append '(#:module (miscutils)) initargs))

         (wrap-function!
           ws
           #:name 'join_strings
           #:returns 'mchars
           #:c-name "join_strings"
           #:arguments '((mchars a) (mchars b))
           #:description "Return a string consisting of a followed by b.")

         (wrap-function!
          ws
          #:name 'seconds-since-dow
          #:returns 'double
          #:c-name "seconds_since_dow"
          #:arguments '((<gw:unsigned-int> day-of-week))
          #:description "Given day-of-week (ranging 1-7), return elapsed time since then."))

`wrap-function!''s arguments should be quite obvious:

`ws'
     the module to which the function wrapper should be added.

`#:name'
     the symbol which should be bound to the wrapped function in Scheme
     at runtime.

`#:returns'
     the symbol naming the G-Wrap wrapped type of the C function result.

`#:c-name'
     a string giving the C function's name.

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

`#:description'
     a string describing the function.

Actually, the example given above won't work because specifying
`mchars' (roughly G-Wrap's type for `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 type options for string type
arguments and return values: `caller-owned' and `callee-owned'.  The
"m" in `mchars' 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 this function would be:

         (wrap-function!
           ws
           #:name 'join_strings
           #:returns '(mchars caller-owned)
           #:c-name "join_strings"
           #:arguments '(((mchars caller-owned) a) ((mchars caller-owned) b))
           #:description "Return a string consisting of a followed by b.")

At this point, we have a wrapset 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.  You could use it like this:

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

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

Though G-Wrap already provides a number of wrapped types in the
standard wrapset, 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.(1)

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 Scheme
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 "codegens") 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 `timespec64'.

To begin, you have to define a new class for your type. We derive it
from `<gw-rti-type>', which can (and should) be used instead of the
more generic `<gw-type>' in most cases(2).

       (define-class <timespec64-type> (<gw-rti-type>))

Then you can add your new type to your wrapset.  Presume that the
following code is inside the body of the `initialize' method of our
previous examples;  i.e. `ws' is bound to the miscutils wrapset you're
creating.

         (add-type! ws (make <timespec64-type>
                             #:name '<miscutils:timespec-64>
                             #:c-type-name "Timespec64"
                             #:c-const-type-name "const Timespec64"))

In order to make this type useful, you have to define some relevant
codegen methods.  Let's start with one that will tell G-Wrap how to
"unwrap" instances of this type that are passed in as arguments from
the Scheme side.

       (define-method (unwrap-value-cg (type <gw-ctype-void>)
                                       (value <gw-value>) error-var)
         (list
           "if (!msu_scm_timespec_64_p(" (scm-var value) "))"
           `(gw:error ,error-var type ,(wrapped-var value))
           "else\n"
           "  " (var value) " = msu_timespec64_to_c(" (scm-var value) ");\n"))

A codegen returns 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 `unwrap-value-cg' is called with the type that should be
"unwrapped", the actual value, which consists of a Scheme and a C
variable. As you can see this codegen grabs the Scheme name and the C
names of the value and then assignes the C value to be the result of
converting the scheme value with the hypothetical
`msu_timespec64_to_scm' function.

The list produced by `unwrap-value-cg' contains a special sublist,
starting with `gw:error'. This indicates a failure condition, which is
checked in the generated code and acted upon properly (i.e. raising an
"argument type" error).

The above codegen presumes that the C function `msu_scm_timespec_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 convert and incoming Scheme
arguments, but it doesn't know how to convert from C values to Scheme,
which is needed if you return a Timespec64. To teach it, you need to
define the `wrap-value-cg' for `<timespec64-type>', which has the duty
to "wrap" the C value for Scheme.

So in our Timespec64 example, we might define our unwrap codegen like
this:

       (define-method (wrap-value-cg (type <gw-ctype-void>)
                                     (value <gw-value>) error-var)
         (list
           (scm-var value) " = "msu_timespec64_to_scm(" (scm-var value) ");\n"))

There are a bunch of codegens you can define for a type but if you do
nothing overly fancy, you can get away with just `wrap-value-cg',
`unwrap-value-cg'. For C values that need deconstruction, there is also
`destruct-value-cg'.

---------- Footnotes ----------

(1) Though you should probably consider using the time type from
SRFI-19 `http://srfi.schemers.org/srfi-19/' instead.

(2) When `<gw-rti-type>' is used, G-Wrap is able to use shared
conversion functions and not emit code for each wrapper function, in
most cases, which can considerably reduce the emitted code size