Filewatcher File Search
FTP Search
  
Directory (beta)
  
Content Search (beta)
   
pkg://g-wrap-1.3.4-8.src.rpm:411848/g-wrap-1.3.4.tar.gz  info  downloads

g-wrap-1.3.4/0002777000175000017500000000000007562640705006476 5g-wrap-1.3.4/bin/0002777000175000017500000000000007562640704007245 5g-wrap-1.3.4/bin/g-wrap-config.in0000644000175000017500000000737207562520637012162 #!@-GUILE-@ \
-e main -s
!#
;;;; g-wrap-config --- utility for linking programs with g-wrap
;;;;
;;;; Copyright 2000 Rob Browning <rlb@defaultvalue.org>
;;;; 
;;;; This program is free software; you can redistribute it and/or
;;;; modify it under the terms of the GNU Lesser General Public
;;;; License as published by the Free Software Foundation; either
;;;; version 2.1, 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
;;;; Lesser General Public License for more details.
;;;; 
;;;; You should have received a copy of the GNU Lesser General Public
;;;; License along with this software; see the file COPYING.  If not,
;;;; write to the Free Software Foundation, Inc., 59 Temple Place,
;;;; Suite 330, Boston, MA 02111-1307 USA
;;;;

(define *program-name* #f)
(define *program-version* "@-VERSION-@")

(define (stderr . args)
  (let ((ep (current-error-port)))
    (for-each (lambda (arg) (display arg ep)) args)))

(define (stdout . args)
  (for-each display args))

(define (usage-msg)
  (let ((pr (lambda ( . msg)
              (stderr "  " *program-name* " ")
              (apply stderr msg)
              (stderr #\newline))))
    (stderr "Usage: " #\newline)
    (pr "--version                     - show version information")
    (pr "--help                        - show this message")
    (pr "--c-compile-args LANGUAGE     - C compile args for LANGUAGE")
    (pr "--c-link-args LANGUAGE        - C link args for LANGUAGE")
    (pr "--c-static-link-args LANGUAGE - C static link args for LANGUAGE")
    (pr "--guile-module-directory      - Location of guile module dir")))

(define (c-link-args language static?)
  (let* ((lib-list '(("guile" "gwrap-wct" "gwrap-glib")
                     ("rscheme" "gwraprs")))
         (libs (assoc language lib-list)))
                   
    (if libs
        (begin
          (if static?
              (for-each
               (lambda (lib) (stdout " @-libdir-@/lib" lib ".a"))
               (cdr libs))
              (begin
                (stdout "-L@-libdir-@")
                (for-each
                 (lambda (lib) (stdout " -l" lib))
                 (cdr libs))))
          (stdout #\newline)
          #t)
        (begin
          (stderr *program-name* ": unknown LANGUAGE \"" language "\" given.")
          (stderr #\newline)
          (usage-msg)
          #f))))

(define (c-compile-args language)
  (stdout "-I @-includedir-@/g-wrap" #\newline)
  #t)

(define (main args)

  (set! *program-name* (basename (car args)))

  ;; Right now we do dirt-stupid argument processing.
  (let ((rest (cdr args))
        (status #t))
    
    (cond
     ((null? rest)
      (usage-msg)
      (set! status #f))

     ;; --version
     ((equal? '("--version") rest)
      (stdout "g-wrap-config " *program-version* #\newline))

     ;; --c-compile-args LANGUAGE
     ((and (string=? "--c-compile-args" (car rest))
           (= (length rest) 2))
      (set! status (c-compile-args (cadr rest))))

     ;; --c-link-args LANGUAGE
     ((and (string=? "--c-link-args" (car rest))
           (= (length rest) 2))
      (set! status (c-link-args (cadr rest) #f)))

     ;; --c-static-link-args LANGUAGE
     ((and (string=? "--c-static-link-args" (car rest))
           (= (length rest) 2))
      (set! status (c-link-args (cadr rest) #t)))

     ;; --c-static-link-args LANGUAGE
     ((and (string=? "--guile-module-directory" (car rest))
           (= (length rest) 1))
      (stdout "@-GUILE_MODULE_DIR-@" #\newline)
      (set! status 0))

     (else
      (usage-msg)
      (set! status #f)))
    
    (quit (if status 0 1))))

;;; Local Variables:
;;; mode: scheme
;;; End:
g-wrap-1.3.4/bin/g-wrap.in0000644000175000017500000000640407562520637010712 #!@-GUILE-@ \
-e main -s
!#
;;;; g-wrap --- main g-wrap command
;;;;
;;;; Copyright 2000 Rob Browning <rlb@defaultvalue.org>
;;;; 
;;;; This program is free software; you can redistribute it and/or
;;;; modify it under the terms of the GNU Lesser General Public
;;;; License as published by the Free Software Foundation; either
;;;; version 2.1, 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
;;;; Lesser General Public License for more details.
;;;; 
;;;; You should have received a copy of the GNU Lesser General Public
;;;; License along with this software; see the file COPYING.  If not,
;;;; write to the Free Software Foundation, Inc., 59 Temple Place,
;;;; Suite 330, Boston, MA 02111-1307 USA
;;;;

(if (not (member "@-GUILE_MODULE_DIR-@" %load-path))
    (set! %load-path (cons "@-GUILE_MODULE_DIR-@" %load-path)))

(use-modules (g-wrap))

(define *program-name* #f)
(define *program-version* "@-VERSION-@")

(define (stderr . args)
  (let ((ep (current-error-port)))
    (for-each (lambda (arg) (display arg ep)) args)))

(define (stdout . args)
  (for-each display args))

(define (usage-msg)
  (let ((pr (lambda ( . msg)
              (stderr "  " *program-name* " ")
              (apply stderr msg)
              (stderr #\newline))))
    (stderr "Usage: g-wrap [options] spec-name module-name" #\newline)
    (pr "--version          - show version information")
    (pr "--help             - show this message")
    (pr "--api LANGUAGE     - language of the API being wrapped")
    (pr "--target LANGUAGE  - language for which wrappers are being generated")
    (pr "--spec-path PATH   - add directory to search for spec-name")
    (stderr #\newline)
    (stderr
     "  Example: g-wrap --api c --target guile \"(g-wrapped foo-spec)\" foo")
    (stderr #\newline)))

(define (main args)
  
  (set! *program-name* (basename (car args)))
  
  ;; Right now we do dirt-stupid argument processing.
  (let* ((rest (cdr args))
         (command-args (if (= (length rest) 6)
                           (reverse (cddr (reverse rest)))
                           #f))
         (module-name (if (= (length rest) 5)
                          (car (reverse rest))
                          #f))
         (spec-name (if (= (length rest) 5)
                        (cadr (reverse rest))
                        #f)))   
    (cond
     ((null? rest)
      (usage-msg)
      (quit 1))
     
     ;; --version
     ((equal? '("--version") rest)
      (stdout "g-wrap " *program-version* #\newline)
      (quit 0))
     
     ;; wrapping for guile
     ((or (equal? '("--api" "c" "--target" "guile") command-args)
          (equal? '("--target" "guile" "--api" "c") command-args))
      (use-modules (g-wrapper (string->symbol spec-name)))
      (gw:generate-module module-name)
      (quit 0))
     
     ;; wrapping for rscheme
     ((or (equal? '("--api" "c" "--target" "rscheme") command-args)
          (equal? '("--target" "rscheme" "--api" "c") command-args))
      (stdout "rscheme support is currently out-of-date.\n"))
     
     (else
      (usage-msg)
      1))))
     
;;; Local Variables:
;;; mode: scheme
;;; End:

g-wrap-1.3.4/bin/Makefile.am0000644000175000017500000000236207562520637011220 
# Initializations
bin_SCRIPTS =
CLEANFILES =
EXTRA_DIST =

bin_SCRIPTS += g-wrap-config
CLEANFILES += g-wrap-config
EXTRA_DIST += g-wrap-config.in g-wrap.in
EXTRA_DIST += .cvsignore

## We borrow guile's convention and use @-...-@ as the substitution
## brackets here, instead of the usual @...@.  This prevents autoconf
## from substituting the values directly into the left-hand sides of
## the sed substitutions.  *sigh*

# Depend on Makefile so that we pick up changes to ../configure
g-wrap: g-wrap.in Makefile
	rm -f $@.tmp
	sed < $@.in > $@.tmp \
            -e 's:@-GUILE-@:${GUILE}:' \
            -e 's:@-VERSION-@:${VERSION}:' \
	    -e 's:@-GUILE_MODULE_DIR-@:${GUILEMODDIR}:'
	chmod +x $@.tmp
	mv $@.tmp $@

## We borrow guile's convention and use @-...-@ as the substitution
## brackets here, instead of the usual @...@.  This prevents autoconf
## from substituting the values directly into the left-hand sides of
## the sed substitutions.  *sigh*

g-wrap-config: g-wrap-config.in
	rm -f $@.tmp
	sed < $@.in > $@.tmp \
	    -e 's:@-GUILE-@:${GUILE}:' \
	    -e 's:@-VERSION-@:${VERSION}:' \
	    -e 's:@-libdir-@:${libdir}:' \
	    -e 's:@-includedir-@:${includedir}:' \
	    -e 's:@-GUILE_MODULE_DIR-@:${GUILEMODDIR}:'
	chmod +x $@.tmp
	mv $@.tmp $@
g-wrap-1.3.4/bin/Makefile.in0000644000175000017500000002261407562640116011226 # Makefile.in generated by automake 1.7.1 from Makefile.am.
# @configure_input@

# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
# Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.

@SET_MAKE@

srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = ..

am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
INSTALL = @INSTALL@
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
host_triplet = @host@
ACLOCAL = @ACLOCAL@
AMDEP_FALSE = @AMDEP_FALSE@
AMDEP_TRUE = @AMDEP_TRUE@
AMTAR = @AMTAR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
BIN_TARGET = @BIN_TARGET@
BUILD_GUILE = @BUILD_GUILE@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
ECHO = @ECHO@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
GUILE = @GUILE@
GUILEMODDIR = @GUILEMODDIR@
GUILEMOD_TARGET = @GUILEMOD_TARGET@
GUILE_LIBS = @GUILE_LIBS@
GUILE_SCMDIR = @GUILE_SCMDIR@
GUILE_TARGET = @GUILE_TARGET@
GW_BUILD_GUILE_GTK = @GW_BUILD_GUILE_GTK@
GW_GLIB_CONFIG = @GW_GLIB_CONFIG@
GW_GTK_CONFIG = @GW_GTK_CONFIG@
GW_GUILE_GTK_CFLAGS = @GW_GUILE_GTK_CFLAGS@
GW_GUILE_GTK_LIBFLAGS = @GW_GUILE_GTK_LIBFLAGS@
GW_HAVE_GLIB_FALSE = @GW_HAVE_GLIB_FALSE@
GW_HAVE_GLIB_TRUE = @GW_HAVE_GLIB_TRUE@
GW_HAVE_GTK_FALSE = @GW_HAVE_GTK_FALSE@
GW_HAVE_GTK_TRUE = @GW_HAVE_GTK_TRUE@
GW_HAVE_GUILE_GTK_FALSE = @GW_HAVE_GUILE_GTK_FALSE@
GW_HAVE_GUILE_GTK_TRUE = @GW_HAVE_GUILE_GTK_TRUE@
GW_WCT_INTERFACE_AGE = @GW_WCT_INTERFACE_AGE@
GW_WCT_INTERFACE_MAJOR_VER = @GW_WCT_INTERFACE_MAJOR_VER@
GW_WCT_INTERFACE_REVISION = @GW_WCT_INTERFACE_REVISION@
G_WRAP_LOAD_DIR = @G_WRAP_LOAD_DIR@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LDFLAGS = @LDFLAGS@
LGWRAP_GLIB_AGE = @LGWRAP_GLIB_AGE@
LGWRAP_GLIB_MAJOR_VER = @LGWRAP_GLIB_MAJOR_VER@
LGWRAP_GLIB_REVISION = @LGWRAP_GLIB_REVISION@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
MAINT = @MAINT@
MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@
MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@
MAKEINFO = @MAKEINFO@
OBJEXT = @OBJEXT@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
RANLIB = @RANLIB@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
VERSION = @VERSION@
ac_ct_CC = @ac_ct_CC@
ac_ct_RANLIB = @ac_ct_RANLIB@
ac_ct_STRIP = @ac_ct_STRIP@
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
am__include = @am__include@
am__quote = @am__quote@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
datadir = @datadir@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localstatedir = @localstatedir@
mandir = @mandir@
oldincludedir = @oldincludedir@
prefix = @prefix@
program_transform_name = @program_transform_name@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@

# Initializations
bin_SCRIPTS = g-wrap-config
CLEANFILES = g-wrap-config
EXTRA_DIST = g-wrap-config.in g-wrap.in .cvsignore
subdir = bin
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
SCRIPTS = $(bin_SCRIPTS)

DIST_SOURCES =
DIST_COMMON = Makefile.am Makefile.in
all: all-am

.SUFFIXES:
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am  $(top_srcdir)/configure.in $(ACLOCAL_M4)
	cd $(top_srcdir) && \
	  $(AUTOMAKE) --gnu  bin/Makefile
Makefile: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.in  $(top_builddir)/config.status
	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)
binSCRIPT_INSTALL = $(INSTALL_SCRIPT)
install-binSCRIPTS: $(bin_SCRIPTS)
	@$(NORMAL_INSTALL)
	$(mkinstalldirs) $(DESTDIR)$(bindir)
	@list='$(bin_SCRIPTS)'; for p in $$list; do \
	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
	  if test -f $$d$$p; then \
	    f=`echo "$$p" | sed 's|^.*/||;$(transform)'`; \
	    echo " $(binSCRIPT_INSTALL) $$d$$p $(DESTDIR)$(bindir)/$$f"; \
	    $(binSCRIPT_INSTALL) $$d$$p $(DESTDIR)$(bindir)/$$f; \
	  else :; fi; \
	done

uninstall-binSCRIPTS:
	@$(NORMAL_UNINSTALL)
	@list='$(bin_SCRIPTS)'; for p in $$list; do \
	  f=`echo "$$p" | sed 's|^.*/||;$(transform)'`; \
	  echo " rm -f $(DESTDIR)$(bindir)/$$f"; \
	  rm -f $(DESTDIR)$(bindir)/$$f; \
	done

mostlyclean-libtool:
	-rm -f *.lo

clean-libtool:
	-rm -rf .libs _libs

distclean-libtool:
	-rm -f libtool
uninstall-info-am:
tags: TAGS
TAGS:

ctags: CTAGS
CTAGS:

DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)

top_distdir = ..
distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)

distdir: $(DISTFILES)
	@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
	list='$(DISTFILES)'; for file in $$list; do \
	  case $$file in \
	    $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
	    $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
	  esac; \
	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
	  dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
	  if test "$$dir" != "$$file" && test "$$dir" != "."; then \
	    dir="/$$dir"; \
	    $(mkinstalldirs) "$(distdir)$$dir"; \
	  else \
	    dir=''; \
	  fi; \
	  if test -d $$d/$$file; then \
	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
	    fi; \
	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
	  else \
	    test -f $(distdir)/$$file \
	    || cp -p $$d/$$file $(distdir)/$$file \
	    || exit 1; \
	  fi; \
	done
check-am: all-am
check: check-am
all-am: Makefile $(SCRIPTS)

installdirs:
	$(mkinstalldirs) $(DESTDIR)$(bindir)

install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am

install-am: all-am
	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am

installcheck: installcheck-am
install-strip:
	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
	  INSTALL_STRIP_FLAG=-s \
	  `test -z '$(STRIP)' || \
	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:

clean-generic:
	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)

distclean-generic:
	-rm -f Makefile $(CONFIG_CLEAN_FILES)

maintainer-clean-generic:
	@echo "This command is intended for maintainers to use"
	@echo "it deletes files that may require special tools to rebuild."
clean: clean-am

clean-am: clean-generic clean-libtool mostlyclean-am

distclean: distclean-am

distclean-am: clean-am distclean-generic distclean-libtool

dvi: dvi-am

dvi-am:

info: info-am

info-am:

install-data-am:

install-exec-am: install-binSCRIPTS

install-info: install-info-am

install-man:

installcheck-am:

maintainer-clean: maintainer-clean-am

maintainer-clean-am: distclean-am maintainer-clean-generic

mostlyclean: mostlyclean-am

mostlyclean-am: mostlyclean-generic mostlyclean-libtool

pdf: pdf-am

pdf-am:

ps: ps-am

ps-am:

uninstall-am: uninstall-binSCRIPTS uninstall-info-am

.PHONY: all all-am check check-am clean clean-generic clean-libtool \
	distclean distclean-generic distclean-libtool distdir dvi \
	dvi-am info info-am install install-am install-binSCRIPTS \
	install-data install-data-am install-exec install-exec-am \
	install-info install-info-am install-man install-strip \
	installcheck installcheck-am installdirs maintainer-clean \
	maintainer-clean-generic mostlyclean mostlyclean-generic \
	mostlyclean-libtool pdf pdf-am ps ps-am uninstall uninstall-am \
	uninstall-binSCRIPTS uninstall-info-am


# Depend on Makefile so that we pick up changes to ../configure
g-wrap: g-wrap.in Makefile
	rm -f $@.tmp
	sed < $@.in > $@.tmp \
            -e 's:@-GUILE-@:${GUILE}:' \
            -e 's:@-VERSION-@:${VERSION}:' \
	    -e 's:@-GUILE_MODULE_DIR-@:${GUILEMODDIR}:'
	chmod +x $@.tmp
	mv $@.tmp $@

g-wrap-config: g-wrap-config.in
	rm -f $@.tmp
	sed < $@.in > $@.tmp \
	    -e 's:@-GUILE-@:${GUILE}:' \
	    -e 's:@-VERSION-@:${VERSION}:' \
	    -e 's:@-libdir-@:${libdir}:' \
	    -e 's:@-includedir-@:${includedir}:' \
	    -e 's:@-GUILE_MODULE_DIR-@:${GUILEMODDIR}:'
	chmod +x $@.tmp
	mv $@.tmp $@
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
g-wrap-1.3.4/bin/.cvsignore0000644000175000017500000000004307562520637011156 Makefile
Makefile.in
g-wrap-config
g-wrap-1.3.4/doc/0002777000175000017500000000000007562640704007242 5g-wrap-1.3.4/doc/g-wrap.info-10000644000175000017500000014137707562640165011402 This is g-wrap.info, produced by makeinfo version 4.2 from g-wrap.texi.


File: g-wrap.info,  Node: Top,  Next: Copying,  Prev: (dir),  Up: (dir)

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.

* Menu:

* Copying::
* Introduction::
* Usage::
* Extending G-wrap::
* Reference::
* Functions for describing C code to import to the interpreter::
* C code needed for adding new types::
* Generating and using the glue code::
* Types available by default::
* Extending g-wrap and porting it to other Scheme implementations::
* Portable "Fancy tricks"::

 --- The Detailed Node Listing ---

Introduction

* Caveats::
* Overview::
* Why Create a Wrapper Generator?::

Usage

* A More Detailed Example.::
* Creating a Wrapper Module::
* Defining New Wrapped Types::
* 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

* Defining a new function::
* Adding a new type::
* Defining a new constant::
* Other functions needed for describing the library glue code::
* Example of a library description::

Defining a new function

* Manually defining functions::
* Scanning source code for functions to export::

Manually defining functions

* Scanning source code for functions to export::

C code needed for adding new types

* Utility functions::
* Printing object representations::
* Function for deallocating an object::
* Function for object comparisons::

Generating and using the glue code

* Generating the glue code::
* Accessing the wrapped API from the target language::
* Coping With Old Guile Versions::

Types available by default

* Guile Types::
* RScheme Types::

Guile Types

* Pointer Tokens and Pointer Arrays::

Pointer Tokens and Pointer Arrays

* Pointer Tokens::
* Pointer Arrays::

Extending g-wrap and porting it to other Scheme implementations

* Defining basic Scheme/C types::


File: g-wrap.info,  Node: Copying,  Next: Introduction,  Prev: Top,  Up: Top

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.


File: g-wrap.info,  Node: Introduction,  Next: Usage,  Prev: Copying,  Up: Top

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

* Menu:

* Caveats::
* Overview::
* Why Create a Wrapper Generator?::


File: g-wrap.info,  Node: Caveats,  Next: Overview,  Prev: Introduction,  Up: 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 :>



File: g-wrap.info,  Node: Overview,  Next: Why Create a Wrapper Generator?,  Prev: Caveats,  Up: Introduction

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

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

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


File: g-wrap.info,  Node: Why Create a Wrapper Generator?,  Prev: Overview,  Up: Introduction

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


File: g-wrap.info,  Node: Usage,  Next: Extending G-wrap,  Prev: Introduction,  Up: Top

Usage
*****

* Menu:

* A More Detailed Example.::
* Creating a Wrapper Module::
* Defining New Wrapped Types::
* Wrapping C Functions::
* Generating the Wrapper Code::
* Using the Wrapped Interface::


File: g-wrap.info,  Node: A More Detailed Example.,  Next: Creating a Wrapper Module,  Prev: Usage,  Up: 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.


File: g-wrap.info,  Node: Creating a Wrapper Module,  Next: Defining New Wrapped Types,  Prev: A More Detailed Example.,  Up: Usage

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>


File: g-wrap.info,  Node: Defining New Wrapped Types,  Next: Wrapping C Functions,  Prev: Creating a Wrapper Module,  Up: Usage

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.(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 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:(2)


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

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

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

(2) 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.


File: g-wrap.info,  Node: Wrapping C Functions,  Next: Generating the Wrapper Code,  Prev: Defining New Wrapped Types,  Up: Usage

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


File: g-wrap.info,  Node: Generating the Wrapper Code,  Next: Using the Wrapped Interface,  Prev: Wrapping C Functions,  Up: Usage

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


File: g-wrap.info,  Node: Using the Wrapped Interface,  Prev: Generating the Wrapper Code,  Up: Usage

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


File: g-wrap.info,  Node: Extending G-wrap,  Next: Reference,  Prev: Usage,  Up: Top

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

* Menu:

* Other Internal Details::
* Adding New Wrapper Types::


File: g-wrap.info,  Node: Other Internal Details,  Next: Adding New Wrapper Types,  Prev: Extending G-wrap,  Up: Extending G-wrap

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


File: g-wrap.info,  Node: Adding New Wrapper Types,  Prev: Other Internal Details,  Up: Extending G-wrap

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


File: g-wrap.info,  Node: Reference,  Next: Functions for describing C code to import to the interpreter,  Prev: Extending G-wrap,  Up: Top

Reference
*********

* Menu:

* Wrapper Module Operations::
* Defining Wrapped Types::
* Defining New Wrapper Types::
* Wrapping Functions::
* Wrapper Types Available by Default::
* Wrapped Types Available by Default::


File: g-wrap.info,  Node: Wrapper Module Operations,  Next: Defining Wrapped Types,  Prev: Reference,  Up: Reference

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


File: g-wrap.info,  Node: Defining Wrapped Types,  Next: Defining New Wrapper Types,  Prev: Wrapper Module Operations,  Up: Reference

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


File: g-wrap.info,  Node: Defining New Wrapper Types,  Next: Wrapping Functions,  Prev: Defining Wrapped Types,  Up: Reference

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


File: g-wrap.info,  Node: Wrapping Functions,  Next: Wrapper Types Available by Default,  Prev: Defining New Wrapper Types,  Up: Reference

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


File: g-wrap.info,  Node: Wrapper Types Available by Default,  Next: Wrapped Types Available by Default,  Prev: Wrapping Functions,  Up: Reference

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


File: g-wrap.info,  Node: Wrapped Types Available by Default,  Prev: Wrapper Types Available by Default,  Up: Reference

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


File: g-wrap.info,  Node: Functions for describing C code to import to the interpreter,  Next: C code needed for adding new types,  Prev: Reference,  Up: Top

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 *Note Example of a library description::.

* Menu:

* Defining a new function::
* Adding a new type::
* Defining a new constant::
* Other functions needed for describing the library glue code::
* Example of a library description::


File: g-wrap.info,  Node: Defining a new function,  Next: Adding a new type,  Prev: Functions for describing C code to import to the interpreter,  Up: Functions for describing C code to import to the interpreter

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

* Menu:

* Manually defining functions::
* Scanning source code for functions to export::


File: g-wrap.info,  Node: Manually defining functions,  Next: Scanning source code for functions to export,  Prev: Defining a new function,  Up: 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.")


* Menu:

* Scanning source code for functions to export::


File: g-wrap.info,  Node: Scanning source code for functions to export,  Prev: Manually defining functions,  Up: Defining a new function

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")



File: g-wrap.info,  Node: Adding a new type,  Next: Defining a new constant,  Prev: Defining a new function,  Up: Functions for describing C code to import to the interpreter

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 *Note C code needed for adding new types:: to
          see how to  write these functions.

        *  This allows `MAT's 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.


File: g-wrap.info,  Node: Defining a new constant,  Next: Other functions needed for describing the library glue code,  Prev: Adding a new type,  Up: Functions for describing C code to import to the interpreter

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


File: g-wrap.info,  Node: Other functions needed for describing the library glue code,  Next: Example of a library description,  Prev: Defining a new constant,  Up: Functions for describing C code to import to the interpreter

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.


File: g-wrap.info,  Node: Example of a library description,  Prev: Other functions needed for describing the library glue code,  Up: Functions for describing C code to import to the interpreter

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)


File: g-wrap.info,  Node: C code needed for adding new types,  Next: Generating and using the glue code,  Prev: Functions for describing C code to import to the interpreter,  Up: Top

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.

* Menu:

* Utility functions::
* Printing object representations::
* Function for deallocating an object::
* Function for object comparisons::


File: g-wrap.info,  Node: Utility functions,  Next: Printing object representations,  Prev: C code needed for adding new types,  Up: C code needed for adding new types

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.


File: g-wrap.info,  Node: Printing object representations,  Next: Function for deallocating an object,  Prev: Utility functions,  Up: C code needed for adding new types

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); }
     }


File: g-wrap.info,  Node: Function for deallocating an object,  Next: Function for object comparisons,  Prev: Printing object representations,  Up: C code needed for adding new types

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 *);


File: g-wrap.info,  Node: Function for object comparisons,  Prev: Function for deallocating an object,  Up: C code needed for adding new types

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;
     }


File: g-wrap.info,  Node: Generating and using the glue code,  Next: Types available by default,  Prev: C code needed for adding new types,  Up: Top

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

* Menu:

* Generating the glue code::
* Accessing the wrapped API from the target language::
* Coping With Old Guile Versions::


File: g-wrap.info,  Node: Generating the glue code,  Next: Accessing the wrapped API from the target language,  Prev: Generating and using the glue code,  Up: 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

g-wrap-1.3.4/doc/g-wrap.info-20000644000175000017500000006043107562640165011372 This is g-wrap.info, produced by makeinfo version 4.2 from g-wrap.texi.


File: g-wrap.info,  Node: Accessing the wrapped API from the target language,  Next: Coping With Old Guile Versions,  Prev: Generating the glue code,  Up: Generating and using the glue code

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.


File: g-wrap.info,  Node: Coping With Old Guile Versions,  Prev: Accessing the wrapped API from the target language,  Up: Generating and using the glue code

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.


File: g-wrap.info,  Node: Types available by default,  Next: Extending g-wrap and porting it to other Scheme implementations,  Prev: Generating and using the glue code,  Up: Top

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

* Menu:

* Guile Types::
* RScheme Types::


File: g-wrap.info,  Node: Guile Types,  Next: RScheme Types,  Prev: Types available by default,  Up: Types available by default

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 *Note
     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 *Note 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 *Note Pointer Tokens and Pointer Arrays::.

* Menu:

* Pointer Tokens and Pointer Arrays::


File: g-wrap.info,  Node: Pointer Tokens and Pointer Arrays,  Prev: Guile Types,  Up: Guile Types

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.

* Menu:

* Pointer Tokens::
* Pointer Arrays::


File: g-wrap.info,  Node: Pointer Tokens,  Next: Pointer Arrays,  Prev: Pointer Tokens and Pointer Arrays,  Up: Pointer Tokens and Pointer Arrays

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

Before deciding to use pointer tokens, please see the warning here
*Note 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.


File: g-wrap.info,  Node: Pointer Arrays,  Prev: Pointer Tokens,  Up: Pointer Tokens and Pointer Arrays

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

Before deciding to use pointer arrays, please see the warning here
*Note 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.


File: g-wrap.info,  Node: RScheme Types,  Prev: Guile Types,  Up: Types available by default

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

FIXME: not documented yet...


File: g-wrap.info,  Node: Extending g-wrap and porting it to other Scheme implementations,  Next: Portable "Fancy tricks",  Prev: Types available by default,  Up: Top

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.

* Menu:

* Defining basic Scheme/C types::


File: g-wrap.info,  Node: Defining basic Scheme/C types,  Prev: Extending g-wrap and porting it to other Scheme implementations,  Up: Extending g-wrap and porting it to other Scheme implementations

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 *Note 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 *Note 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 *Note
     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 ")"))))



File: g-wrap.info,  Node: Portable "Fancy tricks",  Prev: Extending g-wrap and porting it to other Scheme implementations,  Up: Top

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.

* Menu:

* add-new-type:                          Defining basic Scheme/C types.
* add-type <1>:                          Defining basic Scheme/C types.
* add-type:                              Adding a new type.
* get-type:                              Defining basic Scheme/C types.
* gw_error:                              Utility functions.
* gw_puts:                               Utility functions.
* gwrap-assume-types-wrapped:            Other functions needed for describing the library glue code.
* gwrap-close-module:                    Other functions needed for describing the library glue code.
* gwrap-generate-wrapped-header:         Other functions needed for describing the library glue code.
* gwrap-include-global-header:           Other functions needed for describing the library glue code.
* gwrap-include-local-header:            Other functions needed for describing the library glue code.
* gwrap-open-module:                     Other functions needed for describing the library glue code.
* gwrap-scan-source-file:                Scanning source code for functions to export.
* make-c-type:                           Defining basic Scheme/C types.
* make-complex-c-type:                   Defining basic Scheme/C types.
* new-constant:                          Defining a new constant.
* new-function:                          Manually defining functions.
* new-type:                              Adding a new type.
* pointer-array-length:                  Pointer Arrays.
* pointer-array-ref:                     Pointer Arrays.


g-wrap-1.3.4/doc/g-wrap.info0000644000175000017500000000417307562640165011234 This is g-wrap.info, produced by makeinfo version 4.2 from g-wrap.texi.


Indirect:
g-wrap.info-1: 73
g-wrap.info-2: 49919

Tag Table:
(Indirect)
Node: Top73
Node: Copying2688
Node: Introduction4503
Node: Caveats4683
Node: Overview5245
Ref: Overview-Footnote-19860
Node: Why Create a Wrapper Generator?10137
Node: Usage12198
Node: A More Detailed Example.12491
Node: Creating a Wrapper Module13593
Node: Defining New Wrapped Types18070
Ref: Defining New Wrapped Types-Footnote-125891
Ref: Defining New Wrapped Types-Footnote-226010
Node: Wrapping C Functions26175
Node: Generating the Wrapper Code26351
Node: Using the Wrapped Interface26542
Node: Extending G-wrap26704
Node: Other Internal Details26893
Node: Adding New Wrapper Types27073
Node: Reference27232
Node: Wrapper Module Operations27595
Node: Defining Wrapped Types27768
Node: Defining New Wrapper Types27952
Node: Wrapping Functions28137
Node: Wrapper Types Available by Default28318
Node: Wrapped Types Available by Default28539
Node: Functions for describing C code to import to the interpreter28733
Node: Defining a new function29566
Node: Manually defining functions29921
Node: Scanning source code for functions to export33091
Node: Adding a new type35109
Node: Defining a new constant37297
Node: Other functions needed for describing the library glue code38122
Node: Example of a library description42479
Node: C code needed for adding new types44413
Node: Utility functions45125
Node: Printing object representations45720
Node: Function for deallocating an object47223
Node: Function for object comparisons47701
Node: Generating and using the glue code48549
Node: Generating the glue code48901
Node: Accessing the wrapped API from the target language49919
Node: Coping With Old Guile Versions51578
Node: Types available by default53074
Node: Guile Types53465
Node: Pointer Tokens and Pointer Arrays56343
Node: Pointer Tokens57294
Node: Pointer Arrays59442
Node: RScheme Types62995
Node: Extending g-wrap and porting it to other Scheme implementations63150
Node: Defining basic Scheme/C types63759
Node: Portable "Fancy tricks"71858

End Tag Table
g-wrap-1.3.4/doc/g-wrap.texi0000644000175000017500000022440207562520637011252 \input texinfo @c -*-texinfo-*-
@c %**start of header
@setfilename g-wrap.info
@settitle g-wrap
@setchapternewpage on
@c Choices for setchapternewpage are {on,off,odd}.
@paragraphindent 0
@c %**end of header

@iftex
@finalout
@c DL: lose the egregious vertical whitespace, esp. around examples
@c but paras in @defun-like things don't have parindent
@parskip 4pt plus 1pt
@end iftex

@titlepage
@title g-wrap
@subtitle A tool to wrap C APIs for Guile use.
@subtitle Version 1.3.2
@subtitle April 2001
@author Christopher Lee <chrislee@@ri.cmu.edu> and Rob Browning <rlb@@defaultvalue.org>

@page
@vskip 0pt plus 1filll
Copyright @copyright{} 1996, 1997, 1998 Christopher Lee
Copyright @copyright{} 2000-2001 Rob Browning

Permission is granted to make and distribute verbatim copies of this
manual provided the copyright notice and this permission notice are
preserved on all copies.

Permission is granted to copy and distribute modified versions of this
manual under the conditions for verbatim copying, provided that the
entire resulting derived work is distributed under the terms of a
permission notice identical to this one.

Permission is granted to copy and distribute translations of this manual
into another language, under the above conditions for modified versions,
except that this permission notice may be stated in a translation
approved by the author.
@end titlepage

@node Top, Copying, (dir), (dir)
@ifinfo

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

@end ifinfo


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


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.

@menu
* Copying::                     
* Introduction::                
* Usage::                       
* Extending G-wrap::            
* Reference::                   
* Functions for describing C code to import to the interpreter::  
* C code needed for adding new types::  
* Generating and using the glue code::  
* Types available by default::  
* Extending g-wrap and porting it to other Scheme implementations::  
* Portable "Fancy tricks"::     

@detailmenu
 --- The Detailed Node Listing ---

Introduction

* Caveats::                     
* Overview::                    
* Why Create a Wrapper Generator?::  

Usage

* A More Detailed Example.::    
* Creating a Wrapper Module::   
* Defining New Wrapped Types::  
* 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

* Defining a new function::     
* Adding a new type::           
* Defining a new constant::     
* Other functions needed for describing the library glue code::  
* Example of a library description::  

Defining a new function

* Manually defining functions::  
* Scanning source code for functions to export::  

Manually defining functions

* Scanning source code for functions to export::  

C code needed for adding new types

* Utility functions::           
* Printing object representations::  
* Function for deallocating an object::  
* Function for object comparisons::  

Generating and using the glue code

* Generating the glue code::    
* Accessing the wrapped API from the target language::  
* Coping With Old Guile Versions::  

Types available by default

* Guile Types::                 
* RScheme Types::               

Guile Types

* Pointer Tokens and Pointer Arrays::  

Pointer Tokens and Pointer Arrays

* Pointer Tokens::              
* Pointer Arrays::              

Extending g-wrap and porting it to other Scheme implementations

* Defining basic Scheme/C types::  

@end detailmenu
@end menu

@c Chapter ==================================================================
@node Copying, Introduction, Top, Top
@chapter Copying

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

@noindent
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.

@center NO WARRANTY

@noindent
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.

@noindent
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.


@c Chapter ==================================================================
@node Introduction, Usage, Copying, Top
@chapter Introduction

@menu
* Caveats::                     
* Overview::                    
* Why Create a Wrapper Generator?::  
@end menu

@node Caveats, Overview, Introduction, Introduction
@section Caveats

@enumerate

@item
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.

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

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

@end enumerate

@node Overview, Why Create a Wrapper Generator?, Caveats, Introduction
@section 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

@example
  int frob(int x, double y);
@end example

@noindent
a complete g-wrap specification would look like this:

@lisp
  (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.")
@end lisp

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

@lisp
  (gw:generate-wrapset "my-g-wrap-wrapset")
@end lisp

@noindent
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 @code{frob} which you can call
as expected:

@lisp
  (frob 4 2.3)
@end lisp

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@footnote{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:

@table @samp

@item 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.

@item 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.

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

@end table

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.

@node Why Create a Wrapper Generator?,  , Overview, Introduction
@section 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 @url{ftp://ftp.gnucash.org/pub/g-wrap/}.

@c Chapter ==================================================================
@node Usage, Extending G-wrap, Introduction, Top
@chapter Usage

@menu
* A More Detailed Example.::    
* Creating a Wrapper Module::   
* Defining New Wrapped Types::  
* Wrapping C Functions::        
* Generating the Wrapper Code::  
* Using the Wrapped Interface::  
@end menu

@node A More Detailed Example., Creating a Wrapper Module, Usage, Usage
@section 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:

@example

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

@end example

@noindent
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.

@node Creating a Wrapper Module, Defining New Wrapped Types, A More Detailed Example., Usage
@section 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 @code{gw:new-module}, but before that, you have to tell Guile
that you want to use g-wrap functions with a call to @code{(use-modules
(g-wrap))}.  So the most trivial wrapper module possible would look
something like this:

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

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 @code{gw:module-depends-on} like so:

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

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

@example
  (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."))
@end example

@code{gw:wrap-function}'s arguments in order are

@enumerate

@item
the module to which the function wrapper should be added.

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

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

@item
a string giving the C function's name.

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

@item
a string describing the function.

@end enumerate

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: @code{<gw:m-chars-caller-owned>} and
@code{<gw:m-chars-callee-owned>}.  The "m" stands for @code{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 @code{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:

@example
  (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."))

@end example

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:

@example

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

@end example

@node Defining New Wrapped Types, Wrapping C Functions, Creating a Wrapper Module, Usage
@section 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.

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

  Timespec64 elapsed_time(Timespec64 start, Timespec64 finish);

@end example

and let's further presume that we've decided that you want to represent
@code{Timespec64} values on the scheme side using a cons pair where the
car will be the seconds and the cdr will be the
nanoseconds.@footnote{Though you should probably consider using the time
type from SRFI-19 @url{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 rep