Merge remote-tracking branch 'upstream/master' into memleak
# Conflicts: # CHANGES.current
This commit is contained in:
commit
04a0b526eb
192 changed files with 44 additions and 23275 deletions
|
|
@ -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)
|
Version 4.1.0 (in progress)
|
||||||
===========================
|
===========================
|
||||||
|
|
||||||
2021-05-12: adr26
|
2021-05-17: adr26
|
||||||
#1985 [Python] Fix memory leaks:
|
[Python] #1985 Fix memory leaks:
|
||||||
|
|
||||||
1. Python object references were being incorrectly retained by
|
1. Python object references were being incorrectly retained by
|
||||||
SwigPyClientData, causing swig_varlink_dealloc() never to run / free
|
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
|
SWIG_Python_SetModule() (failure could be caused by OOM or a name
|
||||||
clash caused by malicious code)
|
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
|
2021-05-04: olly
|
||||||
[PHP] #1982 #1457 https://sourceforge.net/p/swig/bugs/1339/
|
[PHP] #1982 #1457 https://sourceforge.net/p/swig/bugs/1339/
|
||||||
SWIG now only use PHP's C API to implement its wrappers, and no
|
SWIG now only use PHP's C API to implement its wrappers, and no
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -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 <= 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 <Foo>, 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 <= 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 <top>) (arg1 <Foo>)) (<i>call primitive function</i>))
|
|
||||||
(define-method (foo (arg0 <top>)) (<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>
|
|
||||||
|
|
@ -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><* EXTERNAL *></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><* CALLBACK *></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>--></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>--></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 <file></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 << 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 <file></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 <file></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) > 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) > 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>
|
|
||||||
|
|
@ -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)
|
|
||||||
> <b>import example;</b>
|
|
||||||
> <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>
|
|
||||||
> <b>import example;</b>
|
|
||||||
> <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>
|
|
||||||
> <b>import example;</b>
|
|
||||||
> <b>Foo_get();</b>
|
|
||||||
(1) Result: 3.000000
|
|
||||||
> <b>Foo_set(3.14159);</b>
|
|
||||||
(2) Result: 0
|
|
||||||
> <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>
|
|
||||||
|
|
@ -1250,46 +1250,6 @@ lua_clean:
|
||||||
rm -f core @EXTRA_CLEAN@
|
rm -f core @EXTRA_CLEAN@
|
||||||
rm -f *.@OBJEXT@ *$(LUA_SO)
|
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 ######
|
##### CFFI ######
|
||||||
##################################################################
|
##################################################################
|
||||||
|
|
|
||||||
|
|
@ -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.
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
# see top-level Makefile.in
|
|
||||||
class
|
|
||||||
constants
|
|
||||||
multimap
|
|
||||||
overload
|
|
||||||
simple
|
|
||||||
|
|
@ -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)
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
@ -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();
|
|
||||||
};
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
/* File : example.i */
|
|
||||||
%module example
|
|
||||||
|
|
||||||
%{
|
|
||||||
#include "example.h"
|
|
||||||
%}
|
|
||||||
|
|
||||||
/* Let's just grab the original header file here */
|
|
||||||
%include "example.h"
|
|
||||||
|
|
@ -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)
|
|
||||||
|
|
@ -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)
|
|
||||||
|
|
@ -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)
|
|
||||||
|
|
@ -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;
|
|
||||||
|
|
@ -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)
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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.
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
%module mod1
|
|
||||||
|
|
||||||
%inline %{
|
|
||||||
class Bar {
|
|
||||||
public:
|
|
||||||
int b;
|
|
||||||
};
|
|
||||||
%}
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
%module mod2
|
|
||||||
|
|
||||||
%import "mod1.i"
|
|
||||||
|
|
||||||
%{
|
|
||||||
class Bar {
|
|
||||||
public:
|
|
||||||
int b;
|
|
||||||
};
|
|
||||||
%}
|
|
||||||
|
|
||||||
%inline %{
|
|
||||||
class Bar2 : public Bar {
|
|
||||||
public:
|
|
||||||
int c;
|
|
||||||
};
|
|
||||||
%}
|
|
||||||
|
|
@ -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"))
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
(declare (uses mod1))
|
|
||||||
(declare (uses mod2))
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
%module single
|
|
||||||
|
|
||||||
%inline %{
|
|
||||||
class Foo {
|
|
||||||
public:
|
|
||||||
int a;
|
|
||||||
};
|
|
||||||
%}
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
(run (csc -s -o single.so single.scm single_wrap.cxx))
|
|
||||||
(install-extension 'single '("single.so"))
|
|
||||||
|
|
@ -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)
|
|
||||||
|
|
@ -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)
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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;
|
|
||||||
};
|
|
||||||
%}
|
|
||||||
|
|
@ -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)
|
|
||||||
|
|
@ -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)
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
Overloading example from Chapter 5.14 of SWIG Core Documentation for
|
|
||||||
version 1.3.
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
@ -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);
|
|
||||||
};
|
|
||||||
|
|
@ -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"
|
|
||||||
|
|
||||||
|
|
@ -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)
|
|
||||||
|
|
@ -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)
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Simple example from users manual.
|
|
||||||
|
|
@ -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(<ime);
|
|
||||||
return ctime(<ime);
|
|
||||||
}
|
|
||||||
|
|
@ -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();
|
|
||||||
%}
|
|
||||||
|
|
@ -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)
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
# see top-level Makefile.in
|
|
||||||
class
|
|
||||||
enum
|
|
||||||
exception
|
|
||||||
reference
|
|
||||||
simple
|
|
||||||
typemap
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
@ -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();
|
|
||||||
};
|
|
||||||
|
|
@ -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"
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
@ -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);
|
|
||||||
|
|
@ -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"
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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);
|
|
||||||
|
|
@ -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"
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -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();
|
|
||||||
};
|
|
||||||
|
|
@ -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"
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
/* File : example.i */
|
|
||||||
%module Example
|
|
||||||
|
|
||||||
%inline %{
|
|
||||||
extern int gcd(int x, int y);
|
|
||||||
extern double Foo;
|
|
||||||
%}
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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);
|
|
||||||
|
|
@ -1,10 +1,8 @@
|
||||||
/* File : example.i */
|
/* File : example.i */
|
||||||
%module(directors="1") example
|
%module(directors="1") example
|
||||||
#ifndef SWIGSEXP
|
|
||||||
%{
|
%{
|
||||||
#include "example.h"
|
#include "example.h"
|
||||||
%}
|
%}
|
||||||
#endif
|
|
||||||
|
|
||||||
%feature("director");
|
%feature("director");
|
||||||
%include "example.h"
|
%include "example.h"
|
||||||
|
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
# see top-level Makefile.in
|
|
||||||
class
|
|
||||||
constants
|
|
||||||
enum
|
|
||||||
overload
|
|
||||||
simple
|
|
||||||
template
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
@ -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();
|
|
||||||
};
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
/* File : example.i */
|
|
||||||
%module example
|
|
||||||
|
|
||||||
%{
|
|
||||||
#include "example.h"
|
|
||||||
%}
|
|
||||||
|
|
||||||
/* Let's just grab the original header file here */
|
|
||||||
%include "example.h"
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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.
|
|
||||||
|
|
||||||
|
|
@ -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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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);
|
|
||||||
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
/* File : example.i */
|
|
||||||
%module example
|
|
||||||
|
|
||||||
%{
|
|
||||||
#include "example.h"
|
|
||||||
%}
|
|
||||||
|
|
||||||
/* Let's just grab the original header file here */
|
|
||||||
|
|
||||||
%include "example.h"
|
|
||||||
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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"
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
/* File : example.i */
|
|
||||||
%module example
|
|
||||||
|
|
||||||
%inline %{
|
|
||||||
extern int gcd(int x, int y);
|
|
||||||
extern double Foo;
|
|
||||||
%}
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
@ -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>;
|
|
||||||
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
@ -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.
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -44,8 +44,6 @@
|
||||||
// unsigned char* as strings
|
// unsigned char* as strings
|
||||||
#if defined(SWIGJAVA) || defined(SWIGCSHARP)
|
#if defined(SWIGJAVA) || defined(SWIGCSHARP)
|
||||||
|
|
||||||
/* Note: Chicken does not allow unsigned char * in strings */
|
|
||||||
|
|
||||||
%apply char [ANY] {TAscii[ANY]}
|
%apply char [ANY] {TAscii[ANY]}
|
||||||
%apply char [] {TAscii []}
|
%apply char [] {TAscii []}
|
||||||
%apply char * {TAscii *}
|
%apply char * {TAscii *}
|
||||||
|
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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.
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
(load "casts.so")
|
|
||||||
(include "../schemerunme/casts.scm")
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
(load "char_constant.so")
|
|
||||||
(include "../schemerunme/char_constant.scm")
|
|
||||||
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue