Merge remote-tracking branch 'upstream/master' into memleak

# Conflicts:
#	CHANGES.current
This commit is contained in:
Andrew Rogers 2021-05-17 22:44:56 +01:00
commit 04a0b526eb
192 changed files with 44 additions and 23275 deletions

View file

@ -7,8 +7,8 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/
Version 4.1.0 (in progress)
===========================
2021-05-12: adr26
#1985 [Python] Fix memory leaks:
2021-05-17: adr26
[Python] #1985 Fix memory leaks:
1. Python object references were being incorrectly retained by
SwigPyClientData, causing swig_varlink_dealloc() never to run / free
@ -33,6 +33,41 @@ Version 4.1.0 (in progress)
SWIG_Python_SetModule() (failure could be caused by OOM or a name
clash caused by malicious code)
2021-05-13: olly
[UFFI] #2009 Remove code for Common Lisp UFFI. We dropped support
for it in SWIG 4.0.0 and nobody has stepped forward to revive it in
over 2 years.
2021-05-13: olly
[S-EXP] #2009 Remove code for Common Lisp S-Exp. We dropped
support for it in SWIG 4.0.0 and nobody has stepped forward to
revive it in over 2 years.
2021-05-13: olly
[Pike] #2009 Remove code for Pike. We dropped support for it in
SWIG 4.0.0 and nobody has stepped forward to revive it in over 2
years.
2021-05-13: olly
[Modula3] #2009 Remove code for Modula3. We dropped support for it
in SWIG 4.0.0 and nobody has stepped forward to revive it in over 2
years.
2021-05-13: olly
[CLISP] #2009 Remove code for GNU Common Lisp. We dropped support
for it in SWIG 4.0.0 and nobody has stepped forward to revive it in
over 2 years.
2021-05-13: olly
[Chicken] #2009 Remove code for Chicken. We dropped support for it
in SWIG 4.0.0 and nobody has stepped forward to revive it in over 2
years.
2021-05-13: olly
[Allegrocl] #2009 Remove code for Allegro Common Lisp. We dropped
support for it in SWIG 4.0.0 and nobody has stepped forward to
revive it in over 2 years.
2021-05-04: olly
[PHP] #1982 #1457 https://sourceforge.net/p/swig/bugs/1339/
SWIG now only use PHP's C API to implement its wrappers, and no

File diff suppressed because it is too large Load diff

View file

