Merged first chunk of Guile changes contributed by John Lenz.

git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@4858 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
Matthias Köppe 2003-06-03 22:12:50 +00:00
commit 34ea7f03ef
22 changed files with 1061 additions and 460 deletions

View file

@ -11,21 +11,28 @@
<!-- INDEX -->
<ul>
<li><a href="#n2">Meaning of "Module"</a>
<li><a href="#n3">Linkage</a>
<li><a href="#n3">Using the SCM or GH Guile API</a>
<li><a href="#n4">Linkage</a>
<ul>
<li><a href="#n4">Simple Linkage</a>
<li><a href="#n5">Passive Linkage</a>
<li><a href="#n6">Native Guile Module Linkage</a>
<li><a href="#n7">Old Auto-Loading Guile Module Linkage</a>
<li><a href="#n8">Hobbit4D Linkage</a>
<li><a href="#n9">General Remarks on Multiple SWIG Modules</a>
<li><a href="#n5">Simple Linkage</a>
<li><a href="#n6">Passive Linkage</a>
<li><a href="#n7">Native Guile Module Linkage</a>
<li><a href="#n8">Old Auto-Loading Guile Module Linkage</a>
<li><a href="#n9">Hobbit4D Linkage</a>
<li><a href="#n10">General Remarks on Multiple SWIG Modules</a>
</ul>
<li><a href="#n10">Underscore Folding</a>
<li><a href="#n11">Typemaps</a>
<li><a href="#n12">Smobs</a>
<li><a href="#n13">Exception Handling</a>
<li><a href="#n14">Procedure documentation</a>
<li><a href="#n15">Procedures with setters</a>
<li><a href="#n11">Underscore Folding</a>
<li><a href="#n12">Typemaps</a>
<li><a href="#n13">Smobs</a>
<ul>
<li><a href="#n14">GH API</a>
<li><a href="#n15">SCM API</a>
<li><a href="#n16">Garbage Collection</a>
<!--<li><a href="#n17">GOOPS</a>-->
</ul>
<li><a href="#n18">Exception Handling</a>
<li><a href="#n19">Procedure documentation</a>
<li><a href="#n20">Procedures with setters</a>
</ul>
<!-- INDEX -->
@ -44,7 +51,56 @@ There are three different concepts of "module" involved, defined
separately for SWIG, Guile, and Libtool. To avoid horrible confusion,
we explicitly prefix the context, e.g., "guile-module".
<a name="n3"></a><H2>14.2 Linkage</H2>
<a name="n3"></a><H2>14.2 Using the SCM or GH Guile API</H2>
<p>The guile module can currently export wrapper files that use the guile GH interface or the
SCM interface. This is controlled by an argument passed to swig. The "-gh" argument causes swig
to output GH code, and the "-scm" argument causes swig to output SCM code. Right now the "-gh" argument
is the default. The "-scm" wrapper generation assumes a guile version >= 1.6 and has several advantages over
the "-gh" wrapper generation including garbage collection and possibly GOOPS support in the future.
The "-gh" wrapper generation can be used for older versions of guile. Thus eventually
the guile GH wrapper code generation will be depreciated (as guile 1.6 and above become more common) and the
SCM interface will become the default. The SCM and GH interface differ greatly in how they store
pointers and have completly different run-time code. See below for more info.
<code>make runtime</code> will now produce two libraries, libguilegh and libguilescm containing the
runtime code using the two different guile API's.</p>
<p>The GH interface to guile is deprecated. Read more about why in the
<a href="http://www.gnu.org/software/guile/docs/guile-ref/GH-deprecation.html">Guile manual</a>.
The idea of the GH interface was to provide a high level API that other languages and projects
could adopt. This was a good idea, but didn't pan out well for general development. But for the
specific, minimal uses that the SWIG typemaps put the GH interface to use is ideal for
using a high level API. So even though the GH interface is depreciated, SWIG will continue to use
the GH interface and provide mappings from the GH interface to whatever API we need.
We can maintain this mapping where guile failed because SWIG uses a small subset of all the GH functions
which map easily. All the guile typemaps like typemaps.i and std_vector.i
will continue to use the GH functions to do things like create lists of values, convert strings to
integers, etc. Then every language module will define a mapping between the GH interface and
whatever custom API the language uses. This is currently implemented by the guile module to use
the SCM guile API rather than the GH guile API.
For example, here are some of the current mapping file for the SCM API</p>
<blockquote><pre>
#define gh_append2(a, b) scm_append(scm_listify(a, b, SCM_UNDEFINED))
#define gh_apply(a, b) scm_apply(a, b, SCM_EOL)
#define gh_bool2scm SCM_BOOL
#define gh_boolean_p SCM_BOOLP
#define gh_car SCM_CAR
#define gh_cdr SCM_CDR
#define gh_cons scm_cons
#define gh_double2scm scm_make_real
...
</pre></blockquote>
<p>This file is parsed by SWIG at wrapper generation time, so every reference to a gh_ function is replaced
by a scm_ function in the wrapper file. Thus the gh_ function calls will never be seen in the wrapper;
the wrapper will look exactly like it was generated
for the specific API. Currently only the guile language module has created a mapping policy from gh_ to scm_,
but there is no reason other languages (like mzscheme or chicken) couldn't also use this.
If that happens, there is A LOT less code duplication in the standard typemaps.</p>
<a name="n4"></a><H2>14.3 Linkage</H2>
</a>
@ -54,7 +110,7 @@ Guile support is complicated by a lack of user community cohesiveness,
which manifests in multiple shared-library usage conventions. A set of
policies implementing a usage convention is called a <b>linkage</b>.
<a name="n4"></a><H3>14.2.1 Simple Linkage</H3>
<a name="n5"></a><H3>14.3.1 Simple Linkage</H3>
The default linkage is the simplest; nothing special is done. In this
@ -127,7 +183,7 @@ placed between the <code>define-module</code> form and the
<code>SWIG_init</code> via a preprocessor define to avoid symbol
clashes. For this case, however, passive linkage is available.
<a name="n5"></a><H3>14.2.2 Passive Linkage</H3>
<a name="n6"></a><H3>14.3.2 Passive Linkage</H3>
<p>Passive linkage is just like simple linkage, but it generates an
@ -137,7 +193,7 @@ package name (see below).
<p>You should use passive linkage rather than simple linkage when you
are using multiple modules.
<a name="n6"></a><H3>14.2.3 Native Guile Module Linkage</H3>
<a name="n7"></a><H3>14.3.3 Native Guile Module Linkage</H3>
<p>SWIG can also generate wrapper code that does all the Guile module
@ -178,7 +234,7 @@ Newer Guile versions have a shorthand procedure for this:
</blockquote>
</ul>
<a name="n7"></a><H3>14.2.4 Old Auto-Loading Guile Module Linkage</H3>
<a name="n8"></a><H3>14.3.4 Old Auto-Loading Guile Module Linkage</H3>
<p>Guile used to support an autoloading facility for object-code
@ -204,7 +260,7 @@ option, SWIG generates an exported module initialization function with
an apropriate name.
<a name="n8"></a><H3>14.2.5 Hobbit4D Linkage</H3>
<a name="n9"></a><H3>14.3.5 Hobbit4D Linkage</H3>
<p>
@ -227,7 +283,7 @@ my/lib/libfoo.so.X.Y.Z and friends. This scheme is still very
experimental; the (hobbit4d link) conventions are not well understood.
<a name="n9"></a><H3>14.2.6 General Remarks on Multiple SWIG Modules</H3>
<a name="n10"></a><H3>14.3.6 General Remarks on Multiple SWIG Modules</H3>
If you want to use multiple SWIG modules, they have to share some
@ -241,13 +297,13 @@ with the C compiler switch <code>-DSWIG_GLOBAL</code>.
<li>Or generate all wrapper modules with the <code>-c</code>
command-line argument and compile all wrapper files with the C
compiler switch <code>-DSWIG_GLOBAL</code>. Then link against the
runtime library <code>libswigguile</code>, which is built by
runtime library <code>libswigguile</code> or <code>libswigguilescm</code>, which is built by
<code>make runtime</code>. The needed linker flags are reported by
SWIG if you invoke it with the <code>-guile -ldflags</code>
command-line arguments.
</ul>
<a name="n10"></a><H2>14.3 Underscore Folding</H2>
<a name="n11"></a><H2>14.4 Underscore Folding</H2>
</a>
@ -261,7 +317,7 @@ complained so far.
<code>%rename</code> to specify the Guile name of the wrapped
functions and variables (see CHANGES).
<a name="n11"></a><H2>14.4 Typemaps</H2>
<a name="n12"></a><H2>14.5 Typemaps</H2>
</a>
@ -273,8 +329,8 @@ information is read from <code>Lib/guile/typemaps.i</code>.
Some non-standard typemap substitutions are supported:
<ul>
<li><code>$descriptor</code> expands to a type descriptor for use with
the <code>SWIG_Guile_MakePtr()</code> and
<code>SWIG_Guile_GetPtr</code> functions.
the <code>SWIG_NewPointerObj()</code> and
<code>SWIG_ConvertPtr</code> functions.
<li>For pointer types, <code>$*descriptor</code> expands to a
descriptor for the direct base type (i.e., one pointer is stripped),
whereas <code>$basedescriptor</code> expands to a
@ -282,7 +338,7 @@ descriptor for the base type (i.e., all pointers are stripped).
</ul>
<p>A function returning <code>void</code> (more precisely, a function
whose <code>out</code> typemap returns <code>GH_UNSPECIFIED</code>) is
whose <code>out</code> typemap returns <code>SCM_UNSPECIFIED</code>) is
treated as returning no values. In <code>argout</code> typemaps, one
can use the macro <code>GUILE_APPEND_RESULT</code> in order to append
a value to the list of function return values.
@ -326,13 +382,27 @@ In <code><var>body</var></code>, the first result of
</ul>
See also the "multivalue" example.
<a name="n12"></a><H2>14.5 Smobs</H2>
</a>
<a name="n13"></a><H2>14.6 Smobs</H2>
<p>
For pointer types, SWIG uses Guile smobs.
For pointer types, SWIG uses Guile smobs. SWIG smobs print
like this: <code>#&lt;swig struct xyzzy * 0x1234affe&gt;</code> Two of
them are <code>equal?</code> if and only if they have the same type
and value.
<p>
To construct a Scheme object from a C pointer, the wrapper code calls
the function <code>SWIG_NewPointerObj()</code>, passing a pointer to a
struct representing the pointer type. The type index to store in the
upper half of the CAR is read from this struct.
To get the pointer represented by a smob, the wrapper code calls the
function <code>SWIG_ConvertPtr()</code>, passing a pointer to a struct
representing the expected pointer type. See also
<a href="Typemaps.html#n41">Section 8.8 The run-time type checker</a>.
If the Scheme object passed was not a SWIG smob representing a compatible
pointer, a <code>wrong-type-arg</code> exception is raised.
<a name="n14"></a><H3>14.6.1 GH Smobs</H3>
<p>
In earlier versions of SWIG, C pointers were represented as Scheme
@ -348,25 +418,117 @@ available. <code>SWIG_Guile_Init()</code> registers a smob type named
"swig" with Guile; its type tag is stored in the variable
<code>swig_tag</code>. The upper half of the CAR store an index into
a table of all C pointer types seen so far, to which new types seen
are appended. The CDR stores the pointer value. SWIG smobs print
like this: <code>#&lt;swig struct xyzzy * 0x1234affe&gt;</code> Two of
them are <code>equal?</code> if and only if they have the same type
and value.
are appended. The CDR stores the pointer value.
<p>
To construct a Scheme object from a C pointer, the wrapper code calls
the function <code>SWIG_Guile_MakePtr()</code>, passing a pointer to a
struct representing the pointer type. The type index to store in the
upper half of the CAR is read from this struct.
<a name="n15"></a><H3>14.6.2 SCM Smobs</H3>
<p>
To get the pointer represented by a smob, the wrapper code calls the
function <code>SWIG_Guile_GetPtr</code>, passing a pointer to a struct
representing the expected pointer type. If the
Scheme object passed was not a SWIG smob representing a compatible
pointer, a <code>wrong-type-arg</code> exception is raised.
<p>The SCM interface (using the "-scm" argument to swig) uses common.swg.
The whole type system, when it is first initialized, creates two smobs named "swig" and "collected_swig".
The swig smob is used for non-garbage collected smobs, while the collected_swig smob is used as described
below. Each smob has the same format, which is a double cell created by SCM_NEWSMOB2()
The first word of data is the pointer to the object and the second word of data is the swig_type_info *
structure describing this type. This is a lot easier than the GH interface above because we can store
a pointer to the type info structure right in the type. With the GH interface, there was not enough
room in the smob to store two whole words of data so we needed to store part of the "swig_type_info address"
in the smob tag.</p>
<a name="n13"></a><H2>14.6 Exception Handling</H2>
<a name="n16"></a><H3>14.6.3 Garbage Collection</H3>
<p>Garbage collection is a feature of the new SCM interface, and it is automaticlly included
if you pass the "-scm" flag to swig. Thus the swig garbage collection support requires guile &gt;1.6.
Garbage collection works like this. Every swig_type_info structure stores in its clientdata field a pointer
to the destructor for this type. The destructor is the generated wrapper around the delete function.
So swig still exports a wrapper for the destructor, it just does not call scm_c_define_gsubr() for
the wrapped delete function. So the only way to delete an object is from the garbage collector, since the
delete function is not available to scripts. How swig determins if a type should be garbage collected
is exactly like described in <a href="Customization.html#n9">
Section 9.2 Object ownership and %newobject</a> in the SWIG manual. All typemaps use an $owner var, and
the guile module replaces $owner with 0 or 1 depending on feature:new.</p>
<!--<a name="n17"></a><H3>14.6.4 GOOPS</H3>
<p>GOOPS support is also a feature of the new SCM interface, and the "-goops" argument to swig causes
the GOOPS class defintions to be added to the scmstub file (the "-scmstub" argument is required if the
"-goops" argument is given.</p>
This is what a sample class export would look like
<blockquote>
<pre>
(define-class &lt;Foo&gt; (&lt;swig&gt;)
(a #:allocation #:swig-virtual #:slot-ref Foo-a-get #:slot-set! Foo-a-set #:accessor a)
#:metaclass &lt;swig-metaclass&gt;
#:new-function new-Foo)
(define-method (+ (a &lt;Foo&gt;) (b &lt;Foo&gt;))
(make &lt;Foo&gt; #:init-smob (Foo-add (slot-ref a 'smob) (slot-ref b 'smob))))
(define &lt;Helloo&gt; &lt;Foo&gt;)
(define-class &lt;Bar&gt; (&lt;swig&gt;)
(Foo #:allocation #:swig-virtual-class #:slot-ref Bar-Foo-set #:slot-set! Bar-Foo-get
#:class &lt;Foo&gt; #:accessor Foo)
#:metaclass &lt;swig-metaclass&gt;
#:new-function new-Bar)
(define-method (getInt (b &lt;Bar&gt;))
(Bar-getInt (slot-ref b 'smob)))
(define-method (getSqr (b &lt;Bar&gt;) c)
(make &lt;Helloo&gt; #:init-smob (Bar-getSqr (slot-ref b 'smob) c)))
</pre>
</blockquote>
And the goops base class definitions will look like
<pre>
<blockquote>
(define-class &lt;swig-metaclass&gt; (&lt;class&gt;)
(new-function #:init-value #f))
(define-method (compute-get-n-set (class &lt;swig-metaclass&gt;) s)
(case (slot-definition-allocation s)
((#:swig-virtual)
(list
;getter
(let ((func (get-keyword #:slot-ref (slot-definition-options s) #f)))
(lambda (x) (func (slot-ref x 'smob))))
;setter
(let ((func (get-keyword #:slot-set! (slot-definition-options s) #f)))
(lambda (x val) (func (slot-ref x 'smob) val)))))
((#:swig-virtual-class)
(list
;getter
(let ((func (get-keyword #:slot-ref (slot-definition-options s) #f))
(class (get-keyword #:class (slot-definition-options s) #f)))
(lambda (x) (make class #:init-smob (func (slot-ref x 'smob)))))
;setter
(let ((func (get-keyword #:slot-set! (slot-definition-options s) #f)))
(lambda (x val) (func (slot-ref x 'smob) (func (slot-ref val 'smob)))))))
((#:swig-new-function)
(let ((shared-variable (slot-ref class 'new-function)))
(list (lambda (x) shared-variable)
(lambda (x var) (set! shared-variable var)))))
(else (next-method))))
(define-method (initialize (class &lt;swig-metaclass&gt;) initargs)
(slot-set! class 'new-function (get-keyword #:new-function initargs #f))
(next-method))
(define-class &lt;swig&gt; ()
(smob #:init-value #f)
(new-function #:allocation #:swig-new-function)
#:metaclass &lt;swig-metaclass&gt;)
(define-method (initialize (obj &lt;swig&gt;) initargs)
(case (car initargs)
((#:init-smob)
(slot-set! obj 'smob (cadr initargs)))
(else
(slot-set! obj 'smob (apply (slot-ref obj 'new-function) initargs)))))
</pre>
</blockquote>-->
<a name="n18"></a><H2>14.7 Exception Handling</H2>
</a>
@ -392,7 +554,7 @@ mapping:
The default when not specified here is to use "swig-error".
See Lib/exception.i for details.
<a name="n14"></a><H2>14.7 Procedure documentation</H2>
<a name="n19"></a><H2>14.8 Procedure documentation</H2>
</a>
@ -429,7 +591,7 @@ typemaps <code>indoc</code>, <code>outdoc</code>,
<code>varoutdoc</code>. See <code>Lib/guile/typemaps.i</code> for
details.
<a name="n15"></a><H2>14.8 Procedures with setters</H2>
<a name="n20"></a><H2>14.9 Procedures with setters</H2>
</a>
@ -453,4 +615,4 @@ is created, so you can use <code>(<var>struct</var>-<var>member</var>
<var>value</var>)</code> to set it.
</body>
</html>
</html>