@ -1,597 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>SWIG and Chicken</title>
<link rel="stylesheet" type="text/css" href="style.css">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body bgcolor="#ffffff">
<H1><a name="Chicken">23 SWIG and Chicken</a></H1>
<!-- INDEX -->
<div class="sectiontoc">
<ul>
<li><a href="#Chicken_nn2">Preliminaries</a>
<ul>
<li><a href="#Chicken_nn3">Running SWIG in C mode</a>
<li><a href="#Chicken_nn4">Running SWIG in C++ mode</a>
</ul>
<li><a href="#Chicken_nn5">Code Generation</a>
<ul>
<li><a href="#Chicken_nn6">Naming Conventions</a>
<li><a href="#Chicken_nn7">Modules</a>
<li><a href="#Chicken_nn8">Constants and Variables</a>
<li><a href="#Chicken_nn9">Functions</a>
<li><a href="#Chicken_nn10">Exceptions</a>
</ul>
<li><a href="#Chicken_nn11">TinyCLOS</a>
<li><a href="#Chicken_nn12">Linkage</a>
<ul>
<li><a href="#Chicken_nn13">Static binary or shared library linked at compile time</a>
<li><a href="#Chicken_nn14">Building chicken extension libraries</a>
<li><a href="#Chicken_nn15">Linking multiple SWIG modules with TinyCLOS</a>
</ul>
<li><a href="#Chicken_nn16">Typemaps</a>
<li><a href="#Chicken_nn17">Pointers</a>
<ul>
<li><a href="#Chicken_collection">Garbage collection</a>
</ul>
<li><a href="#Chicken_nn18">Unsupported features and known problems</a>
<ul>
<li><a href="#Chicken_nn19">TinyCLOS problems with Chicken version &lt;= 1.92</a>
</ul>
</ul>
</div>
<!-- INDEX -->
<p>
This chapter describes SWIG's support of CHICKEN. CHICKEN is a
Scheme-to-C compiler supporting most of the language features as
defined in the <i>Revised^5 Report on Scheme</i>. Its main
attributes are that it
</p>
<ol>
<li>generates portable C code</li>
<li>includes a customizable interpreter</li>
<li>links to C libraries with a simple Foreign Function Interface</li>
<li>supports full tail-recursion and first-class continuations</li>
</ol>
<p>
When confronted with a large C library, CHICKEN users can use
SWIG to generate CHICKEN wrappers for the C library. However,
the real advantages of using SWIG with CHICKEN are its
<strong>support for C++</strong> -- object-oriented code is
difficult to wrap by hand in CHICKEN -- and its <strong>typed
pointer representation</strong>, essential for C and C++
libraries involving structures or classes.
</p>
<H2><a name="Chicken_nn2">23.1 Preliminaries</a></H2>
<p>
CHICKEN support was introduced to SWIG in version 1.3.18. SWIG
relies on some recent additions to CHICKEN, which are only
present in releases of CHICKEN with version number
<strong>greater than or equal to 1.89</strong>.
To use a chicken version between 1.40 and 1.89, see the <a href="#Chicken_collection">Garbage collection</a>
section below.
</p>
<p>
You may want to look at any of the examples in Examples/chicken/
directory for the basic steps to run SWIG CHICKEN.
</p>
<H3><a name="Chicken_nn3">23.1.1 Running SWIG in C mode</a></H3>
<p>
To run SWIG CHICKEN in C mode, use
the -chicken option.
</p>
<div class="shell">
<pre>% swig -chicken example.i</pre>
</div>
<p>
To allow the wrapper to take advantage of future CHICKEN code
generation improvements, part of the wrapper is direct CHICKEN
function calls (<tt>example_wrap.c</tt>) and part is CHICKEN
Scheme (<tt>example.scm</tt>). The basic Scheme code must
be compiled to C using your system's CHICKEN compiler or
both files can be compiled directly using the much simpler <tt>csc</tt>.
</p>
<div class="shell">
<pre>
% chicken example.scm -output-file oexample.c
</pre>
</div>
<p>
So for the C mode of SWIG CHICKEN, <tt>example_wrap.c</tt> and
<tt>oexample.c</tt> are the files that must be compiled to
object files and linked into your project.
</p>
<H3><a name="Chicken_nn4">23.1.2 Running SWIG in C++ mode</a></H3>
<p>
To run SWIG CHICKEN in C++ mode, use
the -chicken -c++ option.
</p>
<div class="shell">
<pre>% swig -chicken -c++ example.i</pre>
</div>
<p>
This will generate <tt>example_wrap.cxx</tt> and
<tt>example.scm</tt>. The basic Scheme code must be
compiled to C using your system's CHICKEN compiler or
both files can be compiled directly using the much simpler <tt>csc</tt>.
</p>
<div class="shell">
<pre>% chicken example.scm -output-file oexample.c</pre>
</div>
<p>
So for the C++ mode of SWIG CHICKEN, <tt>example_wrap.cxx</tt>
and <tt>oexample.c</tt> are the files that must be compiled to
object files and linked into your project.
</p>
<H2><a name="Chicken_nn5">23.2 Code Generation</a></H2>
<H3><a name="Chicken_nn6">23.2.1 Naming Conventions</a></H3>
<p>
Given a C variable, function or constant declaration named
<tt>Foo_Bar</tt>, the declaration will be available
in CHICKEN as an identifier ending with
<tt>Foo-Bar</tt>. That is, an underscore is converted
to a dash.
</p>
<p>
You may control what the CHICKEN identifier will be by using the
<tt>%rename</tt> SWIG directive in the SWIG interface file.
</p>
<H3><a name="Chicken_nn7">23.2.2 Modules</a></H3>
<p>
The name of the module must be declared one of two ways:
<ul>
<li>Placing <tt>%module example</tt> in the SWIG interface
file.</li>
<li>Using <tt>-module example</tt> on the SWIG command
line.</li>
</ul>
<p>
The generated example.scm file then exports <code>(declare (unit modulename))</code>.
If you do not want SWIG to export the <code>(declare (unit modulename))</code>, pass
the -nounit option to SWIG.
<p>
CHICKEN will be able to access the module using the <code>(declare
(uses <i>modulename</i>))</code> CHICKEN Scheme form.
</p>
<H3><a name="Chicken_nn8">23.2.3 Constants and Variables</a></H3>
<p>
Constants may be created using any of the four constructs in
the interface file:
</p>
<ol>
<li><code>#define MYCONSTANT1 ...</code></li>
<li><code>%constant int MYCONSTANT2 = ...</code></li>
<li><code>const int MYCONSTANT3 = ...</code></li>
<li><code>enum { MYCONSTANT4 = ... };</code></li>
</ol>
<p>
In all cases, the constants may be accessed from within CHICKEN
using the form <tt>(MYCONSTANT1)</tt>; that is, the constants
may be accessed using the read-only parameter form.
</p>
<p>
Variables are accessed using the full parameter form.
For example, to set the C variable "int my_variable;", use the
Scheme form <tt>(my-variable 2345)</tt>. To get the C variable,
use <tt>(my-variable)</tt>.
</p>
<p>
The <tt>%feature("constasvar")</tt> can be applied to any constant
or immutable variable. Instead of exporting the constant as
a function that must be called, the constant will appear as a
scheme variable. This causes the generated .scm file to just contain the code
<tt>(set! MYCONSTANT1 (MYCONSTANT1))</tt>. See
<a href="Customization.html#Customization_features">Features and the %feature directive</a>
for info on how to apply the %feature.
</p>
<H3><a name="Chicken_nn9">23.2.4 Functions</a></H3>
<p>
C functions declared in the SWIG interface file will have
corresponding CHICKEN Scheme procedures. For example, the C
function "int sqrt(double x);" will be available using the
Scheme form <tt>(sqrt 2345.0)</tt>. A <code>void</code> return
value will give C_SCHEME_UNDEFINED as a result.
</p>
<p>
A function may return more than one value by using the
<code>OUTPUT</code> specifier (see Lib/chicken/typemaps.i).
They will be returned as multiple values using <code>(values)</code> if there is more than one
result (that is, a non-void return value and at least one argout
parameter, or a void return value and at least two argout
parameters). The return values can then be accessed with <code>(call-with-values)</code>.
</p>
<H3><a name="Chicken_nn10">23.2.5 Exceptions</a></H3>
<p>The SWIG chicken module has support for exceptions thrown from
C or C++ code to be caught in scheme.
See <a href="Customization.html#Customization_exception">Exception handling with %exception</a>
for more information about declaring exceptions in the interface file.
</p>
<p>Chicken supports both the <code>SWIG_exception(int code, const char *msg)</code> interface
as well as a <code>SWIG_ThrowException(C_word val)</code> function for throwing exceptions from
inside the %exception blocks. <code>SWIG_exception</code> will throw a list consisting of the code
(as an integer) and the message. Both of these will throw an exception using <code>(abort)</code>,
which can be handled by <code>(handle-exceptions)</code>. See
the Chicken manual on Exceptions
and <a href="http://srfi.schemers.org/srfi-12/srfi-12.html">SFRI-12</a>. Since the exception values are thrown
directly, if <code>(condition-case)</code> is used to catch an exception the exception will come through in the <code>val ()</code> case.
</p>
<p>The following simple module</p>
<div class="code"><pre>
%module exception_test
%inline %{
void test_throw(int i) throws (int) {
if (i == 1) throw 15;
}
%}
</pre></div>
<p>could be run with</p>
<div class="targetlang"><pre>
(handle-exceptions exvar
(if (= exvar 15)
(print "Correct!")
(print "Threw something else " exvar))
(test-throw 1))
</pre></div>
<H2><a name="Chicken_nn11">23.3 TinyCLOS</a></H2>
<p>
The author of TinyCLOS, Gregor Kiczales, describes TinyCLOS as:
"Tiny CLOS is a Scheme implementation of a 'kernelized' CLOS, with a
metaobject protocol. The implementation is even simpler than
the simple CLOS found in 'The Art of the Metaobject Protocol',
weighing in at around 850 lines of code, including (some)
comments and documentation."
</p>
<p>
Almost all good Scheme books describe how to use metaobjects and
generic procedures to implement an object-oriented Scheme
system. Please consult a Scheme book if you are unfamiliar
with the concept.
</p>
<p>
CHICKEN has a modified version of TinyCLOS, which SWIG CHICKEN
uses if the -proxy argument is given. If -proxy is passed, then
the generated example.scm file will contain TinyCLOS class definitions.
A class named Foo is declared as &lt;Foo&gt;, and each member variable
is allocated a slot. Member functions are exported as generic functions.
<p>
Primitive symbols and functions (the interface that would be presented if
-proxy was not passed) are hidden and no longer accessible. If the -unhideprimitive
command line argument is passed to SWIG, then the primitive symbols will be
available, but each will be prefixed by the string "primitive:"
<p>
The exported symbol names can be controlled with the -closprefix and -useclassprefix arguments.
If -useclassprefix is passed to SWIG, every member function will be generated with the class name
as a prefix. If the -closprefix mymod: argument is passed to SWIG, then the exported functions will
be prefixed by the string "mymod:". If -useclassprefix is passed, -closprefix is ignored.
</p>
<H2><a name="Chicken_nn12">23.4 Linkage</a></H2>
<p>
Please refer to <em>CHICKEN - A practical and portable Scheme
system - User's manual</em> for detailed help on how to link
object files to create a CHICKEN Scheme program. Briefly, to
link object files, be sure to add <tt>`chicken-config
-extra-libs -libs`</tt> or <tt>`chicken-config -shared
-extra-libs -libs`</tt>to your linker options. Use the
<tt>-shared</tt> option if you want to create a dynamically
loadable module. You might also want to use the much simpler
<tt>csc</tt> or <tt>csc.bat</tt>.
</p>
<p>Each scheme file that is generated
by SWIG contains <code>(declare (uses <i>modname</i>))</code>. This means that to load the
module from scheme code, the code must include <code>(declare (uses <i>modname</i>))</code>.
</p>
<H3><a name="Chicken_nn13">23.4.1 Static binary or shared library linked at compile time</a></H3>
<p>We can easily use csc to build a static binary.</p>
<div class="shell">
<pre>
$ swig -chicken example.i
$ csc -v example.scm example_impl.c example_wrap.c test_script.scm -o example
$ ./example
</pre>
</div>
<p>Similar to the above, any number of <tt>module.scm</tt> files could be compiled
into a shared library, and then that shared library linked when compiling the
main application.</p>
<div class="shell">
<pre>
$ swig -chicken example.i
$ csc -sv example.scm example_wrap.c example_impl.c -o example.so
</pre>
</div>
<p>The <tt>example.so</tt> file can then linked with <tt>test_script.scm</tt> when it
is compiled, in which case <tt>test_script.scm</tt> must have <code>(declare (uses example))</code>.
Multiple SWIG modules could have been linked into <tt>example.so</tt> and each
one accessed with a <code>(declare (uses ... ))</code>.
</p>
<div class="shell">
<pre>
$ csc -v test_script.scm -lexample
</pre>
</div>
<p>An alternative is that the test_script.scm can have the code <code>(load-library 'example "example.so")</code>,
in which case the test script does not need to be linked with example.so. The test_script.scm file can then
be run with <tt>csi</tt>.
</p>
<H3><a name="Chicken_nn14">23.4.2 Building chicken extension libraries</a></H3>
<p>Building a shared library like in the above section only works if the library
is linked at compile time with a script containing <code>(declare (uses ...))</code> or is
loaded explicitly with <code>(load-library 'example "example.so")</code>. It is
not the format that CHICKEN expects for extension libraries and eggs. The problem is the
<code>(declare (unit <i>modname</i>))</code> inside the <tt>modname.scm</tt> file. There are
two possible solutions to this.</p>
<p>First, SWIG accepts a <tt>-nounit</tt> argument, in which case the <code>(declare (unit <i>modname</i>))</code>
is not generated. Then, the <tt>modname.scm</tt> and <tt>modname_wrap.c</tt> files <b>must</b> be compiled into
their own shared library.</p>
<div class="shell">
<pre>
$ csc -sv modname.scm modname_wrap.c modname_impl.c -o modname.so
</pre>
</div>
<p>This library can then be loaded by scheme code with the <code>(require 'modname)</code> function.
See the
Loading-extension-libraries in the eval unit inside the CHICKEN manual for more information.</p>
<p>Another alternative is to run SWIG normally and create a scheme file that contains <code>(declare (uses <i>modname</i>))</code>
and then compile that file into the shared library as well. For example, inside the <tt>mod_load.scm</tt> file,</p>
<div class="targetlang">
<pre>
(declare (uses mod1))
(declare (uses mod2))
</pre>
</div>
<p>Which would then be compiled with</p>
<div class="shell">
<pre>
$ swig -chicken mod1.i
$ swig -chicken mod2.i
$ csc -sv mod_load.scm mod1.scm mod2.scm mod1_wrap.c mod2_wrap.c mod1_impl.c mod2_impl.c -o mod.so
</pre>
</div>
<p>Then the extension library can be loaded with <code>(require 'mod)</code>. As we can see here,
<tt>mod_load.scm</tt> contains the code that gets executed when the module is loaded. All this code
does is load both mod1 and mod2. As we can see, this technique is more useful when you want to
combine a few SWIG modules into one chicken extension library, especially if modules are related by
<code>%import</code></p>
<p>In either method, the files that are compiled into the shared library could also be
packaged into an egg. The <tt>mod1_wrap.c</tt> and <tt>mod2_wrap.c</tt> files that are created by SWIG
are stand alone and do not need SWIG to be installed to be compiled. Thus the egg could be
distributed and used by anyone, even if SWIG is not installed.</p>
<p>See the <tt>Examples/chicken/egg</tt> directory in the SWIG source for an example that builds
two eggs, one using the first method and one using the second method.</p>
<H3><a name="Chicken_nn15">23.4.3 Linking multiple SWIG modules with TinyCLOS</a></H3>
<p>Linking together multiple modules that share type information using the <code>%import</code>
directive while also using <tt>-proxy</tt> is more complicated. For example, if <tt>mod2.i</tt> imports <tt>mod1.i</tt>, then the
<tt>mod2.scm</tt> file contains references to symbols declared in <tt>mod1.scm</tt>,
and thus a <code>(declare (uses <i>mod1</i>))</code> or <code>(require '<i>mod1</i>)</code> must be exported
to the top of <tt>mod2.scm</tt>. By default, when SWIG encounters an <code>%import "modname.i"</code> directive,
it exports <code>(declare (uses <i>modname</i>))</code> into the scm file. This works fine unless mod1 was compiled with
the <tt>-nounit</tt> argument or was compiled into an extension library with other modules under a different name.</p>
<p>One option is to override the automatic generation of <code>(declare (uses mod1))</code>
by passing the <tt>-noclosuses</tt> option to SWIG when compiling <tt>mod2.i</tt>.
SWIG then provides the <code>%insert(closprefix) %{ %}</code> directive. Any scheme code inside that directive is inserted into the
generated .scm file, and if <tt>mod1</tt> was compiled with <tt>-nounit</tt>, the directive should contain <code>(require 'mod1)</code>.
This option allows for mixed loading as well, where some modules are imported with <code>(declare (uses <i>modname</i>))</code>
(which means they were compiled without -nounit) and some are imported with <code>(require 'modname)</code>.</p>
<p>The other option is to use the second idea in the above section. Compile all the modules normally, without any
<code>%insert(closprefix)</code>, <tt>-nounit</tt>, or <tt>-noclosuses</tt>. Then the modules will import each other correctly
with <code>(declare (uses ...))</code>.
To create an extension library or an egg, just create a <tt>module_load.scm</tt> file that <code>(declare (uses ...))</code>
all the modules.</p>
<H2><a name="Chicken_nn16">23.5 Typemaps</a></H2>
<p>
The Chicken module handles all types via typemaps. This information is
read from <code>Lib/chicken/typemaps.i</code> and
<code>Lib/chicken/chicken.swg</code>.
</p>
<H2><a name="Chicken_nn17">23.6 Pointers</a></H2>
<p>
For pointer types, SWIG uses CHICKEN tagged pointers.
A tagged pointer is an ordinary CHICKEN pointer with an
extra slot for a void *. With SWIG
CHICKEN, this void * is a pointer to a type-info
structure. So each pointer used as input or output from
the SWIG-generated CHICKEN wrappers will have type
information attached to it. This will let the wrappers
correctly determine which method should be called
according to the object type hierarchy exposed in the SWIG
interface files.
</p>
<p>
To construct a Scheme object from a C pointer, the wrapper code
calls the function
<code>SWIG_NewPointerObj(void *ptr, swig_type_info *type, int owner)</code>,
The function that calls <code>SWIG_NewPointerObj</code> must have a variable declared
<code>C_word *known_space = C_alloc(C_SIZEOF_SWIG_POINTER);</code>
It is ok to call <code>SWIG_NewPointerObj</code> more than once,
just make sure known_space has enough space for all the created pointers.
</p>
<p>
To get the pointer represented by a CHICKEN tagged pointer, the
wrapper code calls the function
<code>SWIG_ConvertPtr(C_word s, void **result, swig_type_info *type, int flags)</code>,
passing a pointer to a struct representing the expected pointer
type. flags is either zero or SWIG_POINTER_DISOWN (see below).
</p>
<H3><a name="Chicken_collection">23.6.1 Garbage collection</a></H3>
<p>If the owner flag passed to <code>SWIG_NewPointerObj</code> is 1, <code>NewPointerObj</code> will add a
finalizer to the type which will call the destructor or delete method of
that type. The destructor and delete functions are no longer exported for
use in scheme code, instead SWIG and chicken manage pointers.
In situations where SWIG knows that a function is returning a type that should
be garbage collected, SWIG will automatically set the owner flag to 1. For other functions,
the <code>%newobject</code> directive must be specified for functions whose return values
should be garbage collected. See
<a href="Customization.html#Customization_ownership">Object ownership and %newobject</a> for more information.
</p>
<p>In situations where a C or C++ function will assume ownership of a pointer, and thus
chicken should no longer garbage collect it, SWIG provides the <code>DISOWN</code> input typemap.
After applying this typemap (see the <a href="Typemaps.html#Typemaps">Typemaps chapter</a> for more information on how to apply typemaps),
any pointer that gets passed in will no longer be garbage collected.
An object is disowned by passing the <code>SWIG_POINTER_DISOWN</code> flag to <code>SWIG_ConvertPtr</code>.
<b>Warning:</b> Since the lifetime of the object is now controlled by the underlying code, the object might
get deleted while the scheme code still holds a pointer to it. Further use of this pointer
can lead to a crash.
</p>
<p>Adding a finalizer function from C code was added to chicken in the 1.89 release, so garbage collection
does not work for chicken versions below 1.89. If you would like the SWIG generated code to work with
chicken 1.40 to 1.89, pass the <code>-nocollection</code> argument to SWIG. This will not export code
inside the _wrap.c file to register finalizers, and will then export destructor functions which
must be called manually.
</p>
<H2><a name="Chicken_nn18">23.7 Unsupported features and known problems</a></H2>
<ul>
<li>No director support.</li>
<li>No support for c++ standard types like std::vector.</li>
<li>The TinyCLOS wrappers for overloaded functions will not work correctly when using
<a href="SWIGPlus.html#SWIGPlus_default_args">%feature(compactdefaultargs)</a>.</li>
</ul>
<H3><a name="Chicken_nn19">23.7.1 TinyCLOS problems with Chicken version &lt;= 1.92</a></H3>
<p>In Chicken versions equal to or below 1.92, TinyCLOS has a limitation such that generic methods do not properly work on methods
with different number of specializers: TinyCLOS assumes that every method added to a generic function
will have the same number of specializers. SWIG generates functions with different lengths of specializers
when C/C++ functions are overloaded. For example, the code</p>
<div class="code">
<pre>
class Foo {};
int foo(int a, Foo *b);
int foo(int a);
</pre></div>
<p>will produce scheme code</p>
<div class="targetlang">
<pre>
(define-method (foo (arg0 &lt;top&gt;) (arg1 &lt;Foo&gt;)) (<i>call primitive function</i>))
(define-method (foo (arg0 &lt;top&gt;)) (<i>call primitive function</i>))
</pre></div>
<p>Using unpatched TinyCLOS, the second <code>(define-method)</code> will replace the first one,
so calling <code>(foo 3 f)</code> will produce an error.</p>
<p>There are three solutions to this. The easist is to upgrade to the latest Chicken version. Otherwise, the
file <tt>Lib/chicken/tinyclos-multi-generic.patch</tt> in the SWIG source contains a patch against
tinyclos.scm inside the 1.92 chicken source to add support into TinyCLOS for multi-argument generics. (This patch was accepted into Chicken)
This requires chicken to be rebuilt and custom install of chicken. An alternative is the <tt>Lib/chicken/multi-generic.scm</tt>
file in the SWIG source. This file can be loaded after TinyCLOS is loaded, and it will override some functions
inside TinyCLOS to correctly support multi-argument generics. Please see the comments at the top of both files for more information.</p>
</body>
</html>

View file

@ -1,942 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>SWIG and Modula-3</title>
<link rel="stylesheet" type="text/css" href="style.css">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body bgcolor="#FFFFFF">
<H1><a name="Modula3">31 SWIG and Modula-3</a></H1>
<!-- INDEX -->
<div class="sectiontoc">
<ul>
<li><a href="#Modula3_modula3_overview">Overview</a>
<ul>
<li><a href="#Modula3_motivation">Motivation</a>
</ul>
<li><a href="#Modula3_conception">Conception</a>
<ul>
<li><a href="#Modula3_cinterface">Interfaces to C libraries</a>
<li><a href="#Modula3_cppinterface">Interfaces to C++ libraries</a>
</ul>
<li><a href="#Modula3_preliminaries">Preliminaries</a>
<ul>
<li><a href="#Modula3_compilers">Compilers</a>
<li><a href="#Modula3_commandline">Additional Commandline Options</a>
</ul>
<li><a href="#Modula3_typemaps">Modula-3 typemaps</a>
<ul>
<li><a href="#Modula3_inoutparam">Inputs and outputs</a>
<li><a href="#Modula3_ordinals">Subranges, Enumerations, Sets</a>
<li><a href="#Modula3_class">Objects</a>
<li><a href="#Modula3_imports">Imports</a>
<li><a href="#Modula3_exceptions">Exceptions</a>
<li><a href="#Modula3_typemap_example">Example</a>
</ul>
<li><a href="#Modula3_hints">More hints to the generator</a>
<ul>
<li><a href="#Modula3_features">Features</a>
<li><a href="#Modula3_pragmas">Pragmas</a>
</ul>
<li><a href="#Modula3_remarks">Remarks</a>
</ul>
</div>
<!-- INDEX -->
<p>
This chapter describes SWIG's support for
<a href="http://modula3.org/">Modula-3</a>.
You should be familiar with the
<a href="SWIG.html#SWIG">basics</a>
of SWIG,
especially
<a href="Typemaps.html#Typemaps">typemaps</a>.
</p>
<H2><a name="Modula3_modula3_overview">31.1 Overview</a></H2>
<p>
Modula-3 is a compiled language in the tradition of Niklaus Wirth's Modula 2,
which is in turn a successor to Pascal.
</p>
<p>
SWIG's Modula-3 support is currently very basic and highly experimental!
Many features are still not designed satisfyingly
and I need more discussion about the odds and ends.
Don't rely on any feature, incompatible changes are likely in the future!
However, the Modula-3 generator was already useful for interfacing
to the libraries:
</p>
<ol>
<li>
<a href="http://www.elegosoft.com/cgi-bin/cvsweb.cgi/cm3/m3-libs/plplot/">
PLPlot
</a>
</li>
<li>
<a href="http://www.elegosoft.com/cgi-bin/cvsweb.cgi/cm3/m3-libs/fftw/">
FFTW
</a>
</li>
</ol>
<H3><a name="Modula3_motivation">31.1.1 Motivation</a></H3>
<p>
Although it is possible to write Modula-3 code that performs as well as C/C++
most existing libraries are not written in Modula-3 but in C or C++, and
even libraries in other languages may provide C header files.
</p>
<p>
Fortunately Modula-3 can call C functions, but you have to write Modula-3
interfaces to them, and to make things comfortable you will also need
wrappers that convert between high-level features of Modula-3 (garbage
collecting, exceptions) and the explicit tracking of allocated memory and
exception codes used by C APIs.
</p>
<p>
SWIG converts C headers to Modula-3 interfaces for you, and using typemaps
you can pass <tt>TEXT</tt>s or open arrays, and convert error return codes
into exceptions.
</p>
<p>
If the library API is ill designed
writing appropriate typemaps can still be time-consuming.
E.g. C programmers are very creative to work-around
missing data types like (real) enumerations and sets.
You should turn such work-arounds back to the Modula-3 way
otherwise you lose static safety and consistency.
</p>
<p>
Without SWIG you would probably never consider trying to call C++ libraries
from Modula-3, but with SWIG this is becomes feasible.
SWIG can generate C wrappers to C++ functions and object methods
that may throw exceptions, and then wrap these C wrappers for Modula-3.
To make it complete you can then hide the C interface with Modula-3 classes and
exceptions.
</p>
<p>
SWIG allows you to call C and C++ libraries from Modula-3 (even with call back
functions), but it doesn't allow you to easily integrate a Modula-3 module into
a C/C++ project.
</p>
<H2><a name="Modula3_conception">31.2 Conception</a></H2>
<H3><a name="Modula3_cinterface">31.2.1 Interfaces to C libraries</a></H3>
<p>
Modula-3 has integrated support for calling C functions.
This is also extensively used by the standard Modula-3 libraries
to call OS functions.
The Modula-3 part of SWIG and the corresponding SWIG library
modula3.swg
contain code that uses these features.
Because of the built-in support there is no need
for calling the SWIG kernel to generate wrappers written in C.
All conversion and argument checking can be done in Modula-3
and the interfacing is quite efficient.
All you have to do is to write pieces of Modula-3 code
that SWIG puts together.
</p>
<table border summary="Modula-3 C library support">
<tr><th colspan=2>C library support integrated in Modula-3<th></tr>
<tr>
<td>Pragma <tt>&lt;* EXTERNAL *&gt;</tt></td>
<td>Precedes a declaration of a PROCEDURE that is implemented
in an external library instead of a Modula-3 module.</td>
</tr>
<tr>
<td>Pragma <tt>&lt;* CALLBACK *&gt;</tt></td>
<td>Precedes a declaration of a PROCEDURE that should be called
by external library code.</td>
</tr>
<tr>
<td>Module <tt>Ctypes</tt></td>
<td>Contains Modula-3 types that match some basic C types.</td>
</tr>
<tr>
<td>Module <tt>M3toC</tt></td>
<td>Contains routines that convert between Modula-3's <tt>TEXT</tt> type
and C's <tt>char *</tt> type.</td>
</tr>
</table>
<p>
In each run of SWIG the Modula-3 part
generates several files:
</p>
<table border summary="Modula-3 generated files">
<tr>
<th>Module name scheme</th>
<th>Identifier for <tt>%insert</tt></th>
<th>Description</th>
</tr>
<tr>
<td>Module<tt>Raw.i3</tt></td>
<td><tt>m3rawintf</tt></td>
<td>Declaration of types that are equivalent to those of the C library,
<tt>EXTERNAL</tt> procedures as interface to the C library functions</td>
</tr>
<tr>
<td>Module<tt>Raw.m3</tt></td>
<td><tt>m3rawimpl</tt></td>
<td>Almost empty.</td>
</tr>
<tr>
<td>Module<tt>.i3</tt></td>
<td><tt>m3wrapintf</tt></td>
<td>Declaration of comfortable wrappers to the C library functions.</td>
</tr>
<tr>
<td>Module<tt>.m3</tt></td>
<td><tt>m3wrapimpl</tt></td>
<td>Implementation of the wrappers that
convert between Modula-3 and C types,
check for validity of values,
hand-over resource management to the garbage collector using <tt>WeakRef</tt>s
and raises exceptions.</td>
</tr>
<tr>
<td><tt>m3makefile</tt></td>
<td><tt>m3makefile</tt></td>
<td>Add the modules above to the Modula-3 project and
specify the name of the Modula-3 wrapper library
to be generated.
Today I'm not sure if it is a good idea
to create a <tt>m3makefile</tt> in each run,
because SWIG must be started for each Modula-3 module it creates.
Thus the m3makefile is overwritten each time. :-(
</td>
</tr>
</table>
<p>
Here's a scheme of how the function calls to Modula-3 wrappers
are redirected to C library functions:
</p>
<table summary="Modula-3 C library">
<tr>
<td align=center>
Modula-3 wrapper<br>
Module<tt>.i3</tt><br>
generated by Modula-3 part of SWIG
</td>
<td></td>
<td align=center></td>
</tr>
<tr>
<td align=center>
<!-- pre tag overrides centering -->
|<br>
v
</td>
<td></td>
<td align=center></td>
</tr>
<tr>
<td align=center>
Modula-3 interface to C<br>
Module<tt>Raw.i3</tt><br>
generated by Modula-3 part of SWIG
</td>
<td>--&gt;</td>
<td align=center>
C library
</td>
</tr>
</table>
<p>
I have still no good conception how one can split C library interfaces
into type oriented interfaces.
A Module in Modula-3 represents an Abstract DataType
(or call it a static classes, i.e. a class without virtual methods).
E.g. if you have a principal type, say <tt>Database</tt>,
it is good Modula-3 style to set up one Module with the name <tt>Database</tt>
where the database type is declared with the name <tt>T</tt>
and where all functions are declared that operates on it.
</p>
<p>
The normal operation of SWIG is to generate a fixed set of files per call.
To generate multiple modules one has to write one SWIG interface
(different SWIG interfaces can share common data) per module.
Identifiers belonging to a different module may ignored (<tt>%ignore</tt>)
and the principal type must be renamed (<tt>%typemap</tt>).
</p>
<H3><a name="Modula3_cppinterface">31.2.2 Interfaces to C++ libraries</a></H3>
<p>
Interfaces to C++ files are much more complicated and
there are some more design decisions that are not made, yet.
Modula-3 has no support for C++ functions
but C++ compilers should support generating C++ functions
with a C interface.
</p>
<p>
Here's a scheme of how the function calls to Modula-3 wrappers
are redirected to C library functions:
</p>
<table summary="Modula-3 C++ library">
<tr>
<td align=center>
Modula-3 wrapper<br>
Module<tt>.i3</tt><br>
generated by Modula-3 part of SWIG
</td>
<td></td>
<td align=center>C++ library</td>
</tr>
<tr>
<td align=center>
<!-- pre tag overrides centering -->
|<br>
v
</td>
<td></td>
<td align=center>
^<br>
|
</td>
</tr>
<tr>
<td align=center>
Modula-3 interface to C<br>
Module<tt>Raw.i3</tt><br>
generated by Modula-3 part of SWIG
</td>
<td>--&gt;</td>
<td align=center>
C interface to C++<br>
module<tt>_wrap.cxx</tt><br>
generated by the SWIG core
</td>
</tr>
</table>
<p>
Wrapping C++ libraries arises additional problems:
</p>
<ul>
<li>
Is it sensible to wrap C++ classes with Modula-3 classes?
</li>
<li>
How to find the wrapping Modula-3 class
for a class pointer that is returned by a C++ routine?
</li>
<li>
How to deal with multiple inheritance
which was neglected for Modula-3 for good reasons?
</li>
<li>
Is it possible to sub-class C++ classes with Modula-3 code?
This issue is addressed by directors,
a feature that was experimentally added to some Language modules
like
<a href="Java.html#Java_directors">Java</a> and
<a href="Python.html#Python_directors">Python</a>.
</li>
<li>
How to manage storage with the garbage collector of Modula-3?
Support for
<a href="Customization.html#Customization_ownership">
<tt>%newobject</tt> and <tt>%typemap(newfree)</tt></a>
isn't implemented, yet.
What's about resources that are managed by the garbage collector
but shall be passed back to the storage management of the C++ library?
This is a general issue which is not solved in a satisfying fashion
as far as I know.
</li>
<li>
How to turn C++ exceptions into Modula-3 exceptions?
There's also no support for
<a href="Customization.html#Customization_exception">
<tt>%exception</tt></a>, yet.
</li>
</ul>
<p>
Be warned:
There is no C++ library I wrote a SWIG interface for,
so I'm not sure if this is possible or sensible, yet.
</p>
<H2><a name="Modula3_preliminaries">31.3 Preliminaries</a></H2>
<H3><a name="Modula3_compilers">31.3.1 Compilers</a></H3>
<p>
There are different Modula-3 compilers around:
cm3, pm3, ezm3, Klagenfurth Modula-3, Cambridge Modula-3.
SWIG itself does not contain compiler specific code
but the modula3.swg library file
may do so.
For testing examples I use Critical Mass cm3.
</p>
<H3><a name="Modula3_commandline">31.3.2 Additional Commandline Options</a></H3>
<p>
There are some experimental command line options
that prevent SWIG from generating interface files.
Instead files are emitted that may assist you
when writing SWIG interface files.
</p>
<table border summary="Modula-3 specific options">
<tr>
<th>Modula-3 specific options</th>
<th>Description</th>
</tr>
<tr>
<td valign=top>-generateconst &lt;file&gt;</td>
<td>
Disable generation of interfaces and wrappers.
Instead write code for computing numeric values of constants
to the specified file.
<br>
C code may contain several constant definitions
written as preprocessor macros.
Other language modules of SWIG use
compute-once-use-readonly variables or
functions to wrap such definitions.
All of them can invoke C code dynamically
for computing the macro values.
But if one wants to turn them into Modula-3
integer constants, enumerations or set types,
the values of these expressions has to be known statically.
Although definitions like <tt>(1 &lt;&lt; FLAG_MAXIMIZEWINDOW)</tt>
must be considered as good C style
they are hard to convert to Modula-3
since the value computation can use every feature of C.
<br>
Thus I implemented these switch
to extract all constant definitions
and write a C program that output the values of them.
It works for numeric constants only
and treats all of them as <tt>double</tt>.
Future versions may generate a C++ program
that can detect the type of the macros
by overloaded output functions.
Then strings can also be processed.
</td>
</tr>
<tr>
<td valign=top>-generaterename &lt;file&gt;</td>
<td>
Disable generation of interfaces and wrappers.
Instead generate suggestions for <tt>%rename</tt>.
<br>
C libraries use a naming style
that is neither homogeneous nor similar to that of Modula-3.
C function names often contain a prefix denoting the library
and some name components separated by underscores
or capitalization changes.
To get library interfaces that are really Modula-3 like
you should rename the function names with the <tt>%rename</tt> directive.
This switch outputs a list of such directives
with a name suggestion generated by a simple heuristic.
</td>
</tr>
<tr>
<td valign=top>-generatetypemap &lt;file&gt;</td>
<td>
Disable generation of interfaces and wrappers.
Instead generate templates for some basic typemaps.
</td>
</tr>
</table>
<H2><a name="Modula3_typemaps">31.4 Modula-3 typemaps</a></H2>
<H3><a name="Modula3_inoutparam">31.4.1 Inputs and outputs</a></H3>
<p>
Each C procedure has a bunch of inputs and outputs.
Inputs are passed as function arguments,
outputs are updated referential arguments and
the function value.
</p>
<p>
Each C type can have several typemaps
that apply only in case if a type is used
for an input argument, for an output argument,
or for a return value.
A further typemap may specify
the direction that is used for certain parameters.
I have chosen this separation
in order to be able to write general typemaps for the modula3.swg typemap library.
In the library code the final usage of the type is not known.
Using separate typemaps for each possible use
allows appropriate definitions for each case.
If these pre-definitions are fine
then the direction of the function parameter
is the only hint the user must give.
</p>
<p>
The typemaps specific to Modula-3 have a common name scheme:
A typemap name starts with "m3",
followed by "raw" or "wrap"
depending on whether it controls the generation
of the Module<tt>Raw.i3</tt> or the Module<tt>.i3</tt>, respectively.
It follows an "in" for typemaps applied to input argument,
"out" for output arguments, "arg" for all kind of arguments,
"ret" for returned values.
</p>
<p>
The main task of SWIG is to build wrapper function,
i.e. functions that convert values between C and Modula-3
and call the corresponding C function.
Modula-3 wrapper functions generated by SWIG
consist of the following parts:
</p>
<ul>
<li>Generate <tt>PROCEDURE</tt> signature.</li>
<li>Declare local variables.</li>
<li>Convert input values from Modula-3 to C.</li>
<li>Check for input value integrity.</li>
<li>Call the C function.</li>
<li>Check returned values, e.g. error codes.</li>
<li>Convert and write back values into Modula-3 records.</li>
<li>Free temporary storage.</li>
<li>Return values.</li>
</ul>
<table border summary="Modula-3 typemaps">
<tr>
<th>Typemap</th>
<th>Example</th>
<th>Description</th>
</tr>
<tr>
<td>m3wrapargvar</td>
<td><tt>$1: INTEGER := $1_name;</tt></td>
<td>
Declaration of some variables needed for temporary results.
</td>
</tr>
<tr>
<td>m3wrapargconst</td>
<td><tt>$1 = "$1_name";</tt></td>
<td>
Declaration of some constant, maybe for debug purposes.
</td>
</tr>
<tr>
<td>m3wrapargraw</td>
<td><tt>ORD($1_name)</tt></td>
<td>
The expression that should be passed as argument to the raw Modula-3 interface function.
</td>
</tr>
<tr>
<td>m3wrapargdir</td>
<td><tt>out</tt></td>
<td>
Referential arguments can be used for input, output, update.
???
</td>
</tr>
<tr>
<td>m3wrapinmode</td>
<td><tt>READONLY</tt></td>
<td>
One of Modula-3 parameter modes
<tt>VALUE</tt> (or empty),
<tt>VAR</tt>,
<tt>READONLY</tt>
</td>
</tr>
<tr>
<td>m3wrapinname</td>
<td></td>
<td>
New name of the input argument.
</td>
</tr>
<tr>
<td>m3wrapintype</td>
<td></td>
<td>
Modula-3 type of the input argument.
</td>
</tr>
<tr>
<td>m3wrapindefault</td>
<td></td>
<td>
Default value of the input argument
</td>
</tr>
<tr>
<td>m3wrapinconv</td>
<td><tt>$1 := M3toC.SharedTtoS($1_name);</tt></td>
<td>
Statement for converting the Modula-3 input value to C compliant value.
</td>
</tr>
<tr>
<td>m3wrapincheck</td>
<td><tt>IF Text.Length($1_name) &gt; 10 THEN RAISE E("str too long"); END;</tt></td>
<td>
Check the integrity of the input value.
</td>
</tr>
<tr>
<td>m3wrapoutname</td>
<td></td>
<td>
Name of the <tt>RECORD</tt> field to be used for returning multiple values.
This applies to referential output arguments that shall be turned
into return values.
</td>
</tr>
<tr>
<td>m3wrapouttype</td>
<td></td>
<td>
Type of the value that is returned instead of a referential output argument.
</td>
</tr>
<tr>
<td>m3wrapoutconv</td>
<td></td>
<td>
</td>
</tr>
<tr>
<td>m3wrapoutcheck</td>
<td></td>
<td>
</td>
</tr>
<tr>
<td>m3wrapretraw</td>
<td></td>
<td>
</td>
</tr>
<tr>
<td>m3wrapretname</td>
<td></td>
<td>
</td>
</tr>
<tr>
<td>m3wraprettype</td>
<td></td>
<td>
</td>
</tr>
<tr>
<td>m3wrapretvar</td>
<td></td>
<td>
</td>
</tr>
<tr>
<td>m3wrapretconv</td>
<td></td>
<td>
</td>
</tr>
<tr>
<td>m3wrapretcheck</td>
<td></td>
<td>
</td>
</tr>
<tr>
<td>m3wrapfreearg</td>
<td><tt>M3toC.FreeSharedS(str, arg1);</tt></td>
<td>
Free resources that were temporarily used in the wrapper.
Since this step should never be skipped,
SWIG will put it in the <tt>FINALLY</tt> branch
of a <tt>TRY .. FINALLY</tt> structure.
</td>
</tr>
</table>
<H3><a name="Modula3_ordinals">31.4.2 Subranges, Enumerations, Sets</a></H3>
<p>
Subranges, enumerations, and sets are machine oriented types
that make Modula very strong and expressive compared
with the type systems of many other languages.
</p>
<ul>
<li>
Subranges are used for statically restricted choices of integers.
</li>
<li>
Enumerations are used for named choices.
</li>
<li>
Sets are commonly used for flag (option) sets.
</li>
</ul>
<p>
Using them extensively makes Modula code very safe and readable.
</p>
<p>
C supports enumerations, too, but they are not as safe as the ones of Modula.
Thus they are abused for many things:
For named choices, for integer constant definitions, for sets.
To make it complete every way of defining a value in C
(<tt>#define</tt>, <tt>const int</tt>, <tt>enum</tt>)
is somewhere used for defining something
that must be handled completely different in Modula-3
(<tt>INTEGER</tt>, enumeration, <tt>SET</tt>).
</p>
<p>
I played around with several <tt>%feature</tt>s and <tt>%pragma</tt>s
that split the task up into converting
the C bit patterns (integer or bit set)
into Modula-3 bit patterns (integer or bit set)
and change the type as requested.
See the corresponding example in the
Examples/modula3/enum/example.i file.
This is quite messy and not satisfying.
So the best what you can currently do is
to rewrite constant definitions manually.
Though this is a tedious work
that I'd like to automate.
</p>
<H3><a name="Modula3_class">31.4.3 Objects</a></H3>
<p>
Declarations of C++ classes are mapped to <tt>OBJECT</tt> types
while it is tried to retain the access hierarchy
"public - protected - private" using partial revelation.
Though the example in
Examples/modula3/class/example.i
is not really useful, yet.
</p>
<H3><a name="Modula3_imports">31.4.4 Imports</a></H3>
<p>
Pieces of Modula-3 code provided by typemaps
may contain identifiers from foreign modules.
If the typemap <tt>m3wrapinconv</tt> for <tt>blah *</tt>
contains code using the function <tt>M3toC.SharedTtoS</tt>
you may declare <tt>%typemap("m3wrapinconv:import") blah * %{M3toC%}</tt>.
Then the module <tt>M3toC</tt> is imported
if the <tt>m3wrapinconv</tt> typemap for <tt>blah *</tt>
is used at least once.
Use <tt>%typemap("m3wrapinconv:import") blah * %{MyConversions AS M3toC%}</tt>
if you need module renaming.
Unqualified import is not supported.
</p>
<p>
It is cumbersome to add this typemap to each piece of Modula-3 code.
It is especially useful when writing general typemaps
for the modula3.swg typemap library.
For a monolithic module you might be better off
if you add the imports directly:
</p>
<div class="code">
<pre>
%insert(m3rawintf) %{
IMPORT M3toC;
%}
</pre></div>
<H3><a name="Modula3_exceptions">31.4.5 Exceptions</a></H3>
<p>
Modula-3 provides another possibility
of an output of a function: exceptions.
</p>
<p>
Any piece of Modula-3 code that SWIG inserts
due to a typemap can raise an exception.
This way you can also convert an error code
from a C function into a Modula-3 exception.
</p>
<p>
The <tt>RAISES</tt> clause is controlled
by typemaps with the <tt>throws</tt> extension.
If the typemap <tt>m3wrapinconv</tt> for <tt>blah *</tt>
contains code that may raise the exceptions <tt>OSError.E</tt>
you should declare
<tt>%typemap("m3wrapinconv:throws") blah * %{OSError.E%}</tt>.
</p>
<H3><a name="Modula3_typemap_example">31.4.6 Example</a></H3>
<p>
The generation of wrappers in Modula-3 needs very fine control
to take advantage of the language features.
Here is an example of a generated wrapper
where almost everything is generated by a typemap:
</p>
<div class="code"><pre>
<I> (* %relabel m3wrapinmode m3wrapinname m3wrapintype m3wrapindefault *)</I>
PROCEDURE Name (READONLY str : TEXT := "" )
<I> (* m3wrapoutcheck:throws *)</I>
: NameResult RAISES {E} =
CONST
arg1name = "str"; <I>(* m3wrapargconst *)</I>
VAR
arg0 : C.char_star; <I>(* m3wrapretvar *)</I>
arg1 : C.char_star; <I>(* m3wrapargvar *)</I>
arg2 : C.int;
result : RECORD
<I> (*m3wrapretname m3wraprettype*)</I>
unixPath : TEXT;
<I> (*m3wrapoutname m3wrapouttype*)</I>
checksum : CARDINAL;
END;
BEGIN
TRY
arg1 := M3toC.SharedTtoS(str); <I>(* m3wrapinconv *)</I>
IF Text.Length(arg1) &gt; 10 THEN <I>(* m3wrapincheck *)</I>
RAISE E("str too long");
END;
<I> (* m3wrapretraw m3wrapargraw *)</I>
arg0 := MessyToUnix (arg1, arg2);
result.unixPath := M3toC.CopyStoT(arg0); <I>(* m3wrapretconv *)</I>
result.checksum := arg2; <I>(* m3wrapoutconv *)</I>
IF result.checksum = 0 THEN <I>(* m3wrapoutcheck *)</I>
RAISE E("invalid checksum");
END;
FINALLY
M3toC.FreeSharedS(str, arg1); <I>(* m3wrapfreearg *)</I>
END;
END Name;
</pre></div>
<H2><a name="Modula3_hints">31.5 More hints to the generator</a></H2>
<H3><a name="Modula3_features">31.5.1 Features</a></H3>
<table border summary="Modula-3 features">
<tr>
<th>Feature</th>
<th>Example</th>
<th>Description</th>
</tr>
<tr>
<td>multiretval</td>
<td><tt>%m3multiretval get_box;</tt> or
<tt>%feature("modula3:multiretval") get_box;</tt></td>
<td>Let the denoted function return a <tt>RECORD</tt>
rather than a plain value.
This <tt>RECORD</tt> contains all arguments with "out" direction
including the return value of the C function (if there is one).
If more than one argument is "out"
then the function <b>must</b> have the <tt>multiretval</tt> feature activated,
but it is explicitly requested from the user to prevent mistakes.</td>
</tr>
<tr>
<td>constnumeric</td>
<td><tt>%constnumeric(12) twelve;</tt> or
<tt>%feature("constnumeric", "12") twelve;</tt></td>
<td>This feature can be used to tell Modula-3's back-end of SWIG
the value of an identifier.
This is necessary in the cases
where it was defined by a non-trivial C expression.
This feature is used by the
<tt>-generateconst</tt> <a href="#Modula3_commandline">option</a>.
In future it may be generalized to other kind of values
such as strings.
</td>
</tr>
</table>
<H3><a name="Modula3_pragmas">31.5.2 Pragmas</a></H3>
<table border summary="Modula-3 pragmas">
<tr>
<th>Pragma</th>
<th>Example</th>
<th>Description</th>
</tr>
<tr>
<td>unsafe</td>
<td><tt>%pragma(modula3) unsafe="true";</tt></td>
<td>Mark the raw interface modules as <tt>UNSAFE</tt>.
This will be necessary in many cases.</td>
</tr>
<tr>
<td>library</td>
<td><tt>%pragma(modula3) library="m3fftw";</tt></td>
<td>Specifies the library name for the wrapper library to be created.
It should be distinct from the name of the library to be wrapped.</td>
</tr>
</table>
<H2><a name="Modula3_remarks">31.6 Remarks</a></H2>
<ul>
<li>
The Modula-3 part of SWIG doesn't try to generate nicely formatted code.
If you need to read the generated code, use <tt>m3pp</tt> to postprocess the
Modula files.
</li>
</ul>
</body>
</html>

View file

@ -1,246 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>SWIG and Pike</title>
<link rel="stylesheet" type="text/css" href="style.css">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body bgcolor="#ffffff">
<H1><a name="Pike">37 SWIG and Pike</a></H1>
<!-- INDEX -->
<div class="sectiontoc">
<ul>
<li><a href="#Pike_nn2">Preliminaries</a>
<ul>
<li><a href="#Pike_nn3">Running SWIG</a>
<li><a href="#Pike_nn4">Getting the right header files</a>
<li><a href="#Pike_nn5">Using your module</a>
</ul>
<li><a href="#Pike_nn6">Basic C/C++ Mapping</a>
<ul>
<li><a href="#Pike_nn7">Modules</a>
<li><a href="#Pike_nn8">Functions</a>
<li><a href="#Pike_nn9">Global variables</a>
<li><a href="#Pike_nn10">Constants and enumerated types</a>
<li><a href="#Pike_nn11">Constructors and Destructors</a>
<li><a href="#Pike_nn12">Static Members</a>
</ul>
</ul>
</div>
<!-- INDEX -->
<p>
This chapter describes SWIG support for Pike. As of this writing, the
SWIG Pike module is still under development and is not considered
ready for prime time. The Pike module is being developed against the
Pike 7.4.10 release and may not be compatible with previous versions
of Pike.
</p>
<p>
This chapter covers most SWIG features, but certain low-level details
are covered in less depth than in earlier chapters. At the very
least, make sure you read the "<a href="SWIG.html#SWIG">SWIG Basics</a>"
chapter.<br>
</p>
<H2><a name="Pike_nn2">37.1 Preliminaries</a></H2>
<H3><a name="Pike_nn3">37.1.1 Running SWIG</a></H3>
<p>
Suppose that you defined a SWIG module such as the following:
</p>
<div class="code">
<pre>%module example<br><br>%{<br>#include "example.h"<br>%}<br><br>int fact(int n);<br></pre>
</div>
<p>
To build a C extension module for Pike, run SWIG using the <tt>-pike</tt> option :
</p>
<div class="code">
<pre>$ <b>swig -pike example.i</b><br></pre>
</div>
<p>
If you're building a C++ extension, be sure to add the <tt>-c++</tt> option:
</p>
<div class="code">
<pre>$ <b>swig -c++ -pike example.i</b><br></pre>
</div>
<p>
This creates a single source file named <tt>example_wrap.c</tt> (or <tt>example_wrap.cxx</tt>, if you
ran SWIG with the <tt>-c++</tt> option).
The SWIG-generated source file contains the low-level wrappers that need
to be compiled and linked with the rest of your C/C++ application to
create an extension module.
</p>
<p>
The name of the wrapper file is derived from the name of the input
file. For example, if the input file is <tt>example.i</tt>, the name
of the wrapper file is <tt>example_wrap.c</tt>. To change this, you
can use the <tt>-o</tt> option:
</p>
<div class="code">
<pre>$ <b>swig -pike -o pseudonym.c example.i</b><br></pre>
</div>
<H3><a name="Pike_nn4">37.1.2 Getting the right header files</a></H3>
<p>
In order to compile the C/C++ wrappers, the compiler needs to know the
path to the Pike header files. These files are usually contained in a
directory such as
</p>
<div class="code">
<pre>/usr/local/pike/7.4.10/include/pike<br></pre>
</div>
<p>
There doesn't seem to be any way to get Pike itself to reveal the
location of these files, so you may need to hunt around for them.
You're looking for files with the names <tt>global.h</tt>, <tt>program.h</tt>
and so on.
</p>
<H3><a name="Pike_nn5">37.1.3 Using your module</a></H3>
<p>
To use your module, simply use Pike's <tt>import</tt> statement:
</p>
<div class="code"><pre>
$ <b>pike</b>
Pike v7.4 release 10 running Hilfe v3.5 (Incremental Pike Frontend)
&gt; <b>import example;</b>
&gt; <b>fact(4);</b>
(1) Result: 24
</pre></div>
<H2><a name="Pike_nn6">37.2 Basic C/C++ Mapping</a></H2>
<H3><a name="Pike_nn7">37.2.1 Modules</a></H3>
<p>
All of the code for a given SWIG module is wrapped into a single Pike
module. Since the name of the shared library that implements your
module ultimately determines the module's name (as far as Pike is
concerned), SWIG's <tt>%module</tt> directive doesn't really have any
significance.
</p>
<H3><a name="Pike_nn8">37.2.2 Functions</a></H3>
<p>
Global functions are wrapped as new Pike built-in functions. For
example,
</p>
<div class="code"><pre>
%module example
int fact(int n);
</pre></div>
<p>
creates a new built-in function <tt>example.fact(n)</tt> that works
exactly as you'd expect it to:
</p>
<div class="code"><pre>
&gt; <b>import example;</b>
&gt; <b>fact(4);</b>
(1) Result: 24
</pre></div>
<H3><a name="Pike_nn9">37.2.3 Global variables</a></H3>
<p>
Global variables are currently wrapped as a pair of functions, one to get
the current value of the variable and another to set it. For example, the
declaration
</p>
<div class="code"><pre>
%module example
double Foo;
</pre></div>
<p>
will result in two functions, <tt>Foo_get()</tt> and <tt>Foo_set()</tt>:
</p>
<div class="code"><pre>
&gt; <b>import example;</b>
&gt; <b>Foo_get();</b>
(1) Result: 3.000000
&gt; <b>Foo_set(3.14159);</b>
(2) Result: 0
&gt; <b>Foo_get();</b>
(3) Result: 3.141590
</pre></div>
<H3><a name="Pike_nn10">37.2.4 Constants and enumerated types</a></H3>
<p>
Enumerated types in C/C++ declarations are wrapped as Pike constants,
not as Pike enums.
</p>
<H3><a name="Pike_nn11">37.2.5 Constructors and Destructors</a></H3>
<p>
Constructors are wrapped as <tt>create()</tt> methods, and destructors are
wrapped as <tt>destroy()</tt> methods, for Pike classes.
</p>
<H3><a name="Pike_nn12">37.2.6 Static Members</a></H3>
<p>
Since Pike doesn't support static methods or data for Pike classes, static
member functions in your C++ classes are wrapped as regular functions and
static member variables are wrapped as pairs of functions (one to get the
value of the static member variable, and another to set it). The names of
these functions are prepended with the name of the class.
For example, given this C++ class declaration:
</p>
<div class="code"><pre>
class Shape
{
public:
static void print();
static int nshapes;
};
</pre></div>
<p>
SWIG will generate a <tt>Shape_print()</tt> method that invokes the static
<tt>Shape::print()</tt> member function, as well as a pair of methods,
<tt>Shape_nshapes_get()</tt> and <tt>Shape_nshapes_set()</tt>, to get and set
the value of <tt>Shape::nshapes</tt>.
</p>
</body>
</html>

View file

@ -1250,46 +1250,6 @@ lua_clean:
rm -f core @EXTRA_CLEAN@
rm -f *.@OBJEXT@ *$(LUA_SO)
##################################################################
##### ALLEGRO CL ######
##################################################################
ALLEGROCL = @ALLEGROCLBIN@
ALLEGROCL_SCRIPT=$(RUNME).lisp
allegrocl: $(SRCDIR_SRCS)
$(SWIG) -allegrocl -cwrap $(SWIGOPT) -o $(ISRCS) $(INTERFACEPATH)
$(CC) -c $(CCSHARED) $(CPPFLAGS) $(CFLAGS) $(ISRCS) $(INCLUDES) $(SRCDIR_SRCS)
$(LDSHARED) $(CFLAGS) $(LDFLAGS) $(OBJS) $(IOBJS) $(LIBS) -o $(LIBPREFIX)$(TARGET)$(SO)
allegrocl_cpp: $(SRCDIR_SRCS)
$(SWIG) -c++ -allegrocl $(SWIGOPT) -o $(ICXXSRCS) $(INTERFACEPATH)
$(CXX) -c $(CCSHARED) $(CPPFLAGS) $(CXXFLAGS) $(ICXXSRCS) $(SRCDIR_SRCS) $(SRCDIR_CXXSRCS) $(INCLUDES)
$(CXXSHARED) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(IOBJS) $(LIBS) $(CPP_DLLIBS) -o $(LIBPREFIX)$(TARGET)$(SO)
# -----------------------------------------------------------------
# Run ALLEGRO CL example
# -----------------------------------------------------------------
allegrocl_run:
$(RUNTOOL) $(ALLEGROCL) -batch -s $(ALLEGROCL_SCRIPT) $(RUNPIPE)
# -----------------------------------------------------------------
# Version display
# -----------------------------------------------------------------
allegrocl_version:
$(ALLEGROCL) --version
# -----------------------------------------------------------------
# Cleaning the ALLEGRO CL examples
# -----------------------------------------------------------------
allegrocl_clean:
rm -f *_wrap* *~ .~*
rm -f core @EXTRA_CLEAN@
rm -f *.@OBJEXT@ *@SO@
##################################################################
##### CFFI ######
##################################################################

View file

@ -1,12 +0,0 @@
This directory contains examples for CHICKEN.
class -- illustrates the proxy class C++ interface
constants -- handling #define and %constant literals
egg -- examples of building chicken extension libraries
multimap -- typemaps with multiple sub-types
overload -- C++ function overloading
simple -- the simple example from the user manual
zlib -- a wrapping of the zlib compression library
You should be able to run make in each of the examples. By default, a shared
library will be built. Run make check to execute the test.

View file

@ -1,6 +0,0 @@
# see top-level Makefile.in
class
constants
multimap
overload
simple

View file

@ -1,40 +0,0 @@
TOP = ../..
SWIGEXE = $(TOP)/../swig
SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib
INTERFACE = example.i
SRCS =
CXXSRCS = example.cxx
TARGET = class
INCLUDE =
SWIGOPT =
VARIANT =
# uncomment the following lines to build a static exe (only pick one of the CHICKEN_MAIN lines)
#CHICKEN_MAIN = runme-lowlevel.scm
#CHICKEN_MAIN = runme-tinyclos.scm
#VARIANT = _static
check: build
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CHICKEN_SCRIPT='runme-lowlevel.scm' chicken_run
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CHICKEN_SCRIPT='runme-tinyclos.scm' chicken_run
build: $(TARGET) $(TARGET)_proxy
$(TARGET): $(INTERFACE) $(SRCS)
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' \
SRCS='$(SRCS)' CXXSRCS='$(CXXSRCS)' CHICKEN_MAIN='$(CHICKEN_MAIN)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
INCLUDE='$(INCLUDE)' SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' \
INTERFACE='$(INTERFACE)' CHICKENOPTS='$(CHICKENOPTS)' chicken$(VARIANT)_cpp
$(TARGET)_proxy: $(INTERFACE) $(SRCS)
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' \
SRCS='$(SRCS)' CXXSRCS='$(CXXSRCS)' CHICKEN_MAIN='$(CHICKEN_MAIN)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
INCLUDE='$(INCLUDE)' SWIGOPT='$(SWIGOPT) -proxy' TARGET='$(TARGET)_proxy' \
INTERFACE='$(INTERFACE)' CHICKENOPTS='$(CHICKENOPTS)' chicken$(VARIANT)_cpp
clean:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' chicken_clean
rm -f example.scm
rm -f $(TARGET)

View file

@ -1,28 +0,0 @@
/* File : example.cxx */
#include "example.h"
#define M_PI 3.14159265358979323846
/* Move the shape to a new location */
void Shape::move(double dx, double dy) {
x += dx;
y += dy;
}
int Shape::nshapes = 0;
double Circle::area() {
return M_PI*radius*radius;
}
double Circle::perimeter() {
return 2*M_PI*radius;
}
double Square::area() {
return width*width;
}
double Square::perimeter() {
return 4*width;
}

View file

@ -1,41 +0,0 @@
/* File : example.h */
class Shape {
public:
Shape() {
nshapes++;
}
virtual ~Shape() {
nshapes--;
}
double x, y;
void move(double dx, double dy);
virtual double area() = 0;
virtual double perimeter() = 0;
static int nshapes;
enum SomeEnum {
First = 0,
Second,
Third,
Last = 1000
};
};
class Circle : public Shape {
private:
double radius;
public:
Circle(double r) : radius(r) { }
virtual double area();
virtual double perimeter();
};
class Square : public Shape {
private:
double width;
public:
Square(double w) : width(w) { }
virtual double area();
virtual double perimeter();
};

View file

@ -1,9 +0,0 @@
/* File : example.i */
%module example
%{
#include "example.h"
%}
/* Let's just grab the original header file here */
%include "example.h"

View file

@ -1,76 +0,0 @@
;; This file illustrates the low-level C++ interface generated
;; by SWIG.
(load-library 'example "class.so")
(declare (uses example))
;; ----- Object creation -----
(display "Creating some objects:\n")
(define c (new-Circle 10.0))
(display " Created circle ")
(display c)
(display "\n")
(define s (new-Square 10.0))
(display " Created square ")
(display s)
(display "\n")
;; ----- Access a static member -----
(display "\nA total of ")
(display (Shape-nshapes))
(display " shapes were created\n")
;; ----- Member data access -----
;; Set the location of the object
(Shape-x-set c 20.0)
(Shape-y-set c 30.0)
(Shape-x-set s -10.0)
(Shape-y-set s 5.0)
(display "\nHere is their current position:\n")
(display " Circle = (")
(display (Shape-x-get c))
(display ", ")
(display (Shape-y-get c))
(display ")\n")
(display " Square = (")
(display (Shape-x-get s))
(display ", ")
(display (Shape-y-get s))
(display ")\n")
;; ----- Call some methods -----
(display "\nHere are some properties of the shapes:\n")
(let
((disp (lambda (o)
(display " ")
(display o)
(display "\n")
(display " area = ")
(display (Shape-area o))
(display "\n")
(display " perimeter = ")
(display (Shape-perimeter o))
(display "\n"))))
(disp c)
(disp s))
(display "\nGuess I'll clean up now\n")
;; Note: this invokes the virtual destructor
(set! c #f)
(set! s #f)
(gc #t)
(set! s 3)
(display (Shape-nshapes))
(display " shapes remain\n")
(display "Goodbye\n")
(exit)

View file

@ -1,76 +0,0 @@
;; This file illustrates the proxy C++ interface generated
;; by SWIG.
(load-library 'example "class_proxy.so")
(declare (uses example))
(declare (uses tinyclos))
;; ----- Object creation -----
(display "Creating some objects:\n")
(define c (make <Circle> 10.0))
(display " Created circle ")
(display c)
(display "\n")
(define s (make <Square> 10.0))
(display " Created square ")
(display s)
(display "\n")
;; ----- Access a static member -----
(display "\nA total of ")
(display (Shape-nshapes))
(display " shapes were created\n")
;; ----- Member data access -----
;; Set the location of the object
(slot-set! c 'x 20.0)
(slot-set! c 'y 30.0)
(slot-set! s 'x -10.0)
(slot-set! s 'y 5.0)
(display "\nHere is their current position:\n")
(display " Circle = (")
(display (slot-ref c 'x))
(display ", ")
(display (slot-ref c 'y))
(display ")\n")
(display " Square = (")
(display (slot-ref s 'x))
(display ", ")
(display (slot-ref s 'y))
(display ")\n")
;; ----- Call some methods -----
(display "\nHere are some properties of the shapes:\n")
(let
((disp (lambda (o)
(display " ")
(display o)
(display "\n")
(display " area = ")
(display (area o))
(display "\n")
(display " perimeter = ")
(display (perimeter o))
(display "\n"))))
(disp c)
(disp s))
(display "\nGuess I'll clean up now\n")
;; Note: Invoke the virtual destructors by forcing garbage collection
(set! c 77)
(set! s 88)
(gc #t)
(display (Shape-nshapes))
(display " shapes remain\n")
(display "Goodbye\n")
(exit)

View file

@ -1,31 +0,0 @@
TOP = ../..
SWIGEXE = $(TOP)/../swig
SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib
INTERFACE = example.i
SRCS =
CXXSRCS =
TARGET = constants
INCLUDE =
SWIGOPT =
VARIANT =
# uncomment the following two lines to build a static exe
#CHICKEN_MAIN = runme.scm
#VARIANT = _static
check: build
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' chicken_run
build: $(TARGET)
$(TARGET): $(INTERFACE) $(SRCS)
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' \
SRCS='$(SRCS)' CXXSRCS='$(CXXSRCS)' CHICKEN_MAIN='$(CHICKEN_MAIN)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
INCLUDE='$(INCLUDE)' SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' \
INTERFACE='$(INTERFACE)' CHICKENOPTS='$(CHICKENOPTS)' chicken$(VARIANT)
clean:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' chicken_clean
rm -f example.scm
rm -f $(TARGET)

View file

@ -1,27 +0,0 @@
/* File : example.i */
%module example
/* A few preprocessor macros */
#define ICONST 42
#define FCONST 2.1828
#define CCONST 'x'
#define CCONST2 '\n'
#define SCONST "Hello World"
#define SCONST2 "\"Hello World\""
/* This should work just fine */
#define EXPR ICONST + 3*(FCONST)
/* This shouldn't do anything */
#define EXTERN extern
/* Neither should this (BAR isn't defined) */
#define FOO (ICONST + BAR)
/* The following directives also produce constants. Remember that
CHICKEN is normally case-insensitive, so don't rely on differing
case to differentiate variable names */
%constant int iconstX = 37;
%constant double fconstX = 3.14;

View file

@ -1,16 +0,0 @@
;; feel free to uncomment and comment sections
(load-library 'example "./constants.so")
(display "starting test ... you will see 'finished' if successful.\n")
(or (= (ICONST) 42) (exit 1))
(or (< (abs (- (FCONST) 2.1828)) 0.00001) (exit 1))
(or (char=? (CCONST) #\x) (exit 1))
(or (char=? (CCONST2) #\newline) (exit 1))
(or (string=? (SCONST) "Hello World") (exit 1))
(or (string=? (SCONST2) "\"Hello World\"") (exit 1))
(or (< (abs (- (EXPR) (+ (ICONST) (* 3 (FCONST))))) 0.00001) (exit 1))
(or (= (iconstX) 37) (exit 1))
(or (< (abs (- (fconstX) 3.14)) 0.00001) (exit 1))
(display "finished test.\n")
(exit 0)

View file

@ -1,41 +0,0 @@
TOP = ../..
SWIGEXE = $(TOP)/../swig
SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib
check: build
cd eggs/install && csi ../../test.scm
build: single multi
# This creates an egg which contains only the single module. Any additional implementation files
# that implement the interface being wrapped should also be added to this egg
single: single_wrap.cxx
mkdir -p eggs
tar czf eggs/single.egg single.setup single.scm single_wrap.cxx
rm -f single.scm single_wrap.cxx
# compile the single module with -nounit
single_wrap.cxx: single.i
$(SWIGEXE) -chicken -c++ -proxy -nounit single.i
# Now build both mod1 and mod2 into a single egg
multi: mod1_wrap.cxx mod2_wrap.cxx
mkdir -p eggs
tar czf eggs/multi.egg multi.setup multi_init.scm mod1.scm mod1_wrap.cxx mod2.scm mod2_wrap.cxx
rm -f mod1.scm mod1_wrap.cxx mod2.scm mod2_wrap.cxx
mod1_wrap.cxx: mod1.i
$(SWIGEXE) -chicken -c++ -proxy mod1.i
mod2_wrap.cxx: mod2.i
$(SWIGEXE) -chicken -c++ -proxy mod2.i
clean:
rm -rf eggs
# this part is for testing...
setup:
cd eggs && \
mkdir -p install && \
chicken-setup -repository `pwd`/install single.egg && \
chicken-setup -repository `pwd`/install multi.egg

View file

@ -1,19 +0,0 @@
These examples show how to build a chicken extension module in the form of an
egg. There are two eggs that get built, single.egg which contains a single
module which is built with -nounit and multi.egg, which contains two modules
mod1 and mod2. These are built normally, and multi_init.scm loads them both.
Read section "17.4.2 Building chicken extension libraries" in the manual
for a description of these two techniques.
To build:
$ make
$ make setup
$ make run
$ make clean
The eggs are built into an eggs subdirectory, because chicken-setup has
problems installing eggs when there are other files named similar in
the same directory. The make setup step runs chicken-setup to install
the eggs into the eggs/install directory.

View file

@ -1,8 +0,0 @@
%module mod1
%inline %{
class Bar {
public:
int b;
};
%}

View file

@ -1,17 +0,0 @@
%module mod2
%import "mod1.i"
%{
class Bar {
public:
int b;
};
%}
%inline %{
class Bar2 : public Bar {
public:
int c;
};
%}

View file

@ -1,2 +0,0 @@
(run (csc -s -o multi.so multi_init.scm mod1.scm mod1_wrap.cxx mod2.scm mod2_wrap.cxx))
(install-extension 'multi '("multi.so"))

View file

@ -1,2 +0,0 @@
(declare (uses mod1))
(declare (uses mod2))

View file

@ -1,8 +0,0 @@
%module single
%inline %{
class Foo {
public:
int a;
};
%}

View file

@ -1,2 +0,0 @@
(run (csc -s -o single.so single.scm single_wrap.cxx))
(install-extension 'single '("single.so"))

View file

@ -1,18 +0,0 @@
(require-extension single)
(require-extension multi)
(define f (make <Foo>))
(slot-set! f 'a 3)
(print (slot-ref f 'a))
(define b (make <Bar>))
(slot-set! b 'b 2)
(print (slot-ref b 'b))
(define b2 (make <Bar2>))
(slot-set! b2 'b 4)
(slot-set! b2 'c 6)
(print (slot-ref b2 'b))
(print (slot-ref b2 'c))
(exit 0)

View file

@ -1,31 +0,0 @@
TOP = ../..
SWIGEXE = $(TOP)/../swig
SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib
INTERFACE = example.i
SRCS = example.c
CXXSRCS =
TARGET = multimap
INCLUDE =
SWIGOPT =
VARIANT =
# uncomment the following two lines to build a static exe
#CHICKEN_MAIN = runme.scm
#VARIANT = _static
check: build
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' chicken_run
build: $(TARGET)
$(TARGET): $(INTERFACE) $(SRCS)
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' \
SRCS='$(SRCS)' CXXSRCS='$(CXXSRCS)' CHICKEN_MAIN='$(CHICKEN_MAIN)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
INCLUDE='$(INCLUDE)' SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' \
INTERFACE='$(INTERFACE)' CHICKENOPTS='$(CHICKENOPTS)' chicken$(VARIANT)
clean:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' chicken_clean
rm -f example.scm
rm -f $(TARGET)

View file

@ -1,53 +0,0 @@
/* File : example.c */
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
/* Compute the greatest common divisor of positive integers */
int gcd(int x, int y) {
int g;
g = y;
while (x > 0) {
g = x;
x = y % x;
y = g;
}
return g;
}
int gcdmain(int argc, char *argv[]) {
int x,y;
if (argc != 3) {
printf("usage: gcd x y\n");
return -1;
}
x = atoi(argv[1]);
y = atoi(argv[2]);
printf("gcd(%d,%d) = %d\n", x,y,gcd(x,y));
return 0;
}
int count(char *bytes, int len, char c) {
int i;
int count = 0;
for (i = 0; i < len; i++) {
if (bytes[i] == c) count++;
}
return count;
}
void capitalize(char *str, int len) {
int i;
for (i = 0; i < len; i++) {
str[i] = (char)toupper(str[i]);
}
}
void circle(double x, double y) {
double a = x*x + y*y;
if (a > 1.0) {
printf("Bad points %g, %g\n", x,y);
} else {
printf("Good points %g, %g\n", x,y);
}
}

View file

@ -1,96 +0,0 @@
/* File : example.i */
%module example
%{
extern int gcd(int x, int y);
extern int gcdmain(int argc, char *argv[]);
extern int count(char *bytes, int len, char c);
extern void capitalize (char *str, int len);
extern void circle (double cx, double cy);
extern int squareCubed (int n, int *OUTPUT);
%}
%include exception.i
%include typemaps.i
extern int gcd(int x, int y);
%typemap(in) (int argc, char *argv[]) {
int i;
if (!C_swig_is_vector ($input)) {
swig_barf (SWIG_BARF1_BAD_ARGUMENT_TYPE, "Argument $input is not a vector");
}
$1 = C_header_size ($input);
$2 = (char **) malloc(($1+1)*sizeof(char *));
for (i = 0; i < $1; i++) {
C_word o = C_block_item ($input, i);
if (!C_swig_is_string (o)) {
char err[50];
free($2);
sprintf (err, "$input[%d] is not a string", i);
swig_barf (SWIG_BARF1_BAD_ARGUMENT_TYPE, err);
}
$2[i] = C_c_string (o);
}
$2[i] = 0;
}
%typemap(freearg) (int argc, char *argv[]) {
free($2);
}
extern int gcdmain(int argc, char *argv[]);
%typemap(in) (char *bytes, int len) {
if (!C_swig_is_string ($input)) {
swig_barf (SWIG_BARF1_BAD_ARGUMENT_TYPE, "Argument $input is not a string");
}
$1 = C_c_string ($input);
$2 = C_header_size ($input);
}
extern int count(char *bytes, int len, char c);
/* This example shows how to wrap a function that mutates a string */
%typemap(in) (char *str, int len)
%{ if (!C_swig_is_string ($input)) {
swig_barf (SWIG_BARF1_BAD_ARGUMENT_TYPE, "Argument $input is not a string");
}
$2 = C_header_size ($input);
$1 = (char *) malloc ($2+1);
memmove ($1, C_c_string ($input), $2);
%}
/* Return the mutated string as a new object. Notice the if MANY construct ... they must be at column 0. */
%typemap(argout) (char *str, int len) (C_word *scmstr)
%{ scmstr = C_alloc (C_SIZEOF_STRING ($2));
SWIG_APPEND_VALUE(C_string (&scmstr, $2, $1));
free ($1);
%}
extern void capitalize (char *str, int len);
/* A multi-valued constraint. Force two arguments to lie
inside the unit circle */
%typemap(check) (double cx, double cy) {
double a = $1*$1 + $2*$2;
if (a > 1.0) {
SWIG_exception (SWIG_ValueError, "cx and cy must be in unit circle");
}
}
extern void circle (double cx, double cy);
/* Test out multiple return values */
extern int squareCubed (int n, int *OUTPUT);
%{
/* Returns n^3 and set n2 to n^2 */
int squareCubed (int n, int *n2) {
*n2 = n * n;
return (*n2) * n;
};
%}

View file

@ -1,58 +0,0 @@
;; feel free to uncomment and comment sections
(load-library 'example "multimap.so")
(display "(gcd 90 12): ")
(display (gcd 90 12))
(display "\n")
(display "(circle 0.5 0.5): ")
(display (circle 0.5 0.5))
(display "\n")
(display "(circle 1.0 1.0): ")
(handle-exceptions exvar
(if (= (car exvar) 9)
(display "success: exception thrown")
(display "an incorrect exception was thrown"))
(begin
(circle 1.0 1.0)
(display "an exception was not thrown when it should have been")))
(display "\n")
(display "(circle 1 1): ")
(handle-exceptions exvar
(if (= (car exvar) 9)
(display "success: exception thrown")
(display "an incorrect exception was thrown"))
(begin
(circle 1 1)
(display "an exception was not thrown when it should have been")))
(display "\n")
(display "(capitalize \"will this be all capital letters?\"): ")
(display (capitalize "will this be all capital letters?"))
(display "\n")
(display "(count \"jumpity little spider\" #\\t): ")
(display (count "jumpity little spider" #\t))
(display "\n")
(display "(gcdmain '#(\"hi\" \"there\")): ")
(display (gcdmain '#("hi" "there")))
(display "\n")
(display "(gcdmain '#(\"gcd\" \"9\" \"28\")): ")
(gcdmain '#("gcd" "9" "28"))
(display "\n")
(display "(gcdmain '#(\"gcd\" \"12\" \"90\")): ")
(gcdmain '#("gcd" "12" "90"))
(display "\n")
(display "squarecubed 3: ")
(call-with-values (lambda() (squareCubed 3))
(lambda (a b) (printf "~A ~A" a b)))
(display "\n")
(exit)

View file

@ -1,31 +0,0 @@
TOP = ../..
SWIGEXE = $(TOP)/../swig
SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib
INTERFACE = example.i
SRCS =
CXXSRCS = example.cxx
TARGET = overload
INCLUDE =
SWIGOPT = -proxy -unhideprimitive
VARIANT =
# uncomment the following lines to build a static exe
#CHICKEN_MAIN = runme.scm
#VARIANT = _static
check: build
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' chicken_run
build: $(TARGET)
$(TARGET): $(INTERFACE) $(SRCS)
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' \
SRCS='$(SRCS)' CXXSRCS='$(CXXSRCS)' CHICKEN_MAIN='$(CHICKEN_MAIN)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
INCLUDE='$(INCLUDE)' SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' \
INTERFACE='$(INTERFACE)' CHICKENOPTS='$(CHICKENOPTS)' chicken$(VARIANT)_cpp
clean:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' chicken_clean
rm -f example.scm
rm -f $(TARGET)

View file

@ -1,2 +0,0 @@
Overloading example from Chapter 5.14 of SWIG Core Documentation for
version 1.3.

View file

@ -1,33 +0,0 @@
/* File : example.c */
#include "example.h"
#include <stdio.h>
void foo(int x) {
printf("x is %d\n", x);
}
void foo(char *x) {
printf("x is '%s'\n", x);
}
Foo::Foo () {
myvar = 55;
printf ("Foo constructor called\n");
}
Foo::Foo (const Foo &) {
myvar = 66;
printf ("Foo copy constructor called\n");
}
void Foo::bar (int x) {
printf ("Foo::bar(x) method ... \n");
printf("x is %d\n", x);
}
void Foo::bar (char *s, int y) {
printf ("Foo::bar(s,y) method ... \n");
printf ("s is '%s'\n", s);
printf ("y is %d\n", y);
}

View file

@ -1,14 +0,0 @@
/* File : example.h */
extern void foo (int x);
extern void foo (char *x);
class Foo {
private:
int myvar;
public:
Foo();
Foo(const Foo &); // Copy constructor
void bar(int x);
void bar(char *s, int y);
};

View file

@ -1,16 +0,0 @@
/* File : example.i */
%module example
%{
#include "example.h"
%}
/* Let "Foo" objects be converted back and forth from TinyCLOS into
low-level CHICKEN SWIG procedures */
%typemap(clos_in) Foo * = SIMPLE_CLOS_OBJECT *;
%typemap(clos_out) Foo * = SIMPLE_CLOS_OBJECT *;
/* Let's just grab the original header file here */
%include "example.h"

View file

@ -1,45 +0,0 @@
;; This file demonstrates the overloading capabilities of SWIG
(load-library 'example "overload.so")
;; Low level
;; ---------
(display "
Trying low level code ...
(foo 1)
(foo \"some string\")
(define A-FOO (new-Foo))
(define ANOTHER-FOO (new-Foo A-FOO)) ;; copy constructor
(Foo-bar A-FOO 2)
(Foo-bar ANOTHER-FOO \"another string\" 3)
")
(primitive:foo 1)
(primitive:foo "some string")
(define A-FOO (slot-ref (primitive:new-Foo) 'swig-this))
(define ANOTHER-FOO (slot-ref (primitive:new-Foo A-FOO) 'swig-this)) ;; copy constructor
(primitive:Foo-bar A-FOO 2)
(primitive:Foo-bar ANOTHER-FOO "another string" 3)
;; TinyCLOS
;; --------
(display "
Trying TinyCLOS code ...
(+foo+ 1)
(+foo+ \"some string\")
(define A-FOO (make <Foo>))
(define ANOTHER-FOO (make <Foo> A-FOO)) ;; copy constructor
(-bar- A-FOO 2)
(-bar- ANOTHER-FOO \"another string\" 3)
")
(foo 1)
(foo "some string")
(define A-FOO (make <Foo>))
(define ANOTHER-FOO (make <Foo> A-FOO)) ;; copy constructor
(bar A-FOO 2)
(bar ANOTHER-FOO "another string" 3)
(exit)

View file

@ -1,31 +0,0 @@
TOP = ../..
SWIGEXE = $(TOP)/../swig
SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib
INTERFACE = example.i
SRCS = example.c
CXXSRCS =
TARGET = simple
INCLUDE =
SWIGOPT =
VARIANT =
# uncomment the following two lines to build a static exe
#CHICKEN_MAIN = runme.scm
#VARIANT = _static
check: build
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' chicken_run
build: $(TARGET)
$(TARGET): $(INTERFACE) $(SRCS)
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' \
SRCS='$(SRCS)' CXXSRCS='$(CXXSRCS)' CHICKEN_MAIN='$(CHICKEN_MAIN)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
INCLUDE='$(INCLUDE)' SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' \
INTERFACE='$(INTERFACE)' CHICKENOPTS='$(CHICKENOPTS)' chicken$(VARIANT)
clean:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' chicken_clean
rm -f example.scm example-generic.scm example-clos.scm
rm -f $(TARGET)

View file

@ -1 +0,0 @@
Simple example from users manual.

View file

@ -1,24 +0,0 @@
/* Simple example from documentation */
/* File : example.c */
#include <time.h>
double My_variable = 3.0;
/* Compute factorial of n */
int fact(int n) {
if (n <= 1) return 1;
else return n*fact(n-1);
}
/* Compute n mod m */
int my_mod(int n, int m) {
return (n % m);
}
char *get_time() {
long ltime;
time(&ltime);
return ctime(&ltime);
}

View file

@ -1,16 +0,0 @@
/* File : example.i */
%module example
%{
/* Put headers and other declarations here */
%}
%include typemaps.i
%rename(mod) my_mod;
%inline %{
extern double My_variable;
extern int fact(int);
extern int my_mod(int n, int m);
extern char *get_time();
%}

View file

@ -1,28 +0,0 @@
;; feel free to uncomment and comment sections
(load-library 'example "simple.so")
(display "(My-variable): ")
(display (My-variable))
(display "\n")
(display "(My-variable 3.141259): ")
(display (My-variable 3.141259))
(display "\n")
(display "(My-variable): ")
(display (My-variable))
(display "\n")
(display "(fact 5): ")
(display (fact 5))
(display "\n")
(display "(mod 75 7): ")
(display (mod 75 7))
(display "\n")
(display "(get-time): ")
(display (get-time))
(display "\n")
(exit)

View file

@ -1,7 +0,0 @@
# see top-level Makefile.in
class
enum
exception
reference
simple
typemap

View file

@ -1,26 +0,0 @@
TOP = ../..
SWIGEXE = $(TOP)/../swig
SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib
SRCS =
TARGET = example
PLATFORM = LINUXLIBC6
INTERFACE = example.i
SWIGOPT = -c++
MODULA3SRCS = *.[im]3
check: build
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' modula3_run
build:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' modula3
m3ppinplace $(MODULA3SRCS)
# compilation of example_wrap.cxx is started by cm3
# $(CXX) -c $(TARGET)_wrap.cxx
mv example_wrap.cxx m3makefile $(MODULA3SRCS) src/
ln -sf ../example.h src/example.h
cm3
clean:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' modula3_clean

View file

@ -1,28 +0,0 @@
/* File : example.cxx */
#include "example.h"
#define M_PI 3.14159265358979323846
/* Move the shape to a new location */
void Shape::move(double dx, double dy) {
x += dx;
y += dy;
}
int Shape::nshapes = 0;
double Circle::area() {
return M_PI*radius*radius;
}
double Circle::perimeter() {
return 2*M_PI*radius;
}
double Square::area() {
return width*width;
}
double Square::perimeter() {
return 4*width;
}

View file

@ -1,34 +0,0 @@
/* File : example.h */
class Shape {
public:
Shape() {
nshapes++;
}
virtual ~Shape() {
nshapes--;
}
double x, y;
void move(double dx, double dy);
virtual double area() = 0;
virtual double perimeter() = 0;
static int nshapes;
};
class Circle : public Shape {
private:
double radius;
public:
Circle(double r) : radius(r) { }
virtual double area();
virtual double perimeter();
};
class Square : public Shape {
private:
double width;
public:
Square(double w) : width(w) { }
virtual double area();
virtual double perimeter();
};

View file

@ -1,32 +0,0 @@
/* File : example.i */
%module Example
%{
#include "example.h"
%}
%insert(m3makefile) %{template("../swig")
cxx_source("example_wrap")%}
%typemap(m3rawinmode) Shape *, Circle *, Square * ""
%typemap(m3rawrettype) Shape *, Circle *, Square * "$1_basetype"
%typemap(m3wrapinmode) Shape *, Circle *, Square * ""
%typemap(m3wrapargraw) Shape *, Circle *, Square * "self.cxxObj"
%typemap(m3wrapretvar) Circle *, Square * "cxxObj : ExampleRaw.$1_basetype;"
%typemap(m3wrapretraw) Circle *, Square * "cxxObj"
%typemap(m3wrapretconv) Circle *, Square * "NEW($1_basetype,cxxObj:=cxxObj)"
%typemap(m3wraprettype) Circle *, Square * "$1_basetype"
/* Should work with and without renaming
%rename(M3Shape) Shape;
%rename(M3Circle) Circle;
%rename(M3Square) Square;
%typemap(m3wrapintype) Shape *, Circle *, Square * "M3$1_basetype"
%typemap(m3wraprettype) Shape *, Circle *, Square * "M3$1_basetype"
%typemap(m3wrapretconv) Circle *, Square * "NEW(M3$1_basetype,cxxObj:=cxxObj)"
*/
/* Let's just grab the original header file here */
%include "example.h"

View file

@ -1,11 +0,0 @@
readonly proc cxx_source (X) is
local cxxfile = X&".cxx"
local objfile = X&".o"
%exec("echo $PWD")
if stale(objfile,cxxfile)
exec("cd",path(),"; g++ -I.. -c -o",objfile,cxxfile)
end
import_obj(X)
%unlink_file(path()&SL&objfile)
end

View file

@ -1,27 +0,0 @@
TOP = ../..
SWIGEXE = $(TOP)/../swig
SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib
SRCS =
TARGET = example
INTERFACE = example.i
CONSTNUMERIC = example_const
SWIGOPT = -c++
MODULA3SRCS = *.[im]3
check: build
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' modula3_run
build:
$(SWIGEXE) -modula3 $(SWIGOPT) -module Example -generateconst $(CONSTNUMERIC) $(TARGET).h
$(CXX) -Wall $(CONSTNUMERIC).c -o $(CONSTNUMERIC)
$(CONSTNUMERIC) >$(CONSTNUMERIC).i
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' modula3
m3ppinplace $(MODULA3SRCS)
mv m3makefile $(MODULA3SRCS) src/
cm3
clean:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' modula3_clean

View file

@ -1,32 +0,0 @@
/* File : example.cxx */
#include "example.h"
#include <stdio.h>
void Foo::enum_test(speed s) {
if (s == IMPULSE) {
printf("IMPULSE speed\n");
} else if (s == WARP) {
printf("WARP speed\n");
} else if (s == LUDICROUS) {
printf("LUDICROUS speed\n");
} else if (s == HYPER) {
printf("HYPER speed\n");
} else {
printf("Unknown speed\n");
}
}
void enum_test(color c, Foo::speed s) {
if (c == RED) {
printf("color = RED, ");
} else if (c == BLUE) {
printf("color = BLUE, ");
} else if (c == GREEN) {
printf("color = GREEN, ");
} else {
printf("color = Unknown color!, ");
}
Foo obj;
obj.enum_test(s);
}

View file

@ -1,83 +0,0 @@
/* File : example.h */
#define PI 3.141
#define DAY_MONDAY 0
#define DAY_TUESDAY 1
#define DAY_WEDNESDAY 2
#define DAY_THURSDAY 3
#define DAY_FRIDAY 4
#define DAY_SATURDAY 5
#define DAY_SUNDAY 6
enum color { BLUE, RED, GREEN };
#define CLB_BLACK 0
#define CLB_BLUE 1
#define CLB_RED 2
#define CLB_MAGENTA 3
#define CLB_GREEN 4
#define CLB_CYAN 5
#define CLB_YELLOW 6
#define CLB_WHITE 7
/* Using this would be good style
which cannot be expected for general C header files.
Instead I want to demonstrate how to live without it.
enum month {
MTHF_JANUARY,
MTHF_FEBRUARY,
MTHF_MARCH,
MTHF_APRIL,
MTHF_MAY,
MTHF_JUNE,
MTHF_JULY,
MTHF_AUGUST,
MTHF_SEPTEMBER,
MTHF_OCTOBER,
MTHF_NOVEMBER,
MTHF_DECEMBER,
}
*/
/* Since there are no compile time constants in C / C++
it is a common abuse
to declare bit set (flag) constants
as enumerations. */
enum calendar {
MTHB_JANUARY = 1 << 0, /* 1 << MTHF_JANUARY, */
MTHB_FEBRUARY = 1 << 1, /* 1 << MTHF_FEBRUARY, */
MTHB_MARCH = 1 << 2, /* 1 << MTHF_MARCH, */
MTHB_APRIL = 1 << 3, /* 1 << MTHF_APRIL, */
MTHB_MAY = 1 << 4, /* 1 << MTHF_MAY, */
MTHB_JUNE = 1 << 5, /* 1 << MTHF_JUNE, */
MTHB_JULY = 1 << 6, /* 1 << MTHF_JULY, */
MTHB_AUGUST = 1 << 7, /* 1 << MTHF_AUGUST, */
MTHB_SEPTEMBER = 1 << 8, /* 1 << MTHF_SEPTEMBER, */
MTHB_OCTOBER = 1 << 9, /* 1 << MTHF_OCTOBER, */
MTHB_NOVEMBER = 1 << 10, /* 1 << MTHF_NOVEMBER, */
MTHB_DECEMBER = 1 << 11, /* 1 << MTHF_DECEMBER, */
MTHB_SPRING = MTHB_MARCH | MTHB_APRIL | MTHB_MAY,
MTHB_SUMMER = MTHB_JUNE | MTHB_JULY | MTHB_AUGUST,
MTHB_AUTUMN = MTHB_SEPTEMBER | MTHB_OCTOBER | MTHB_NOVEMBER,
MTHB_WINTER = MTHB_DECEMBER | MTHB_JANUARY | MTHB_FEBRUARY,
};
namespace Answer {
enum {
UNIVERSE_AND_EVERYTHING = 42,
SEVENTEEN_AND_FOUR = 21,
TWOHUNDRED_PERCENT_OF_NOTHING = 0,
};
class Foo {
public:
Foo() { }
enum speed { IMPULSE = -2, WARP = 0, HYPER, LUDICROUS = 3};
void enum_test(speed s);
};
};
void enum_test(color c, Answer::Foo::speed s);

View file

@ -1,72 +0,0 @@
/* File : example.i */
%module Example
%{
#include "example.h"
%}
%include "example_const.i"
// such features are generated by the following pragmas
#if 0
%feature("modula3:enumitem:enum","Days") DAY_MONDAY;
%feature("modula3:enumitem:name","monday") DAY_MONDAY;
%feature("modula3:enumitem:conv","int:int") DAY_MONDAY;
%feature("modula3:enumitem:enum","Month") MTHB_JANUARY;
%feature("modula3:enumitem:name","january") MTHB_JANUARY;
%feature("modula3:enumitem:conv","set:int") MTHB_JANUARY;
//%feature("modula3:constset:type","MonthSet") MTHB_JANUARY; /*type in the constant definition*/
%feature("modula3:constset:set", "MonthSet") MTHB_JANUARY; /*remarks that the 'type' is a set type*/
%feature("modula3:constset:base","Month") MTHB_JANUARY;
%feature("modula3:constset:name","monthsJanuary") MTHB_JANUARY;
%feature("modula3:constset:conv","set:set") MTHB_JANUARY; /*conversion of the bit pattern: no change*/
%feature("modula3:enumitem:enum","Color") BLUE;
%feature("modula3:enumitem:name","blue") BLUE;
%feature("modula3:enumitem:conv","int:int") BLUE;
%feature("modula3:constint:type","INTEGER") Foo::IMPULSE;
%feature("modula3:constint:name","impulse") Foo::IMPULSE;
%feature("modula3:constint:conv","int:int") Foo::IMPULSE;
#endif
%rename(pi) PI;
%pragma(modula3) enumitem="prefix=DAY_;int;srcstyle=underscore;Day";
%pragma(modula3) enumitem="enum=color;int;srcstyle=underscore;Color";
%pragma(modula3) makesetofenum="Color";
%pragma(modula3) constset="prefix=CLB_;set;srcstyle=underscore,prefix=clb;ColorSet,Color";
%pragma(modula3) enumitem="prefix=MTHB_,enum=calendar;set;srcstyle=underscore;Month";
%pragma(modula3) makesetofenum="Month";
%pragma(modula3) constset="prefix=MTHB_,enum=calendar;set;srcstyle=underscore,prefix=monthset;MonthSet,Month";
%pragma(modula3) constint="prefix=Answer::Foo::,enum=Answer::Foo::speed;int;srcstyle=underscore,prefix=speed;INTEGER";
%pragma(modula3) constint="prefix=Answer::,enum=Answer::;int;srcstyle=underscore,prefix=answer;CARDINAL";
%rename(AnswerFoo) Answer::Foo;
%typemap("m3rawrettype") Answer::Foo * %{AnswerFoo%}
%typemap("m3rawintype") Answer::Foo * %{AnswerFoo%}
%typemap("m3rawinmode") Answer::Foo * %{%}
%typemap("m3wraprettype") Answer::Foo * %{AnswerFoo%}
%typemap("m3wrapintype") Answer::Foo * %{AnswerFoo%}
%typemap("m3wrapinmode") Answer::Foo * %{%}
%typemap("m3wrapargraw") Answer::Foo * %{self.cxxObj%}
%typemap("m3wrapretvar") Answer::Foo * %{cxxObj : ExampleRaw.AnswerFoo;%}
%typemap("m3wrapretraw") Answer::Foo * %{cxxObj%}
%typemap("m3wrapretconv") Answer::Foo * %{NEW(AnswerFoo,cxxObj:=cxxObj)%}
%typemap("m3rawintype") Answer::Foo::speed %{C.int%};
%typemap("m3rawintype:import") Answer::Foo::speed %{Ctypes AS C%};
%typemap("m3wrapintype") Answer::Foo::speed %{[-2..3]%};
%typemap("m3wrapintype") color %{Color%};
%typemap("m3wrapargraw") color %{ORD($1_name)%};
/* Let's just grab the original header file here */
%include "example.h"

View file

@ -1,24 +0,0 @@
TOP = ../..
SWIGEXE = $(TOP)/../swig
SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib
CXXSRCS = example.cxx
TARGET = example
INTERFACE = example.i
SWIGOPT =
MODULA3SRCS = *.[im]3
MODULA3FLAGS= -o runme
check: build
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' modula3_run
build:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' modula3_cpp
# $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' MODULA3SRCS='$(MODULA3SRCS)' MODULA3FLAGS='$(MODULA3FLAGS)' modula3_compile
m3ppinplace $(MODULA3SRCS)
mv m3makefile $(MODULA3SRCS) src/
cm3
clean:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' modula3_clean

View file

@ -1,18 +0,0 @@
/* File : example.h */
enum error {OK, OVERFLOW, DIVISION_BY_ZERO, NEGATIVE_RADICAND, NEGATIVE_BASE};
typedef error errorstate; /* just to separate the typemaps */
error acc_add (double &x, double y);
error acc_sub (double &x, double y);
error acc_mul (double &x, double y);
error acc_div (double &x, double y);
double op_add (double x, double y, errorstate &err);
double op_sub (double x, double y, errorstate &err);
double op_mul (double x, double y, errorstate &err);
double op_div (double x, double y, errorstate &err);
double op_sqrt (double x, errorstate &err);
double op_pow (double x, double y, errorstate &err);
double op_noexc (double x, double y);

View file

@ -1,43 +0,0 @@
/* File : example.i */
%module Example
%{
#include "example.h"
%}
%insert(m3wrapintf) %{
EXCEPTION E(Error);
%}
%insert(m3wrapimpl) %{
IMPORT Ctypes AS C;
%}
%pragma(modula3) enumitem="enum=error;int;srcstyle=underscore;Error";
%typemap("m3rawintype") double & %{C.double%};
%typemap("m3wrapintype") double & %{LONGREAL%};
%typemap("m3wraprettype") error ""
%typemap("m3wrapretvar") error "rawerr: C.int;"
%typemap("m3wrapretraw") error "rawerr"
%typemap("m3wrapretcheck:throws") error "E"
%typemap("m3wrapretcheck") error
%{VAR err := VAL(rawerr, Error);
BEGIN
IF err # Error.ok THEN
RAISE E(err);
END;
END;%}
%typemap("m3rawintype") errorstate & %{C.int%};
%typemap("m3wrapintype",numinputs=0) errorstate & %{%};
%typemap("m3wrapargvar") errorstate & %{err:C.int:=ORD(Error.ok);%};
%typemap("m3wrapoutcheck:throws") errorstate & "E";
%typemap("m3wrapoutcheck") errorstate &
%{IF VAL(err,Error) # Error.ok THEN
RAISE E(VAL(err,Error));
END;%}
/* Let's just grab the original header file here */
%include "example.h"

View file

@ -1,22 +0,0 @@
TOP = ../..
SWIGEXE = $(TOP)/../swig
SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib
SRCS =
TARGET = example
INTERFACE = example.i
SWIGOPT = -c++
MODULA3SRCS = *.[im]3
check: build
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' modula3_run
build:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' modula3
m3ppinplace $(MODULA3SRCS)
mv m3makefile $(MODULA3SRCS) src/
cm3
clean:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' modula3_clean

View file

@ -1,46 +0,0 @@
/* File : example.cxx */
/* Deal with Microsoft's attempt at deprecating C standard runtime functions */
#if !defined(SWIG_NO_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER)
# define _CRT_SECURE_NO_DEPRECATE
#endif
#include "example.h"
#include <stdio.h>
#include <stdlib.h>
Vector operator+(const Vector &a, const Vector &b) {
Vector r;
r.x = a.x + b.x;
r.y = a.y + b.y;
r.z = a.z + b.z;
return r;
}
char *Vector::print() {
static char temp[512];
sprintf(temp,"Vector %p (%g,%g,%g)", (void *)this, x,y,z);
return temp;
}
VectorArray::VectorArray(int size) {
items = new Vector[size];
maxsize = size;
}
VectorArray::~VectorArray() {
delete [] items;
}
Vector &VectorArray::operator[](int index) {
if ((index < 0) || (index >= maxsize)) {
printf("Panic! Array index out of bounds.\n");
exit(1);
}
return items[index];
}
int VectorArray::size() {
return maxsize;
}

View file

@ -1,22 +0,0 @@
/* File : example.h */
struct Vector {
private:
double x,y,z;
public:
Vector() : x(0), y(0), z(0) { }
Vector(double x, double y, double z) : x(x), y(y), z(z) { }
Vector operator+(const Vector &b) const;
char *print();
};
struct VectorArray {
private:
Vector *items;
int maxsize;
public:
VectorArray(int maxsize);
~VectorArray();
Vector &operator[](int);
int size();
};

View file

@ -1,32 +0,0 @@
/* File : example.i */
/* This file has a few "typical" uses of C++ references. */
%module Example
%{
#include "example.h"
%}
%pragma(modula3) unsafe="1";
%insert(m3wrapintf) %{FROM ExampleRaw IMPORT Vector, VectorArray;%}
%insert(m3wrapimpl) %{FROM ExampleRaw IMPORT Vector, VectorArray;%}
%typemap(m3wrapretvar) Vector %{vec: UNTRACED REF Vector;%}
%typemap(m3wrapretraw) Vector %{vec%}
%typemap(m3wrapretconv) Vector %{vec^%}
/* This helper function calls an overloaded operator */
%inline %{
Vector addv(const Vector &a, const Vector &b) {
return a+b;
}
%}
%rename(Vector_Clear) Vector::Vector();
%rename(Add) Vector::operator+;
%rename(GetItem) VectorArray::operator[];
%include "example.h"

View file

@ -1,22 +0,0 @@
TOP = ../..
SWIGEXE = $(TOP)/../swig
SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib
SRCS =
TARGET = example
INTERFACE = example.i
SWIGOPT =
MODULA3SRCS = *.[im]3
check: build
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' modula3_run
build:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' modula3
m3ppinplace $(MODULA3SRCS)
mv m3makefile $(MODULA3SRCS) src/
cm3
clean:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' modula3_clean

View file

@ -1,18 +0,0 @@
/* File : example.c */
/* A global variable */
double Foo = 3.0;
/* Compute the greatest common divisor of positive integers */
int gcd(int x, int y) {
int g;
g = y;
while (x > 0) {
g = x;
x = y % x;
y = g;
}
return g;
}

View file

@ -1,7 +0,0 @@
/* File : example.i */
%module Example
%inline %{
extern int gcd(int x, int y);
extern double Foo;
%}

View file

@ -1,22 +0,0 @@
TOP = ../..
SWIGEXE = $(TOP)/../swig
SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib
SRCS =
TARGET = example
INTERFACE = example.i
SWIGOPT =
MODULA3SRCS = *.[im]3
check: build
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' modula3_run
build:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' modula3
m3ppinplace $(MODULA3SRCS)
mv m3makefile $(MODULA3SRCS) src/
cm3
clean:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' modula3_clean

View file

@ -1,90 +0,0 @@
/* File : example.i */
%module Example
%pragma(modula3) unsafe="true";
%insert(m3wrapintf) %{FROM ExampleRaw IMPORT Window, Point;
%}
%insert(m3wrapimpl) %{FROM ExampleRaw IMPORT Window, Point;
IMPORT M3toC;
IMPORT Ctypes AS C;
%}
/* Typemap applied to patterns of multiple arguments */
%typemap(m3rawinmode) (char *outstr) %{VAR%}
%typemap(m3rawintype) (char *outstr) %{CHAR%}
%typemap(m3wrapinmode) (char *outstr, int size) %{VAR%}
%typemap(m3wrapintype) (char *outstr, int size) %{ARRAY OF CHAR%}
%typemap(m3wrapargraw) (char *outstr, int size) %{$1_name[0], NUMBER($1_name)%}
%typemap(m3rawinmode) (const struct Window *) %{READONLY%}
%typemap(m3wrapinmode) (const struct Window *) %{READONLY%}
%typemap(m3rawintype) ( struct Window *) %{Window%}
%typemap(m3wrapintype) ( struct Window *) %{Window%}
%typemap(m3rawinmode) (const char *str []) %{READONLY%}
%typemap(m3wrapinmode) (const char *str []) %{READONLY%}
%typemap(m3rawintype) (const char *str []) %{(*ARRAY OF*) C.char_star%}
%typemap(m3wrapintype) (const char *str []) %{ARRAY OF TEXT%}
%typemap(m3wrapargvar) (const char *str []) %{$1: REF ARRAY OF C.char_star;%}
%typemap(m3wrapargraw) (const char *str []) %{$1[0]%}
%typemap(m3wrapinconv) (const char *str []) %{$1:= NEW(REF ARRAY OF C.char_star,NUMBER($1_name));
FOR i:=FIRST($1_name) TO LAST($1_name) DO
$1[i]:=M3toC.SharedTtoS($1_name[i]);
END;%}
%typemap(m3wrapfreearg) (const char *str [])
%{FOR i:=FIRST($1_name) TO LAST($1_name) DO
M3toC.FreeSharedS($1_name[i],$1[i]);
END;%}
%typemap(m3wraprettype) char * %{TEXT%}
%typemap(m3wrapretvar) char * %{result_string: C.char_star;%}
%typemap(m3wrapretraw) char * %{result_string%}
%typemap(m3wrapretconv) char * %{M3toC.CopyStoT(result_string)%}
struct Window {
char *label;
int left,top,width,height;
};
%typemap(m3wrapinname) (int x, int y) %{p%}
%typemap(m3wrapinmode) (int x, int y) %{READONLY%}
%typemap(m3wrapintype) (int x, int y) %{Point%}
%typemap(m3wrapargraw) (int x, int y) %{p.$1_name, p.$2_name%}
%typemap(m3wrapargraw) (int &x, int &y) %{p.$1_name, p.$2_name%}
%typemap(m3wrapintype) (int &x, int &y) %{Point%}
%typemap(m3wrapoutname) (int &x, int &y) %{p%}
%typemap(m3wrapouttype) (int &x, int &y) %{Point%}
%typemap(m3wrapargdir) (int &x, int &y) "out"
%typemap(m3wrapargvar) int &left, int &top, int &width, int &height "$1:C.int;"
%typemap(m3wrapargraw) int &left, int &top, int &width, int &height "$1"
%typemap(m3wrapoutconv) int &left, int &top, int &width, int &height "$1"
%typemap(m3wrapargdir) int &left, int &top "out"
%typemap(m3wrapouttype) int &width, int &height "CARDINAL"
%typemap(m3wrapargdir) int &width, int &height "out"
struct Point {
int x,y;
};
%m3multiretval get_box;
void set_label ( struct Window *win, const char *str, bool activate);
void set_multi_label ( struct Window *win, const char *str []);
void write_label (const struct Window *win, char *outstr, int size);
int get_label (const struct Window *win, char *outstr, int size);
char *get_label_ptr (const struct Window *win);
void move(struct Window *win, int x, int y);
int get_area(const struct Window *win);
void get_box(const struct Window *win, int &left, int &top, int &width, int &height);
void get_left(const struct Window *win, int &left);
void get_mouse(const struct Window *win, int &x, int &y);
int get_attached_data(const struct Window *win, const char *id);

View file

@ -1,10 +1,8 @@
/* File : example.i */
%module(directors="1") example
#ifndef SWIGSEXP
%{
#include "example.h"
%}
#endif
%feature("director");
%include "example.h"

View file

@ -1,7 +0,0 @@
# see top-level Makefile.in
class
constants
enum
overload
simple
template

View file

@ -1,23 +0,0 @@
TOP = ../..
SWIGEXE = $(TOP)/../swig
SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib
CXXSRCS = example.cxx
TARGET = example
INTERFACE = example.i
LIBS = -lm
check: build
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' pike_run
build:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' pike_cpp
static:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='mypike' INTERFACE='$(INTERFACE)' pike_cpp_static
clean:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' pike_clean

View file

@ -1,28 +0,0 @@
/* File : example.cxx */
#include "example.h"
#define M_PI 3.14159265358979323846
/* Move the shape to a new location */
void Shape::move(double dx, double dy) {
x += dx;
y += dy;
}
int Shape::nshapes = 0;
double Circle::area() {
return M_PI*radius*radius;
}
double Circle::perimeter() {
return 2*M_PI*radius;
}
double Square::area() {
return width*width;
}
double Square::perimeter() {
return 4*width;
}

View file

@ -1,34 +0,0 @@
/* File : example.h */
class Shape {
public:
Shape() {
nshapes++;
}
virtual ~Shape() {
nshapes--;
}
double x, y;
void move(double dx, double dy);
virtual double area() = 0;
virtual double perimeter() = 0;
static int nshapes;
};
class Circle : public Shape {
private:
double radius;
public:
Circle(double r) : radius(r) { }
virtual double area();
virtual double perimeter();
};
class Square : public Shape {
private:
double width;
public:
Square(double w) : width(w) { }
virtual double area();
virtual double perimeter();
};

View file

@ -1,9 +0,0 @@
/* File : example.i */
%module example
%{
#include "example.h"
%}
/* Let's just grab the original header file here */
%include "example.h"

View file

@ -1,53 +0,0 @@
import .example;
int main()
{
// ----- Object creation -----
write("Creating some objects:\n");
Circle c = Circle(10.0);
write(" Created circle.\n");
Square s = Square(10.0);
write(" Created square.\n");
// ----- Access a static member -----
write("\nA total of " + Shape_nshapes_get() + " shapes were created\n");
// ----- Member data access -----
// Set the location of the object
c->x_set(20.0);
c->y_set(30.0);
s->x_set(-10.0);
s->y_set(5.0);
write("\nHere is their current position:\n");
write(" Circle = (%f, %f)\n", c->x_get(), c->y_get());
write(" Square = (%f, %f)\n", s->x_get(), s->y_get());
// ----- Call some methods -----
write("\nHere are some properties of the shapes:\n");
write(" The circle:\n");
write(" area = %f.\n", c->area());
write(" perimeter = %f.\n", c->perimeter());
write(" The square:\n");
write(" area = %f.\n", s->area());
write(" perimeter = %f.\n", s->perimeter());
write("\nGuess I'll clean up now\n");
/* See if we can force 's' to be garbage-collected */
s = 0;
/* Now we should be down to only 1 shape */
write("%d shapes remain\n", Shape_nshapes_get());
/* Done */
write("Goodbye\n");
return 0;
}

View file

@ -1,22 +0,0 @@
TOP = ../..
SWIGEXE = $(TOP)/../swig
SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib
SRCS =
TARGET = example
INTERFACE = example.i
check: build
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' pike_run
build:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' pike
static:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='mypike' INTERFACE='$(INTERFACE)' pike_static
clean:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' pike_clean

View file

@ -1,27 +0,0 @@
/* File : example.i */
%module example
/* A few preprocessor macros */
#define ICONST 42
#define FCONST 2.1828
#define CCONST 'x'
#define CCONST2 '\n'
#define SCONST "Hello World"
#define SCONST2 "\"Hello World\""
/* This should work just fine */
#define EXPR ICONST + 3*(FCONST)
/* This shouldn't do anything */
#define EXTERN extern
/* Neither should this (BAR isn't defined) */
#define FOO (ICONST + BAR)
/* The following directives also produce constants */
%constant int iconst = 37;
%constant double fconst = 3.14;

View file

@ -1,24 +0,0 @@
int main()
{
write("ICONST = %d (should be 42)\n", .example.ICONST);
write("FCONST = %f (should be 2.1828)\n", .example.FCONST);
write("CCONST = %c (should be 'x')\n", .example.CCONST);
write("CCONST2 = %c (this should be on a new line)\n", .example.CCONST2);
write("SCONST = %s (should be 'Hello World')\n", .example.SCONST);
write("SCONST2 = %s (should be '\"Hello World\"')\n", .example.SCONST2);
write("EXPR = %f (should be 48.5484)\n", .example.EXPR);
write("iconst = %d (should be 37)\n", .example.iconst);
write("fconst = %f (should be 3.14)\n", .example.fconst);
if (search(indices(.example), "EXTERN") == -1)
write("EXTERN isn't defined (good)\n");
else
write("EXTERN is defined (bad)\n");
if (search(indices(.example), "FOO") == -1)
write("FOO isn't defined (good)\n");
else
write("FOO is defined (bad)\n");
return 0;
}

View file

@ -1,23 +0,0 @@
TOP = ../..
SWIGEXE = $(TOP)/../swig
SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib
CXXSRCS = example.cxx
TARGET = example
INTERFACE = example.i
LIBS = -lm
check: build
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' pike_run
build:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' pike_cpp
static:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='mypike' INTERFACE='$(INTERFACE)' pike_cpp_static
clean:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' pike_clean

View file

@ -1,13 +0,0 @@
This example will not compile with Pike versions 7.4.20 unless you first
patch the Pike sources. The problem is for line 91 of Pike's "stralloc.h"
(usually installed as /usr/local/pike/7.4.10/include/pike/stralloc.h). That
line reads:
tmp.ptr=ptr;
but should be patched to read:
tmp.ptr=(p_wchar0 *) ptr;
This bug has been reported to the Pike developers.

View file

@ -1,37 +0,0 @@
/* File : example.c */
#include "example.h"
#include <stdio.h>
void Foo::enum_test(speed s) {
if (s == IMPULSE) {
printf("IMPULSE speed\n");
} else if (s == WARP) {
printf("WARP speed\n");
} else if (s == LUDICROUS) {
printf("LUDICROUS speed\n");
} else {
printf("Unknown speed\n");
}
}
void enum_test(color c, Foo::speed s) {
if (c == RED) {
printf("color = RED, ");
} else if (c == BLUE) {
printf("color = BLUE, ");
} else if (c == GREEN) {
printf("color = GREEN, ");
} else {
printf("color = Unknown color!, ");
}
if (s == Foo::IMPULSE) {
printf("speed = IMPULSE speed\n");
} else if (s == Foo::WARP) {
printf("speed = WARP speed\n");
} else if (s == Foo::LUDICROUS) {
printf("speed = LUDICROUS speed\n");
} else {
printf("speed = Unknown speed!\n");
}
}

View file

@ -1,13 +0,0 @@
/* File : example.h */
enum color { RED, BLUE, GREEN };
class Foo {
public:
Foo() { }
enum speed { IMPULSE, WARP, LUDICROUS };
void enum_test(speed s);
};
void enum_test(color c, Foo::speed s);

View file

@ -1,11 +0,0 @@
/* File : example.i */
%module example
%{
#include "example.h"
%}
/* Let's just grab the original header file here */
%include "example.h"

View file

@ -1,28 +0,0 @@
int main()
{
write("*** color ***\n");
write(" RED = " + .example.RED + "\n");
write(" BLUE = " + .example.BLUE + "\n");
write(" GREEN = " + .example.GREEN + "\n");
write("\n*** Foo::speed ***\n");
write(" Foo_IMPULSE = " + .example.Foo.IMPULSE + "\n");
write(" Foo_WARP = " + .example.Foo.WARP + "\n");
write(" Foo_LUDICROUS = " + .example.Foo.LUDICROUS + "\n");
write("\nTesting use of enums with functions\n\n");
.example.enum_test(.example.RED, .example.Foo.IMPULSE);
.example.enum_test(.example.BLUE, .example.Foo.WARP);
.example.enum_test(.example.GREEN, .example.Foo.LUDICROUS);
.example.enum_test(1234, 5678);
write("\nTesting use of enum with class method\n");
.example.Foo f = .example.Foo();
f->enum_test(.example.Foo.IMPULSE);
f->enum_test(.example.Foo.WARP);
f->enum_test(.example.Foo.LUDICROUS);
return 0;
}

View file

@ -1,23 +0,0 @@
TOP = ../..
SWIGEXE = $(TOP)/../swig
SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib
CXXSRCS = example.cxx
TARGET = example
INTERFACE = example.i
LIBS = -lstdc++ -lm
check: build
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' pike_run
build:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' pike_cpp
static:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='mypike' INTERFACE='$(INTERFACE)' pike_cpp_static
clean:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' pike_clean

View file

@ -1,115 +0,0 @@
#include <iostream>
#include "example.h"
// Overloaded constructors for class Bar
Bar::Bar() {
std::cout << "Called Bar::Bar()" << std::endl;
}
Bar::Bar(const Bar&) {
std::cout << "Called Bar::Bar(const Bar&)" << std::endl;
}
Bar::Bar(double x) {
std::cout << "Called Bar::Bar(double) with x = " << x << std::endl;
}
Bar::Bar(double x, char *y) {
std::cout << "Called Bar::Bar(double, char *) with x, y = " << x << ", \"" << y << "\"" << std::endl;
}
Bar::Bar(int x, int y) {
std::cout << "Called Bar::Bar(int, int) with x, y = " << x << ", " << y << std::endl;
}
Bar::Bar(char *x) {
std::cout << "Called Bar::Bar(char *) with x = \"" << x << "\"" << std::endl;
}
Bar::Bar(int x) {
std::cout << "Called Bar::Bar(int) with x = " << x << std::endl;
}
Bar::Bar(long x) {
std::cout << "Called Bar::Bar(long) with x = " << x << std::endl;
}
Bar::Bar(Bar *x) {
std::cout << "Called Bar::Bar(Bar *) with x = " << x << std::endl;
}
// Overloaded member functions
void Bar::foo(const Bar& x) {
std::cout << "Called Bar::foo(const Bar&) with &x = " << &x << std::endl;
}
void Bar::foo(double x) {
std::cout << "Called Bar::foo(double) with x = " << x << std::endl;
}
void Bar::foo(double x, char *y) {
std::cout << "Called Bar::foo(double, char *) with x, y = " << x << ", \"" << y << "\"" << std::endl;
}
void Bar::foo(int x, int y) {
std::cout << "Called Bar::foo(int, int) with x, y = " << x << ", " << y << std::endl;
}
void Bar::foo(char *x) {
std::cout << "Called Bar::foo(char *) with x = \"" << x << "\"" << std::endl;
}
void Bar::foo(int x) {
std::cout << "Called Bar::foo(int) with x = " << x << std::endl;
}
void Bar::foo(long x) {
std::cout << "Called Bar::foo(long) with x = " << x << std::endl;
}
void Bar::foo(Bar *x) {
std::cout << "Called Bar::foo(Bar *) with x = " << x << std::endl;
}
void Bar::spam(int x, int y, int z) {
std::cout << "Called Bar::spam(int, int, int) with x, y, z = " << x << ", " << y << ", " << z << std::endl;
}
void Bar::spam(double x, int y, int z) {
std::cout << "Called Bar::spam(double, int, int) with x, y, z = " << x << ", " << y << ", " << z << std::endl;
}
// Overloaded global methods
void foo(const Bar& x) {
std::cout << "Called foo(const Bar& x) with &x = " << &x << std::endl;
}
void foo(double x) {
std::cout << "Called foo(double) with x = " << x << std::endl;
}
void foo(double x, char *y) {
std::cout << "Called foo(double, char *) with x, y = " << x << ", \"" << y << "\"" << std::endl;
}
void foo(int x, int y) {
std::cout << "Called foo(int, int) with x, y = " << x << ", " << y << std::endl;
}
void foo(char *x) {
std::cout << "Called foo(char *) with x = \"" << x << "\"" << std::endl;
}
void foo(int x) {
std::cout << "Called foo(int) with x = " << x << std::endl;
}
void foo(long x) {
std::cout << "Called foo(long) with x = " << x << std::endl;
}
void foo(Bar *x) {
std::cout << "Called foo(Bar *) with x = " << x << std::endl;
}

View file

@ -1,41 +0,0 @@
#ifndef EXAMPLE_H
#define EXAMPLE_H
class Bar {
public:
Bar();
Bar(const Bar&);
Bar(double);
Bar(double, char *);
Bar(int, int);
Bar(char *);
Bar(long);
Bar(int);
Bar(Bar *);
void foo(const Bar&);
void foo(double);
void foo(double, char *);
void foo(int, int);
void foo(char *);
void foo(long);
void foo(int);
void foo(Bar *);
void spam(int x, int y=2, int z=3);
void spam(double x, int y=2, int z=3);
};
void foo(const Bar&);
void foo(double);
void foo(double, char *);
void foo(int, int);
void foo(char *);
void foo(int);
void foo(long);
void foo(Bar *);
void spam(int x, int y=2, int z=3);
void spam(double x, int y=2, int z=3);
#endif

View file

@ -1,28 +0,0 @@
/* File : example.i */
%module example
%{
#include "example.h"
%}
/**
* These overloaded declarations conflict with other overloads (as far as
* SWIG's Ruby module's implementation for overloaded methods is concerned).
* One option is use the %rename directive to rename the conflicting methods;
* here, we're just using %ignore to avoid wrapping some of the overloaded
* functions altogether.
*/
%ignore Bar;
%ignore Bar::Bar(Bar *);
%ignore Bar::Bar(long);
%ignore Bar::foo(const Bar&);
%ignore Bar::foo(long);
%ignore ::foo(const Bar&);
%ignore ::foo(int);
/* Let's just grab the original header file here */
%include "example.h"

View file

@ -1,83 +0,0 @@
// import .example;
int main()
{
// This should invoke foo(double)
.example.foo(3.14159);
// This should invoke foo(double, char *)
.example.foo(3.14159, "Pi");
// This should invoke foo(int, int)
.example.foo(3, 4);
// This should invoke foo(char *)
.example.foo("This is a test");
// This should invoke foo(long)
.example.foo(42);
/*
// This should invoke Bar::Bar() followed by foo(Bar *)
foo(Bar.new);
// Skip a line
write("\n");
// This should invoke Bar::Bar(double)
Bar.new(3.14159);
// This should invoke Bar::Bar(double, char *)
Bar.new(3.14159, "Pi");
// This should invoke Bar::Bar(int, int)
Bar.new(3, 4);
// This should invoke Bar::Bar(char *)
Bar.new("This is a test");
// This should invoke Bar::Bar(int)
Bar.new(42);
// This should invoke Bar::Bar() for the input argument,
// followed by Bar::Bar(const Bar&).
Bar.new(Bar.new);
// Skip a line
write("\n");
*/
// Construct a new Bar instance (invokes Bar::Bar())
/*
bar = Bar.new;
// This should invoke Bar::foo(double)
bar.foo(3.14159);
// This should invoke Bar::foo(double, char *)
bar.foo(3.14159, "Pi");
// This should invoke Bar::foo(int, int)
bar.foo(3, 4);
// This should invoke Bar::foo(char *)
bar.foo("This is a test");
// This should invoke Bar::foo(int)
bar.foo(42);
// This should invoke Bar::Bar() to construct the input
// argument, followed by Bar::foo(Bar *).
bar.foo(Example::Bar.new);
// This should invoke Bar::spam(int x, int y, int z)
bar.spam(1);
// This should invoke Bar::spam(double x, int y, int z)
bar.spam(3.14159);
*/
write("Goodbye\n");
return 0;
}

View file

@ -1,22 +0,0 @@
TOP = ../..
SWIGEXE = $(TOP)/../swig
SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib
SRCS = example.c
TARGET = example
INTERFACE = example.i
check: build
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' pike_run
build:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' pike
static:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='mypike' INTERFACE='$(INTERFACE)' pike_static
clean:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' pike_clean

View file

@ -1,18 +0,0 @@
/* File : example.c */
/* A global variable */
double Foo = 3.0;
/* Compute the greatest common divisor of positive integers */
int gcd(int x, int y) {
int g;
g = y;
while (x > 0) {
g = x;
x = y % x;
y = g;
}
return g;
}

View file

@ -1,7 +0,0 @@
/* File : example.i */
%module example
%inline %{
extern int gcd(int x, int y);
extern double Foo;
%}

View file

@ -1,20 +0,0 @@
int main()
{
/* Call our gcd() function */
int x = 42;
int y = 105;
int g = .example.gcd(x, y);
write("The gcd of %d and %d is %d\n", x, y, g);
/* Manipulate the Foo global variable */
/* Output its current value */
write("Foo = %f\n", .example->Foo_get());
/* Change its value */
.example->Foo_set(3.1415926);
/* See if the change took effect */
write("Foo = %f\n", .example->Foo_get());
return 0;
}

View file

@ -1,24 +0,0 @@
TOP = ../..
SWIGEXE = $(TOP)/../swig
SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib
CXXSRCS =
TARGET = example
INTERFACE = example.i
LIBS = -lm
SWIGOPT =
check: build
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' pike_run
build:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' pike_cpp
static:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
SWIGOPT='$(SWIGOPT)' TARGET='mypike' INTERFACE='$(INTERFACE)' pike_cpp_static
clean:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' pike_clean

View file

@ -1,32 +0,0 @@
/* File : example.h */
// Some template definitions
template<class T> T max(T a, T b) { return a>b ? a : b; }
template<class T> class vector {
T *v;
int sz;
public:
vector(int _sz) {
v = new T[_sz];
sz = _sz;
}
T &get(int index) {
return v[index];
}
void set(int index, T &val) {
v[index] = val;
}
#ifdef SWIG
%extend {
T getitem(int index) {
return $self->get(index);
}
void setitem(int index, T val) {
$self->set(index,val);
}
}
#endif
};

View file

@ -1,17 +0,0 @@
/* File : example.i */
%module example
%{
#include "example.h"
%}
/* Let's just grab the original header file here */
%include "example.h"
/* Now instantiate some specific template declarations */
%template(maxint) max<int>;
%template(maxdouble) max<double>;
%template(vecint) vector<int>;
%template(vecdouble) vector<double>;

View file

@ -1,33 +0,0 @@
int main()
{
// Call some templated functions
write(sprintf("%d\n", .example.maxint(3, 7)));
write(sprintf("%f\n", .example.maxdouble(3.14, 2.18)));
// Create some objects
.example.vecint iv = .example.vecint(100);
.example.vecdouble dv = .example.vecdouble(1000);
for (int i = 0; i < 100; i++) {
iv->setitem(i, 2*i);
}
for (int i = 0; i < 1000; i++) {
dv->setitem(i, 1.0/(i+1));
}
int isum = 0;
for (int i = 0; i < 100; i++) {
isum += iv->getitem(i);
}
write(sprintf("%d\n", isum));
float fsum = 0.0;
for (int i = 0; i < 1000; i++) {
fsum += dv->getitem(i);
}
write(sprintf("%f\n", fsum));
return 0;
}

View file

@ -1,389 +0,0 @@
;;; This is experimental code that uses the s-expression
;;; representation of a C/C++ library interface to generate Foreign
;;; Function Interface definitions for use with Kevin Rosenberg's
;;; UFFI.
;;;
;;; Written by Matthias Koeppe <mkoeppe@mail.math.uni-magdeburg.de>
(eval-when (:compile-toplevel :load-toplevel :execute)
(require 'port) ; from CLOCC
(require 'uffi))
(in-package :cl-user)
;; Interaction with the SWIG binary
(defvar *swig-source-directory* #p"/home/mkoeppe/s/swig1.3/")
(defvar *swig-program* (merge-pathnames "swig" *swig-source-directory*))
(defun run-swig (swig-interface-file-name &key directory-search-list module
ignore-errors c++)
(let ((temp-file-name "/tmp/swig.lsp"))
(let ((process
(port:run-prog (namestring *swig-program*)
:output t
:args `(,@(and c++ '("-c++"))
"-sexp"
,@(mapcar (lambda (dir)
(concatenate 'string
"-I" (namestring dir)))
directory-search-list)
,@(and module
`("-module" ,module))
"-o" ,temp-file-name
,(namestring swig-interface-file-name)))))
#+cmu (unless (or (zerop (ext:process-exit-code process))
ignore-errors)
(error "Process swig exited abnormally"))
(with-open-file (s temp-file-name)
(read s)))))
;; Type system
(defun parse-swigtype (type-string &key start end junk-ok)
"Parse TYPE-STRING as SWIG's internal representation of C/C++
types. Return two values: The type description (an improper list) and
the terminating index into TYPE-STRING."
;; SWIG's internal representation is described in Source/Swig/stype.c
(unless start
(setq start 0))
(unless end
(setq end (length type-string)))
(flet ((prefix-match (prefix)
(let ((position (mismatch prefix type-string :start2 start :end2 end)))
(or (not position)
(= position (length prefix)))))
(bad-type-error (reason)
(error "Bad SWIG type (~A): ~A" reason
(subseq type-string start end)))
(type-char (index)
(and (< index (length type-string))
(char type-string index)))
(cons-and-recurse (prefix start end)
(multiple-value-bind (type-description index)
(parse-swigtype type-string :start start :end end
:junk-ok junk-ok)
(values (cons prefix type-description)
index))))
(cond
((prefix-match "p.") ; pointer
(cons-and-recurse '* (+ start 2) end))
((prefix-match "r.") ; C++ reference
(cons-and-recurse '& (+ start 2) end))
((prefix-match "a(") ; array
(let ((closing-paren (position #\) type-string
:start (+ start 2)
:end end)))
(unless closing-paren
(bad-type-error "missing right paren"))
(unless (eql (type-char (+ closing-paren 1)) #\.)
(bad-type-error "missing dot"))
(cons-and-recurse (list 'ARRAY (subseq type-string (+ start 2) closing-paren))
(+ closing-paren 2) end)))
((prefix-match "q(") ; qualifier (const, volatile)
(let ((closing-paren (position #\) type-string
:start (+ start 2)
:end end)))
(unless closing-paren
(bad-type-error "missing right paren"))
(unless (eql (type-char (+ closing-paren 1)) #\.)
(bad-type-error "missing dot"))
(cons-and-recurse (list 'QUALIFIER (subseq type-string (+ start 2) closing-paren))
(+ closing-paren 2) end)))
((prefix-match "m(") ; C++ member pointer
(multiple-value-bind (class-type class-end-index)
(parse-swigtype type-string :junk-ok t
:start (+ start 2) :end end)
(unless (eql (type-char class-end-index) #\))
(bad-type-error "missing right paren"))
(unless (eql (type-char (+ class-end-index 1)) #\.)
(bad-type-error "missing dot"))
(cons-and-recurse (list 'MEMBER-POINTER class-type)
(+ class-end-index 2) end)))
((prefix-match "f(") ; function
(loop with index = (+ start 2)
until (eql (type-char index) #\))
collect (multiple-value-bind (arg-type arg-end-index)
(parse-swigtype type-string :junk-ok t
:start index :end end)
(case (type-char arg-end-index)
(#\, (setq index (+ arg-end-index 1)))
(#\) (setq index arg-end-index))
(otherwise (bad-type-error "comma or right paren expected")))
arg-type)
into arg-types
finally (unless (eql (type-char (+ index 1)) #\.)
(bad-type-error "missing dot"))
(return (cons-and-recurse (cons 'FUNCTION arg-types)
(+ index 2) end))))
((prefix-match "v(") ;varargs
(let ((closing-paren (position #\) type-string
:start (+ start 2)
:end end)))
(unless closing-paren
(bad-type-error "missing right paren"))
(values (list 'VARARGS (subseq type-string (+ start 2) closing-paren))
(+ closing-paren 1))))
(t (let ((junk-position (position-if (lambda (char)
(member char '(#\, #\( #\) #\.)))
type-string
:start start :end end)))
(cond (junk-position ; found junk
(unless junk-ok
(bad-type-error "trailing junk"))
(values (subseq type-string start junk-position)
junk-position))
(t
(values (subseq type-string start end)
end))))))))
(defun swigtype-function-p (swigtype)
"Check whether SWIGTYPE designates a function. If so, the second
value is the list of argument types, and the third value is the return
type."
(if (and (consp swigtype)
(consp (first swigtype))
(eql (first (first swigtype)) 'FUNCTION))
(values t (rest (first swigtype)) (rest swigtype))
(values nil nil nil)))
;; UFFI
(defvar *uffi-definitions* '())
(defconstant *uffi-default-primitive-type-alist*
'(("char" . :char)
("unsigned char" . :unsigned-byte)
("signed char" . :byte)
("short" . :short)
("signed short" . :short)
("unsigned short" . :unsigned-short)
("int" . :int)
("signed int" . :int)
("unsigned int" . :unsigned-int)
("long" . :long)
("signed long" . :long)
("unsigned long" . :unsigned-long)
("float" . :float)
("double" . :double)
((* . "char") . :cstring)
((* . "void") . :pointer-void)
("void" . :void)))
(defvar *uffi-primitive-type-alist* *uffi-default-primitive-type-alist*)
(defun uffi-type-spec (type-list)
"Return the UFFI type spec equivalent to TYPE-LIST, or NIL if there
is no representation."
(let ((primitive-type-pair
(assoc type-list *uffi-primitive-type-alist* :test 'equal)))
(cond
(primitive-type-pair
(cdr primitive-type-pair))
((and (consp type-list)
(eql (first type-list) '*))
(let ((base-type-spec (uffi-type-spec (rest type-list))))
(cond
((not base-type-spec)
:pointer-void)
(t
(list '* base-type-spec)))))
(t nil))))
;; Parse tree
(defvar *uffi-output* nil)
(defun emit-uffi-definition (uffi-definition)
(format *uffi-output* "~&~S~%" uffi-definition)
(push uffi-definition *uffi-definitions*))
(defun make-cl-symbol (c-identifier &key uninterned)
(let ((name (substitute #\- #\_ (string-upcase c-identifier))))
(if uninterned
(make-symbol name)
(intern name))))
(defvar *class-scope* '() "A stack of names of nested C++ classes.")
(defvar *struct-fields* '())
(defvar *linkage* :C "NIL or :C")
(defgeneric handle-node (node-type &key &allow-other-keys)
(:documentation "Handle a node of SWIG's parse tree of a C/C++ program"))
(defmethod handle-node ((node-type t) &key &allow-other-keys)
;; do nothing for unknown node types
nil)
(defmethod handle-node ((node-type (eql 'cdecl)) &key name decl storage parms type &allow-other-keys)
(let ((swigtype (parse-swigtype (concatenate 'string decl type))))
(let ((*print-pretty* nil) ; or FUNCTION would be printed as #' by cmucl
(*print-circle* t))
(format *uffi-output* "~&;; C Declaration: ~A ~A ~A ~A~%;; with-parms ~W~%;; of-type ~W~%"
storage type name decl parms swigtype))
(multiple-value-bind (function-p arg-swigtype-list return-swigtype)
(swigtype-function-p swigtype)
(declare (ignore arg-swigtype-list))
(cond
((and (null *class-scope*) function-p
(or (eql *linkage* :c)
(string= storage "externc")))
;; ordinary top-level function with C linkage
(let ((argnum 0)
(argname-list '()))
(flet ((unique-argname (name)
;; Sometimes the functions in SWIG interfaces
;; do not have unique names. Make them unique
;; by adding a suffix. Also avoid symbols
;; that are specially bound.
(unless name
(setq name (format nil "arg~D" argnum)))
(let ((argname (make-cl-symbol name)))
(when (boundp argname) ;specially bound
(setq argname (make-cl-symbol name :uninterned t)))
(push argname argname-list)
argname)))
(let ((uffi-arg-list
(mapcan (lambda (param)
(incf argnum)
(destructuring-bind (&key name type &allow-other-keys) param
(let ((uffi-type (uffi-type-spec (parse-swigtype type))))
(cond
((not uffi-type)
(format *uffi-output* "~&;; Warning: Cannot handle type ~S of argument `~A'~%"
type name)
(return-from handle-node))
((eq uffi-type :void)
'())
(t
(let ((symbol (unique-argname name)))
(list `(,symbol ,uffi-type))))))))
parms))
(uffi-return-type
(uffi-type-spec return-swigtype)))
(unless uffi-return-type
(format *uffi-output* "~&;; Warning: Cannot handle return type `~S'~%"
return-swigtype)
(return-from handle-node))
(emit-uffi-definition `(UFFI:DEF-FUNCTION ,name ,uffi-arg-list :RETURNING ,uffi-return-type))))))
((and (not (null *class-scope*)) (null (rest *class-scope*))
(not function-p)) ; class/struct member (no nested structs)
(let ((uffi-type (uffi-type-spec swigtype)))
(unless uffi-type
(format *uffi-output* "~&;; Warning: Cannot handle type ~S of struct field `~A'~%"
type name)
(return-from handle-node))
(push `(,(make-cl-symbol name) ,uffi-type) *struct-fields*)))))))
(defmethod handle-node ((node-type (eql 'class)) &key name children kind &allow-other-keys)
(format *uffi-output* "~&;; Class ~A~%" name)
(let ((*class-scope* (cons name *class-scope*))
(*struct-fields* '()))
(dolist (child children)
(apply 'handle-node child))
(emit-uffi-definition `(,(if (string= kind "union")
'UFFI:DEF-UNION
'UFFI:DEF-STRUCT)
,(make-cl-symbol name) ,@(nreverse *struct-fields*)))))
(defmethod handle-node ((node-type (eql 'top)) &key children &allow-other-keys)
(dolist (child children)
(apply 'handle-node child)))
(defmethod handle-node ((node-type (eql 'include)) &key name children &allow-other-keys)
(format *uffi-output* ";; INCLUDE ~A~%" name)
(dolist (child children)
(apply 'handle-node child)))
(defmethod handle-node ((node-type (eql 'extern)) &key name children &allow-other-keys)
(format *uffi-output* ";; EXTERN \"C\" ~A~%" name)
(let ((*linkage* :c))
(dolist (child children)
(apply 'handle-node child))))
;;(defun compute-uffi-definitions (swig-interface)
;; (let ((*uffi-definitions* '()))
;; (handle-node swig-interface)
;; *uffi-definitions*))
;; Test instances
;;; Link to SWIG itself
#||
(defparameter *c++-compiler* "g++")
(defun stdc++-library (&key env)
(let ((error-output (make-string-output-stream)))
(let ((name-output (make-string-output-stream)))
(let ((proc (ext:run-program
*c++-compiler*
'("-print-file-name=libstdc++.so")
:env env
:input nil
:output name-output
:error error-output)))
(unless proc
(error "Could not run ~A" *c++-compiler*))
(unless (zerop (ext:process-exit-code proc))
(system:serve-all-events 0)
(error "~A failed:~%~A" *c++-compiler*
(get-output-stream-string error-output))))
(string-right-trim '(#\Newline) (get-output-stream-string name-output)))))
(defvar *swig-interface* nil)
(defvar *swig-uffi-pathname* #p"/tmp/swig-uffi.lisp")
(defun link-swig ()
(setq *swig-interface*
(run-swig (merge-pathnames "Source/swig.i" *swig-source-directory*)
:directory-search-list
(list (merge-pathnames "Source/" *swig-source-directory*))
:module "swig"
:ignore-errors t
:c++ t))
(with-open-file (f *swig-uffi-pathname* :direction :output)
(let ((*linkage* :c++)
(*uffi-definitions* '())
(*uffi-output* f)
(*uffi-primitive-type-alist* *uffi-default-primitive-type-alist*))
(apply 'handle-node *swig-interface*)))
(compile-file *swig-uffi-pathname*)
(alien:load-foreign (merge-pathnames "Source/libswig.a"
*swig-source-directory*)
:libraries (list (stdc++-library)))
;; FIXME: UFFI stuffes a "-l" in front of the passed library names
;; (uffi:load-foreign-library (merge-pathnames "Source/libswig.a"
;; *swig-source-directory*)
;; :supporting-libraries
;; (list (stdc++-library)))
(load (compile-file-pathname *swig-uffi-pathname*)))
||#
;;;; TODO:
;; * How to do type lookups? Is everything important that SWIG knows
;; about the types written out? What to make of typemaps?
;;
;; * Wrapped functions should probably automatically COERCE their
;; arguments (as of type DOUBLE-FLOAT), to make the functions more
;; flexible?
;;
;; * Why are the functions created by FFI interpreted?
;;
;; * We can't deal with more complicated structs and C++ classes
;; directly with the FFI; we have to emit SWIG wrappers that access
;; those classes.
;;
;; * A CLOS layer where structure fields are mapped as slots. It
;; looks like we need MOP functions to implement this.
;;
;; * Maybe modify SWIG so that key-value hashes are distinguished from
;; value-value hashes.

View file

@ -1,126 +0,0 @@
#######################################################################
# Makefile for allegrocl test-suite
#######################################################################
LANGUAGE = allegrocl
ALLEGROCL = @ALLEGROCLBIN@
SCRIPTSUFFIX = _runme.lisp
srcdir = @srcdir@
top_srcdir = @top_srcdir@
top_builddir = @top_builddir@
# these cpp tests generate warnings/errors when compiling
# the wrapper .cxx file.
CPP_TEST_BROKEN_CXX =
# the error is wrap:action code generated by swig. \
# error: can't convert [std::string] 'b' to 'bool' \
# might just need a bool overload op for std::string. \
global_vars \
# same as w/ global_vars but with more errors in cxx file \
naturalvar \
# these cpp tests aren't working. Fix 'em
# need to further separate these into tests requiring
# std libraries, or the $ldestructor problem.
CPP_TEST_BROKEN_ACL = \
contract \
allprotected \
# 'throws' typemap entries. \
cplusplus_throw \
# 'throws' typemap entries. \
default_args \
# missing typemaps. suspect module support needed \
dynamic_cast \
extend_variable \
# cdata.i support needed \
li_cdata_cpp \
# warning generated. otherwise all good. \
operator_overload \
# std_common.i support \
sizet \
# std_vector.i support. \
template_default \
# *** line 31. can't copy typemap?? \
typemap_namespace \
# these aren't working due to longlong support. (low hanging fruit)
CPP_TEST_BROKEN_LONGLONG = \
arrays_dimensionless \
arrays_global \
arrays_global_twodim \
li_typemaps \
li_windows \
long_long_apply \
primitive_ref \
reference_global_vars \
template_default_arg
# These are currently unsupported.
CPP_TEST_CASES_ACL_UNSUPPORTED = \
# contract support \
aggregate \
# directors support \
apply_signed_char \
# contract support \
contract \
director_exception \
director_protected \
exception_order \
# 'throws' typemap support \
extern_throws \
throw_exception \
using_pointers \
C_TEST_CASES_ACL_BROKEN = \
# 'cdate.i' module support \
li_cdata \
# adding an existing type defnition... \
typedef_struct \
# swigrun.swg support. \
typemap_subst
C_TEST_BROKEN_LONGLONG = \
long_long
# std lib support hasn't been done yet.
SKIP_CPP_STD_CASES = Yes
include $(srcdir)/../common.mk
# Overridden variables here
# SWIGOPT += -debug-module 4
# Custom tests - tests with additional commandline options
# none!
# Rules for the different types of tests
%.cpptest:
$(setup)
+$(swig_and_compile_cpp)
$(run_testcase)
%.ctest:
$(setup)
+$(swig_and_compile_c)
$(run_testcase)
%.multicpptest:
$(setup)
+$(swig_and_compile_multi_cpp)
$(run_testcase)
# Runs the testcase. A testcase is only run if
# a file is found which has _runme.lisp appended after the testcase name.
run_testcase = \
if [ -f $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then \
env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH $(RUNTOOL) $(ALLEGROCLBIN) -batch -s $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX); \
fi
%.clean:
@rm -f $*.cl
clean:
$(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile SRCDIR="$(SRCDIR)" allegrocl_clean

View file

@ -44,8 +44,6 @@
// unsigned char* as strings
#if defined(SWIGJAVA) || defined(SWIGCSHARP)
/* Note: Chicken does not allow unsigned char * in strings */
%apply char [ANY] {TAscii[ANY]}
%apply char [] {TAscii []}
%apply char * {TAscii *}

View file

@ -1,101 +0,0 @@
#######################################################################
# Makefile for chicken test-suite
#######################################################################
LANGUAGE = chicken
VARIANT =
SCRIPTSUFFIX = _runme.ss
PROXYSUFFIX = _runme_proxy.ss
srcdir = @srcdir@
top_srcdir = @top_srcdir@
top_builddir = @top_builddir@
CHICKEN_CSI = @CHICKEN_CSI@ -quiet -batch -no-init
SO = @SO@
#C_TEST_CASES = long_long list_vector pointer_in_out multivalue
# Skip the STD cases for now, except for li_std_string.i
SKIP_CPP_STD_CASES = Yes
CPP_TEST_CASES += li_std_string
EXTRA_TEST_CASES += chicken_ext_test.externaltest
include $(srcdir)/../common.mk
# Overridden variables here
SWIGOPT += -nounit
# Custom tests - tests with additional commandline options
# If there exists a PROXYSUFFIX runme file, we also generate the wrapper
# with the -proxy argument
%.cppproxy: SWIGOPT += -proxy
%.cppproxy: SCRIPTSUFFIX = $(PROXYSUFFIX)
%.cproxy: SWIGOPT += -proxy
%.cproxy: SCRIPTSUFFIX = $(PROXYSUFFIX)
%.multiproxy: SWIGOPT += -proxy -noclosuses
%.multiproxy: SCRIPTSUFFIX = $(PROXYSUFFIX)
# Rules for the different types of tests
%.cpptest:
$(setup)
+$(swig_and_compile_cpp)
$(run_testcase)
if [ -f $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(PROXYSUFFIX) ]; then \
$(MAKE) $*.cppproxy; \
fi
%.ctest:
$(setup)
+$(swig_and_compile_c)
$(run_testcase)
if [ -f $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(PROXYSUFFIX) ]; then \
$(MAKE) $*.cproxy; \
fi
%.multicpptest:
$(setup)
+$(swig_and_compile_multi_cpp)
$(run_testcase)
if [ -f $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(PROXYSUFFIX) ]; then \
$(MAKE) $*.multiproxy; \
fi
%.externaltest:
$(setup)
+$(swig_and_compile_external)
$(run_testcase)
%.cppproxy:
echo "$(ACTION)ing $(LANGUAGE) testcase $* (with run test) with -proxy"
+$(swig_and_compile_cpp)
$(run_testcase)
%.cproxy:
echo "$(ACTION)ing $(LANGUAGE) testcase $* (with run test) with -proxy"
+$(swig_and_compile_c)
$(run_testcase)
%.multiproxy:
echo "$(ACTION)ing $(LANGUAGE) testcase $* (with run test) with -proxy"
+$(swig_and_compile_multi_cpp)
$(run_testcase)
# Runs the testcase. A testcase is only run if
# a file is found which has _runme.scm appended after the testcase name.
run_testcase = \
if [ -f $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then \
env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH $(RUNTOOL) $(CHICKEN_CSI) $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX); \
fi
# Clean
%.clean:
@exit 0
clean:
$(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile SRCDIR='$(SRCDIR)' chicken_clean
rm -f *.scm

View file

@ -1,11 +0,0 @@
See ../README for common README file.
Any testcases which have _runme.ss appended after the testcase name will be detected and run.
NOTE: I had to use _runme.ss because otherwise it would be hard to implement make clean
Since when SWIG runs it generates an example.scm file for every test, to clean those files
I needed to add a rm -f *.scm to make clean. But we don't want the runme scripts to
disappear as well!
Any testcases which have _runme_proxy.ss appended after the testcase name will be detected
and run with the -proxy argument passed to SWIG. SWIG will not be run with the -unhide-primitive
option, so the _runme_proxy.ss file must use only the tinyclos exported interface.

View file

@ -1,2 +0,0 @@
(load "casts.so")
(include "../schemerunme/casts.scm")

View file

@ -1,2 +0,0 @@
(load "char_constant.so")
(include "../schemerunme/char_constant.scm")

View file

@ -1,21 +0,0 @@
#include <chicken/chicken_ext_test_wrap_hdr.h>
#include <imports_a.h>
void test_create(C_word,C_word,C_word) C_noret;
void test_create(C_word argc, C_word closure, C_word continuation) {
C_word resultobj;
swig_type_info *type;
A *newobj;
C_word *known_space = C_alloc(C_SIZEOF_SWIG_POINTER);
C_trace("test-create");
if (argc!=2) C_bad_argc(argc,2);
newobj = new A();
type = SWIG_TypeQuery("A *");
resultobj = SWIG_NewPointerObj(newobj, type, 1);
C_kontinue(continuation, resultobj);
}

Some files were not shown because too many files have changed in this diff Show more