Initial commit of Octave module.

git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@10290 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
Xavier Delacour 2008-03-01 23:35:44 +00:00
commit 393391965c
275 changed files with 14004 additions and 5 deletions

View file

@ -990,6 +990,44 @@
</div>
<!-- INDEX -->
<h3><a href="Octave.html#Octave">22 SWIG and Octave</a></h3>
<!-- INDEX -->
<div class="sectiontoc">
<ul>
<li><a href="Octave.html#Octave_nn2">Preliminaries</a>
<li><a href="Octave.html#Octave_nn3">Running SWIG</a>
<ul>
<li><a href="Octave.html#Octave_nn4">Compiling and Linking and Interpreter</a>
<li><a href="Octave.html#Octave_nn5">Compiling a dynamic module</a>
<li><a href="Octave.html#Octave_nn6">Using your module</a>
</ul>
<li><a href="Octave.html#Octave_nn7">A tour of basic C/C++ wrapping</a>
<ul>
<li><a href="Octave.html#Octave_nn8">Modules</a>
<li><a href="Octave.html#Octave_nn9">Functions</a>
<li><a href="Octave.html#Octave_nn10">Global variables</a>
<li><a href="Octave.html#Octave_nn11">Constants and enums</a>
<li><a href="Octave.html#Octave_nn12">Pointers</a>
<li><a href="Octave.html#Octave_nn13">Structures</a>
<!--
<li><a href="Octave.html#Octave_nn14">C++ classes</a>
<li><a href="Octave.html#Octave_nn15">C++ inheritance</a>
<li><a href="Octave.html#Octave_nn16">Pointers, references, values, and arrays</a>
<li><a href="Octave.html#Octave_nn17">C++ overloaded functions</a>
<li><a href="Octave.html#Octave_nn18">C++ operators</a>
<li><a href="Octave.html#Octave_nn19">Class extension with %extend</a>
<li><a href="Octave.html#Octave_nn20">C++ templates</a>
<li><a href="Octave.html#Octave_nn22">Writing your own custom wrappers</a>
</ul>
<li><a href="Octave.html#Octave_nn23">Details on the Octave binding</a>
-->
<ul>
</ul>
</ul>
</div>
<!-- INDEX -->
<h3><a href="Perl5.html#Perl5">26 SWIG and Perl5</a></h3>
<!-- INDEX -->

721
Doc/Manual/Octave.html Normal file
View file

@ -0,0 +1,721 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>SWIG and Octave</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body bgcolor="#ffffff">
<H1><a name="Octave_nn1"></a>22 SWIG and Octave</H1>
<!-- INDEX -->
<div class="sectiontoc">
<ul>
<li><a href="#Octave_nn2">Preliminaries</a>
<li><a href="#Octave_nn3">Running SWIG</a>
<ul>
<li><a href="#Octave_nn4">Compiling and Linking and Interpreter</a>
<li><a href="#Octave_nn5">Compiling a dynamic module</a>
<li><a href="#Octave_nn6">Using your module</a>
</ul>
<li><a href="#Octave_nn7">A tour of basic C/C++ wrapping</a>
<ul>
<li><a href="#Octave_nn8">Modules</a>
<li><a href="#Octave_nn9">Functions</a>
<li><a href="#Octave_nn10">Global variables</a>
<li><a href="#Octave_nn11">Constants and enums</a>
<li><a href="#Octave_nn12">Pointers</a>
<li><a href="#Octave_nn13">Structures</a>
<li><a href="#Octave_nn14">C++ classes</a>
<li><a href="#Octave_nn15">C++ inheritance</a>
<li><a href="#Octave_nn16">Pointers, references, values, and arrays</a>
<li><a href="#Octave_nn17">C++ overloaded functions</a>
<li><a href="#Octave_nn18">C++ operators</a>
<li><a href="#Octave_nn19">Class extension with %extend</a>
<li><a href="#Octave_nn20">C++ templates</a>
<li><a href="#Octave_nn21">C++ Smart Pointers</a>
</ul>
<li><a href="#Octave_nn22">Details...</a>
<ul>
<li><a href="#Octave_nn22">Directors (calling Octave from C++ code)</a>
<li><a href="#Octave_nn23">Threads</a>
<li><a href="#Octave_nn24">Memory management</a>
<li><a href="#Octave_nn25">STL support</a>
<li><a href="#Octave_nn26">Matrix typemaps</a>
</ul>
<ul>
</ul>
</ul>
</div>
<!-- INDEX -->
<p>
Octave is a high-level language intended for numerical programming that is mostly compatible with MATLAB.
More information can be found at <a href="http://www.octave.org">octave.org</a>.
</p>
<p>
The Octave documentation is preliminary and is intended to give only a cursory introduction to using the module. You should (at a minimum) also read the SWIG documentation that is not specific to Octave. (also note, some of the early sections here are adapted from the Lua docs).
</p>
<p>
For now, the best way to find information about how to use the Octave module is to look at the code itself, test-suite, and examples. There are a dozen or so examples in the Examples/octave directory, and hundreds in the test suite (Examples/test-suite and Examples/test-suite/octave).
</p>
<p>
The bulk of the Octave-specific wrapper generator code is in Source/Modules/octave.cxx. The runtime components are in Lib/octave, and in particular Lib/octave/octrun.swg.
</p>
<H2><a name="Octave_nn2"></a>22.1 Preliminaries</H2>
<p>
The current SWIG implemention is based on Octave 2.9.12. Support for other versions (in particular the recent 3.0) has not been tested, nor has support for any OS other than Linux.
</p>
<H2><a name="Octave_nn3"></a>22.2 Running SWIG</H2>
<p>
Let's start with a very simple SWIG interface file:
</p>
<p>
<div class="code"><pre>%module example
%{
#include "example.h"
%}
int gcd(int x, int y);
extern double Foo; </pre></div>
</p>
<p>
To build an Octave module, run SWIG using the <tt>-octave</tt> option. The <tt>-c++</tt> option is required (for now) as Octave itself is written in C++ and thus the wrapper code must also be.
</p>
<p>
<div class="shell"><pre>$ swig -octave -c++ example.i </pre></div>
</p>
<p>
This creates a C/C++ source file <tt>example_wrap.cxx</tt>. The generated C++ source file contains the low-level wrappers that need to be compiled and linked with the rest of your C/C++ application (in this case, the gcd implementation) to create an extension module.
</p>
<p>
The swig command line has a number of options you can use, like to redirect it's output. Use <tt>swig --help</tt> to learn about these.
</p>
<H3><a name="Octave_nn5"></a>22.2.2 Compiling a dynamic module</H3>
<p>
Octave modules are DLLs/shared objects having the ".oct" suffix.
Building an oct file is usually done with the mkoctfile command (either within Octave itself, or from the shell). For example,
</p>
<p>
<div class="shell"><pre>
$ swig -octave -c++ example.i -o example_wrap.cxx
$ mkoctfile example_wrap.cxx example.c
</pre></div>
</p>
<p>
where example.c is the file containing the gcd() implementation.
</p>
<p>
mkoctfile can also be used to extract the build parameters required to invoke the compiler and linker yourself. See the Octave manual and mkoctfile man page.
</p>
<p>
mkoctfile will produce example.oct, which contains the compiled extension module. Loading it into Octave is then a matter of invoking
</p>
<p>
<div class="targetlang"><pre>octave:1&gt; example</pre></div>
</p>
<p>
<H3><a name="Octave_nn6"></a>22.2.3 Using your module</H3>
</p>
<p>
Assuming all goes well, you will be able to do this:
<br>
</p>
<p>
<div class="targetlang"><pre>$ octave -q
octave:1&gt; example
octave:2&gt; example.gcd(4,6)
ans = 2
octave:3&gt; example.cvar.Foo
ans = 3
octave:4&gt; example.cvar.Foo=4;
octave:5&gt; example.cvar.Foo
ans = 4 </pre></div>
</p>
<H2><a name="Octave_nn7"></a>22.3 A tour of basic C/C++ wrapping</H2>
<H3><a name="Octave_nn8"></a>22.3.1 Modules</H3>
<p>
The SWIG module directive specifies the name of the Octave module. If you specify `module example', then in Octave everything in the module will be accessible under "example", as in the above example. When choosing a module name, make sure you don't use the same name as a built-in Octave command or standard module name.
</p>
<p>
When Octave is asked to invoke <tt>example</tt>, it will try to find the .m or .oct file that defines the function "example". It will thusly find example.oct, that upon loading will register all of the module's symbols.
</p>
<p>
Giving this function a parameter "global" will cause it to load all symbols into the global namespace in addition to the <tt>example</tt> namespace. For example:
</p>
<p>
<div class="targetlang"><pre>$ octave -q
octave:1&gt; example("global")
octave:2&gt; gcd(4,6)
ans = 2
octave:3&gt; cvar.Foo
ans = 3
octave:4&gt; cvar.Foo=4;
octave:5&gt; cvar.Foo
ans = 4
</pre></div>
</p>
<p>
It is also possible to rename the module namespace with an assignment, as in: <br>
<p>
<div class="targetlang"><pre>octave:1&gt; example;
octave:2&gt; c=example;
octave:3&gt; c.gcd(10,4)
ans = 2 </pre></div>
</p>
<p>
All global variables are put into the cvar namespace object. This is accessible either as <tt>my_module.cvar</tt>, or just <tt>cvar</tt> (if the module is imported into the global namespace).
</p>
<p>
One can also rename it by simple assignment, e.g.,
</p>
<p>
<div class="targetlang"><pre>
octave:1&gt; some_vars = cvar;
</div></pre>
</p>
<H3><a name="Octave_nn9"></a>22.3.2 Functions</H3>
<p>
Global functions are wrapped as new Octave built-in functions. For example,
</p>
<p>
<div class="code"><pre>&#037;module example
int fact(int n); </pre></div>
</p>
<p>
creates a built-in function <tt>example.fact(n)</tt> that works exactly like you think it does:
</p>
<p>
<div class="targetlang"><pre>octave:1&gt; example.fact(4)
24 </pre></div>
</p>
<p>
If there are name collisions (especially if using the "global" option), the last-loaded functions (in this case those from the SWIG module) will override the previously defined ones. <H3><a name="Octave_nn10"></a>22.3.3 Global variables</H3>
<p>
Global variables are a little special in Octave. Given a global variable:
</p>
<p>
<div class="code"><pre>%module example
extern double Foo;
</pre></div>
</p>
<p>
To expose variables, SWIG actually generates two functions, to get and set the value. In this case, Foo_set and Foo_set would be generated. SWIG then automatically calls these functions when you get and set the variable-- in the former case creating a local copy in the interpreter of the C variables, and in the latter case copying an interpreter variables onto the C variable.
</p>
<p>
<div class="targetlang"><pre>octave:1&gt; example;
octave:2&gt; c=example.cvar.Foo
c = 3
octave:3&gt; example.cvar.Foo=4;
octave:4&gt; c
c = 3
octave:5&gt; example.cvar.Foo
ans = 4</pre></div>
</p>
<p>
If a variable is marked with the %immutable directive then any attempts to set this variable will cause an Octave error. Given a global variable:
</p>
<p>
<div class="code"><pre>%module example
%immutable;
extern double Foo;
%mutable;
</pre></div>
</p>
<p>
SWIG will allow the the reading of <tt>Foo</tt> but when a set attempt is made, an error function will be called.
</p>
<p>
<div class="targetlang"><pre>octave:1&gt; example
octave:2&gt; example.Foo=4
error: attempt to set immutable member variable
error: assignment failed, or no method for `swig_type = scalar'
error: evaluating assignment expression near line 2, column 12 </pre></div>
</p>
<p>
It is possible to add new functions or variables to the module. This also allows the user to rename/remove existing functions and constants (but not linked variables, mutable or immutable). Therefore users are recommended to be careful when doing so.
</p>
<p>
<div class="targetlang"><pre>octave:1&gt; example;
octave:2&gt; example.PI=3.142;
octave:3&gt; example.PI
ans = 3.1420 </pre></div>
</p>
<H3><a name="Octave_nn11"></a>22.3.4 Constants and enums</H3>
<p>
Because Octave doesn't really have the concept of constants, C/C++ constants are not really constant in Octave. They are actually just a copy of the value into the Octave interpreter. Therefore they can be changed just as any other value. For example given some constants:
</p>
<p>
<div class="code"><pre>%module example
%constant int ICONST=42;
#define SCONST "Hello World"
enum Days{SUNDAY,MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY};
</pre></div>
</p>
<p>
This is 'effectively' converted into the following Octave code:
</p>
<p>
<div class="targetlang"><pre>example.ICONST=42
example.SCONST="Hello World"
example.SUNDAY=0
.... </pre></div>
</p>
<p>
Constants are not guaranteed to remain constant in Octave. The name of the constant could be accidentally reassigned to refer to some other object. Unfortunately, there is no easy way for SWIG to generate code that prevents this. You will just have to be careful. <H3><a name="Octave_nn12"></a>22.3.5 Pointers</H3>
</p>
<p>
C/C++ pointers are fully supported by SWIG. Furthermore, SWIG has no problem working with incomplete type information. Given a wrapping of the &lt;file.h&gt; interface:
C/C++ pointers are fully supported by SWIG. Furthermore, SWIG has no problem working with incomplete type information. Given a wrapping of the &lt;file.h&gt; interface:
</p>
<p>
<div class="code"><pre>%module example
FILE *fopen(const char *filename, const char *mode);
int fputs(const char *, FILE *);
int fclose(FILE *);
</pre></div>
</p>
<p>
When wrapped, you will be able to use the functions in a natural way from Octave. For example:
</p>
<p>
<div class="targetlang"><pre>
octave:1&gt; example;
octave:2&gt; f=example.fopen("w","junk");
octave:3&gt; example.fputs("Hello world",f);
octave:4&gt; example.fclose(f);
</pre></div>
</p>
<p>
Simply printing the value of a wrapped C++ type will print it's typename. E.g.,
</p>
<p>
<div class="targetlang"><pre>octave:1&gt; example;
octave:2&gt; f=example.fopen("junk","w");
octave:3&gt; f
f =
{
_p_FILE, ptr = 0x9b0cd00
} </pre></div>
</p>
<p>
As the user of the pointer, you are responsible for freeing it, or closing any resources associated with it (just as you would in a C program). This does not apply so strictly to classes and structs (see below).
</p>
<p>
<div class="targetlang"><pre>octave:1&gt; example;
octave:2&gt; f=example.fopen("not there","r");
error: value on right hand side of assignment is undefined
error: evaluating assignment expression near line 2, column 2 </pre></div>
</p>
<H3><a name="Octave_nn13"></a>22.3.6 Structures</H3>
<p>
SWIG wraps C structures and C++ classes by creating type objects. When invoked as a function, they create a new object of their type. The structures/classes themselves are mapped to a native Octave type. This provides a very natural interface. For example,
</p>
<p>
<div class="code"><pre>struct Point{
int x,y;
};
</pre></div>
</p>
<p>
is used as follows:
</p>
<p>
<div class="targetlang">
<pre>octave:1&gt; example;
octave:2&gt; p=example.Point();
octave:3&gt; p.x=3;
octave:4&gt; p.y=5;
octave:5&gt; p.x, p.y
ans = 3
ans = 5
</pre></div>
</p>
<H3><a name="Octave_nn14"></a>22.3.7 C++ classes</H3>
<p>
C++ classes are handled in a way identical to other modules.
</p>
<H3><a name="Octave_nn15"></a>22.3.8 C++ inheritance</H3>
<p>
Inheritance is handled in a way identical to other modules.
</p>
<H3><a name="Octave_nn16"></a>22.3.9 Pointers, references, values, and arrays</H3>
<p>
Pointers, references, values, and arrays are handled in the same way as other modules.
</p>
<p>
There are still some failing tests relating to global arrays.
</p>
<H3><a name="Octave_nn17"></a>22.3.10 C++ overloaded functions</H3>
<p>
Overloaded functions are supported, and handled as in other modules.
</p>
<H3><a name="Octave_nn18"></a>22.3.11 C++ operators</H3>
<p>
C++ operator overloading is supported, in a way similar to other modules.
</p>
<p>
SWIG types are represented in Octave by a special type called <tt>swig_ref</tt> (the full list of types can be listed with <tt>typeinfo()</tt>, and SWIG specific information can be extracted via <tt>swig_this(obj)</tt> and <tt>swig_type(obj)</tt>). This type supports all unary and binary operators between itself and all other types that exist in the system at module load time. When an operator is used (where one of the operands is a <tt>swig_ref</tt>), the runtime routes the call to either a member function of the given object, or to a global function whose named is derived from the types of the operands (either both or just the lhs or rhs). (... more details needed ...)
</p>
<p>
For example, if <tt>a</tt> and <tt>b</tt> are SWIG variables in Octave, <tt>a+b</tt> becomes <tt>a.__add(b)</tt>. The wrapper is then free to implement __add to do whatever it wants. A wrapper may define the <tt>__add</tt> function manually, %rename some other function to it, or %rename a C++ operator to it.
</p>
<p>
By default the C++ operators are renamed to their corresponding Octave operators. So without doing any work, they just work.
</p>
<p>
For example, the following:
<div class="code"><pre>
%inline {
struct A {
int value;
A(int _value) : value(_value) {}
A operator+ (const A& x) {
return A(value+x.value);
}
};
}
</pre></div>
</p>
<p>
may be used naturally from Octave:
</p>
<p>
<div class="targetlang"><pre>
a=A(2), b=A(3), c=a+b
assert(c.value==5);
</pre></div>
</p>
<p>
Octave operators are mapped in the following way:
</p>
<p>
<div class="code"><pre>
__brace a{args}
__brace_asgn a{args} = rhs
__paren a(args)
__paren_asgn a(args) = rhs
__str generates string rep
__not !a
__uplus +a
__uminus -a
__transpose a.'
__hermitian a'
__incr a++
__decr a--
__add a + b
__sub a - b
__mul a * b
__div a / b
__pow a ^ b
__ldiv a \ b
__lshift a << b
__rshift a >> b
__lt a < b
__le a <= b
__eq a == b
__ge a >= b
__gt a > b
__ne a != b
__el_mul a .* b
__el_div a ./ b
__el_pow a .^ b
__el_ldiv a .\ b
__el_and a & b
__el_or a | b
</pre></div>
</p>
<p>
On the C++ side, the default mappings are as follows:
</p>
<p>
<div class="code"><pre>
%rename(__add) *::operator+;
%rename(__add) *::operator+();
%rename(__add) *::operator+() const;
%rename(__sub) *::operator-;
%rename(__uminus) *::operator-();
%rename(__uminus) *::operator-() const;
%rename(__mul) *::operator*;
%rename(__div) *::operator/;
%rename(__mod) *::operator%;
%rename(__lshift) *::operator<<;
%rename(__rshift) *::operator>>;
%rename(__el_and) *::operator&&;
%rename(__el_or) *::operator||;
%rename(__xor) *::operator^;
%rename(__invert) *::operator~;
%rename(__lt) *::operator<;
%rename(__le) *::operator<=;
%rename(__gt) *::operator>;
%rename(__ge) *::operator>=;
%rename(__eq) *::operator==;
%rename(__ne) *::operator!=;
%rename(__not) *::operator!;
%rename(__incr) *::operator++;
%rename(__decr) *::operator--;
%rename(__paren) *::operator();
%rename(__brace) *::operator[];
</pre></div>
<H3><a name="Octave_nn19"></a>22.3.12 Class extension with %extend</H3>
<p>
The %extend directive works the same as in other modules.
</p>
<p>
You can use it to define special behavior, like for example defining Octave operators not mapped to C++ operators, or defining certain Octave mechanisms such as how an object prints. For example, the <tt>octave_value::{is_string,string_value,print}</tt> functions are routed to a special method <tt>__str</tt> that can be defined inside an %extend.
</p>
<p>
<div class="code"><pre>
%extend A {
string __str() {
stringstream sout;
sout&lt;&lt;$self->value;
return sout.str();
}
}
</pre></div>
</p>
<p>
Then in Octave one gets,
</p>
<p>
<div class="targetlang"><pre>
octave:1&gt; a=A(4);
octave:2&gt; a
a = 4
octave:3&gt; printf("%s\n",a);
4
octave:4&gt; a.__str()
4
</pre></div>
</p>
<H3><a name="Octave_nn20"></a>22.3.13 C++ templates</H3>
<p>
C++ templates are fully supported, as in other modules.
</p>
<H3><a name="Octave_nn21"></a>22.3.14 C++ Smart Pointers</H3>
<p>
C++ smart pointers are fully supported, as in other modules.
</p>
<H3><a name="Octave_nn22"></a>22.4.1 Directors (calling Octave from C++ code)</H3>
<p>
There is full support for SWIG Directors, which permits Octave code to subclass C++ classes, and implement their virtual methods.
</p>
<p>
Octave has no direct support for object oriented programming, however the <tt>swig_ref</tt> type provides some of this support. All SWIG types are wrapped inside a <tt>swig_ref</tt>. These handle calling set and get methods for C++ variables (see other SWIG docs), and invoking member functions (by prepending self parameter). You can aquire a <tt>swig_ref</tt> by having a wrapped function return a pointer, reference, or value of a non-primitive type. You can also manufacture one using the <tt>subclass</tt> function (provided by the SWIG/Octave runtime).
</p>
<p>
For example,
</p>
<p>
<div class="targetlang"><pre>
octave:1&gt; a=subclass();
octave:2&gt; a.my_var = 4;
octave:3&gt; a.my_method = @(self) printf("my_var = ",self.my_var);
octave:4&gt; a.my_method();
my_var = 4
</div></pre>
</p>
<p>
<tt>subclass()</tt> can also be used to subclass one or more C++ types. Suppose you have an interface defined by
</p>
<p>
<div class="code"><pre>
%inline {
class A {
public:
virtual my_method() {
printf("c-side routine called\n");
}
};
void call_your_method(A& a) {
a.my_method();
}
}
</pre></div>
</p>
<p>
Then from Octave you can say:
</p>
<p>
<div class="targetlang"><pre>
octave:1&gt; B=@() subclass(A(),@my_method);
octave:2&gt; function my_method(self)
octave:3&gt; printf("octave-side routine called\n");
octave:4&gt; end
octave:5&gt; call_your_method(B());
octave-side routine called
</pre></div>
</p>
<p>
or more concisely,
</p>
<p>
<div class="targetlang"><pre>
octave:1&gt; B=@() subclass(A(),'my_method',@(self) printf("octave-side routine called\n"));
octave:2&gt; call_your_method(B());
octave-side routine called
</pre></div>
</p>
<p>
Note that you have to enable directors via the %feature directive (see other modules for this).
</p>
<p>
<tt>subclass()</tt> will accept any number of C++ bases or other <tt>subclass()</tt>'ed objects, <tt>(string,octave_value)</tt> pairs, and <tt>function_handles</tt>. In the first case, these are taken as base classes; in the second case, as named members (either variables or functions, depending on whether the given value is a function handle); in the third case, as member functions whose name is taken from the given function handle. E.g.,
</p>
<p>
<div class="targetlang"><pre>
octave:1&gt; B=@(some_var=2) subclass(A(),'some_var',some_var,@some_func,'another_func',@(self) do_stuff())
</pre></div>
</p>
<p>
You can also assign non-C++ member variables and functions after construct time. There is no support for non-C++ static members.
</p>
<p>
There is limited support for explicitly referencing C++ bases. So, in the example above, we could have
</p>
<p>
<div class="targetlang"><pre>
octave:1&gt; B=@() subclass(A(),@my_method);
octave:2&gt; function my_method(self)
octave:3&gt; self.A.my_method();
octave:4&gt; printf("octave-side routine called\n");
octave:5&gt; end
octave:6&gt; call_your_method(B());
c-side routine called
octave-side routine called
</pre></div>
</p>
<H3><a name="Octave_nn23"></a>22.4.1 Threads</H3>
<p>
The use of threads in wrapped Director code is not supported; i.e., an Octave-side implementation of a C++ class must be called from the Octave interpreter's thread. Anything fancier (apartment/queue model, whatever) is left to the user. Without anything fancier, this amounts to the limitation that Octave must drive the module... like, for example, an optimization package that calls Octave to evaluate an objective function.
</p>
<H3><a name="Octave_nn24"></a>22.4.3 Memory management</H3>
<p>
All Octave objects are referenced counted internally. SWIG-wrapped objects are no different. This means that destructors get called when the Octave object's reference count goes to zero.
</p>
<p>
For example,
<div class="code"><pre>
%inline {
class A {
public:
A() { printf("A constructing\n"); }
~A() { printf("A destructing\n"); }
};
}
</pre></div>
</p>
<p>
Would produce this behavior in Octave:
</p>
<p>
<div class="targetlang"><pre>
octave:1&gt; a=A();
A constructing
octave:2&gt; b=a;
octave:3&gt; clear a;
octave:4&gt; b=4;
A destructing
</pre></div>
</p>
<p>
In the case where one wishes for the C++ side to own an object that was created in Octave (especially a Director object), one can use the __disown() method to invert this logic. Then letting the Octave reference count go to zero will not destroy the object, but destroying the object will invalidate the Octave-side object if it still exists (and call destructors of other C++ bases in the case of multiple inheritance/<tt>subclass()</tt>'ing).
</p>
<H3><a name="Octave_nn25"></a>22.4.3 STL support</H3>
<p>
This is some skeleton support for various STL containers, but this work is not finished.
</p>
<H3><a name="Octave_nn26"></a>22.4.3 Matrix typemaps</H3>
<p>
Octave provides a rich set of classes for dealing with matrices etc. Currently there are no typemaps to deal with those, though such support will be added soon. However, these are relatively straight forward for users to add themselves (see the docs on typemaps). Without much work (a single typemap decl-- say, 5 lines of code in the interface file), it would be possible to have a function
</p>
<p>
<div class="code"><pre>
double my_det(const double* mat,int m,int n);
</div></pre>
</p>
<p>
that is accessed from Octave as,
</p>
<p>
<div class="targetlang"><pre>
octave:1&gt; my_det(rand(4));
ans = -0.18388
</div></pre>
</p>
<tt><br></tt>
</body>
</html>

View file

@ -273,6 +273,36 @@ python_clean:
rm -f core @EXTRA_CLEAN@
rm -f *.@OBJEXT@ *@SO@ *@PYTHON_SO@
##################################################################
##### OCTAVE ######
##################################################################
# Make sure these locate your Octave installation
OCTAVE_INCLUDE= $(DEFS) @OCTAVEEXT@
OCTAVE_LIB =
# Extra Octave specific dynamic linking options
OCTAVE_DLNK = @OCTAVEDYNAMICLINKING@
OCTAVE_SO = @OCTAVE_SO@
# -----------------------------------------------------------------
# Build a C++ dynamically loadable module
# -----------------------------------------------------------------
octave_cpp: $(SRCS)
$(SWIG) -c++ -octave $(SWIGOPT) $(INTERFACE)
$(CXX) -g -c $(CCSHARED) $(CFLAGS) $(ICXXSRCS) $(SRCS) $(CXXSRCS) $(INCLUDES) -I$(OCTAVE_INCLUDE)
$(CXXSHARED) -g $(CFLAGS) $(OBJS) $(IOBJS) $(OCTAVE_DLNK) $(LIBS) $(CPP_DLLIBS) -o $(LIBPREFIX)$(TARGET)$(OCTAVE_SO)
# -----------------------------------------------------------------
# Cleaning the octave examples
# -----------------------------------------------------------------
octave_clean:
rm -f *_wrap* *~ .~* myoctave@EXEEXT@ *.pyc
rm -f core @EXTRA_CLEAN@
rm -f *.@OBJEXT@ *@SO@ *@OCTAVE_SO@
##################################################################
##### GUILE ######
##################################################################

View file

@ -0,0 +1,21 @@
TOP = ../..
SWIG = $(TOP)/../preinst-swig
CXXSRCS = example.cxx
TARGET = example
INTERFACE = example.i
LIBS = -lm
SWIGOPT =
all::
$(MAKE) -f $(TOP)/Makefile $(SWIGLIB) CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \
SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' octave_cpp
static::
$(MAKE) -f $(TOP)/Makefile $(SWIGLIB) CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \
SWIGOPT='$(SWIGOPT)' TARGET='myoctave' INTERFACE='$(INTERFACE)' octave_cpp_static
clean::
$(MAKE) -f $(TOP)/Makefile octave_clean
rm -f $(TARGET).py
check: all

View file

@ -0,0 +1,4 @@
/* File : example.cxx */
#include "example.h"

View file

@ -0,0 +1,23 @@
/* File : example.h */
#include <cstdio>
#include <iostream>
class Callback {
public:
virtual ~Callback() { std::cout << "Callback::~Callback()" << std:: endl; }
virtual void run() { std::cout << "Callback::run()" << std::endl; }
};
class Caller {
private:
Callback *_callback;
public:
Caller(): _callback(0) {}
~Caller() { delCallback(); }
void delCallback() { delete _callback; _callback = 0; }
void setCallback(Callback *cb) { delCallback(); _callback = cb; }
void call() { if (_callback) _callback->run(); }
};

View file

@ -0,0 +1,13 @@
/* File : example.i */
%module(directors="1") example
%{
#include "example.h"
%}
%include "std_string.i"
/* turn on director wrapping Callback */
%feature("director") Callback;
%include "example.h"

View file

@ -0,0 +1,63 @@
# file: runme.m
# This file illustrates the cross language polymorphism using directors.
example
OctCallback=@() subclass(example.Callback(), \
'run',@(self) printf("OctCallback.run()\n"));
# Create an Caller instance
caller = example.Caller();
# Add a simple C++ callback (caller owns the callback, so
# we disown it first)
printf("Adding and calling a normal C++ callback\n");
printf("----------------------------------------\n");
callback = example.Callback().__disown();
caller.setCallback(callback);
caller.call();
caller.delCallback();
printf("Adding and calling a Octave callback\n");
printf("------------------------------------\n");
# Add a Octave callback (caller owns the callback, so we
# disown it first by calling __disown).
caller.setCallback(OctCallback().__disown())
caller.call();
caller.delCallback();
printf("Adding and calling another Octave callback\n");
printf("------------------------------------------\n");
# Let's do the same but use the weak reference this time.
callback = OctCallback().__disown();
caller.setCallback(callback);
caller.call();
caller.delCallback();
# careful-- using callback here may cause problems; octave_swig_type still
# exists, but is holding a destroyed object (the C++ example.Callback).
# to manually drop the octave-side reference, you can use
clear callback;
# Let's call them directly now
printf("Calling Octave and C++ callbacks directly\n");
printf("------------------------------------------\n");
a = OctCallback();
a.run();
a.Callback.run();
# All done.
printf("octave exit\n");

View file

@ -0,0 +1,16 @@
# see top-level Makefile.in
callback
class
constants
contract
enum
extend
funcptr
funcptr2
functor
operator
pointer
reference
simple
template
variables

View file

@ -0,0 +1,21 @@
TOP = ../..
SWIG = $(TOP)/../preinst-swig
CXXSRCS = example.cxx
TARGET = example
INTERFACE = example.i
LIBS = -lm
SWIGOPT =
all::
$(MAKE) -f $(TOP)/Makefile $(SWIGLIB) CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \
SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' octave_cpp
static::
$(MAKE) -f $(TOP)/Makefile $(SWIGLIB) CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \
SWIGOPT='$(SWIGOPT)' TARGET='myoctave' INTERFACE='$(INTERFACE)' octave_cpp_static
clean::
$(MAKE) -f $(TOP)/Makefile octave_clean
rm -f $(TARGET).py
check: all

View file

@ -0,0 +1,28 @@
/* File : example.c */
#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(void) {
return M_PI*radius*radius;
}
double Circle::perimeter(void) {
return 2*M_PI*radius;
}
double Square::area(void) {
return width*width;
}
double Square::perimeter(void) {
return 4*width;
}

View file

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

View file

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

View file

@ -0,0 +1,52 @@
# file: runme.m
# This file illustrates the shadow-class C++ interface generated
# by SWIG.
example
# ----- Object creation -----
printf("Creating some objects:\n");
c = example.Circle(10)
s = example.Square(10)
# ----- Access a static member -----
printf("\nA total of %i shapes were created\n", example.Shape.nshapes);
# ----- Member data access -----
# Set the location of the object
c.x = 20
c.y = 30
s.x = -10
s.y = 5
printf("\nHere is their current position:\n");
printf(" Circle = (%f, %f)\n",c.x,c.y);
printf(" Square = (%f, %f)\n",s.x,s.y);
# ----- Call some methods -----
printf("\nHere are some properties of the shapes:\n");
function print_shape(o)
o
printf(" area = %f\n", o.area());
printf(" perimeter = %f\n", o.perimeter());
end;
print_shape(c);
print_shape(s);
printf("\nGuess I'll clean up now\n");
# Note: this invokes the virtual destructor
clear c
clear s
printf("%i shapes remain\n", example.Shape.nshapes);
printf("Goodbye\n");

View file

@ -0,0 +1,21 @@
TOP = ../..
SWIG = $(TOP)/../preinst-swig
CXXSRCS =
TARGET = example
INTERFACE = example.i
LIBS = -lm
SWIGOPT =
all::
$(MAKE) -f $(TOP)/Makefile $(SWIGLIB) CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \
SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' octave_cpp
static::
$(MAKE) -f $(TOP)/Makefile $(SWIGLIB) CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \
SWIGOPT='$(SWIGOPT)' TARGET='myoctave' INTERFACE='$(INTERFACE)' octave_cpp_static
clean::
$(MAKE) -f $(TOP)/Makefile octave_clean
rm -f $(TARGET).py
check: all

View file

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

View file

@ -0,0 +1,29 @@
# file: runme.m
example
printf("ICONST = %i (should be 42)\n", example.ICONST);
printf("FCONST = %f (should be 2.1828)\n", example.FCONST);
printf("CCONST = %s (should be 'x')\n", example.CCONST);
printf("CCONST2 = %s (this should be on a new line)\n", example.CCONST2);
printf("SCONST = %s (should be 'Hello World')\n", example.SCONST);
printf("SCONST2 = %s (should be '\"Hello World\"')\n", example.SCONST2);
printf("EXPR = %f (should be 48.5484)\n", example.EXPR);
printf("iconst = %i (should be 37)\n", example.iconst);
printf("fconst = %f (should be 3.14)\n", example.fconst);
try
printf("EXTERN = %s (Arg! This shouldn't printf(anything)\n", example.EXTERN);
catch
printf("EXTERN isn't defined (good)\n");
end_try_catch
try
printf("FOO = %i (Arg! This shouldn't printf(anything)\n", example.FOO);
catch
printf("FOO isn't defined (good)\n");
end_try_catch

View file

@ -0,0 +1,21 @@
TOP = ../..
SWIG = $(TOP)/../preinst-swig
CXXSRCS = example.c
TARGET = example
INTERFACE = example.i
LIBS = -lm
SWIGOPT =
all::
$(MAKE) -f $(TOP)/Makefile $(SWIGLIB) CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \
SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' octave_cpp
static::
$(MAKE) -f $(TOP)/Makefile $(SWIGLIB) CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \
SWIGOPT='$(SWIGOPT)' TARGET='myoctave' INTERFACE='$(INTERFACE)' octave_cpp_static
clean::
$(MAKE) -f $(TOP)/Makefile octave_clean
rm -f $(TARGET).py
check: all

View file

@ -0,0 +1,23 @@
/* 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;
}
int fact(int n) {
if (n <= 0) return 1;
return n*fact(n-1);
}

View file

@ -0,0 +1,21 @@
/* File : example.i */
%module example
%contract gcd(int x, int y) {
require:
x >= 0;
y >= 0;
}
%contract fact(int n) {
require:
n >= 0;
ensure:
fact >= 1;
}
%inline %{
extern int gcd(int x, int y);
extern int fact(int n);
extern double Foo;
%}

View file

@ -0,0 +1,22 @@
# file: runme.m
example
# Call our gcd() function
x = 42;
y = 105;
g = example.gcd(x,y);
printf("The gcd of %d and %d is %d\n",x,y,g);
# Manipulate the Foo global variable
# Output its current value
printf("Foo = %f\n", example.cvar.Foo);
# Change its value
example.cvar.Foo = 3.1415926;
# See if the change took effect
printf("Foo = %f\n", example.cvar.Foo);

View file

@ -0,0 +1,21 @@
TOP = ../..
SWIG = $(TOP)/../preinst-swig
CXXSRCS = example.cxx
TARGET = example
INTERFACE = example.i
LIBS = -lm
SWIGOPT =
all::
$(MAKE) -f $(TOP)/Makefile $(SWIGLIB) CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \
SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' octave_cpp
static::
$(MAKE) -f $(TOP)/Makefile $(SWIGLIB) CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \
SWIGOPT='$(SWIGOPT)' TARGET='myoctave' INTERFACE='$(INTERFACE)' octave_cpp_static
clean::
$(MAKE) -f $(TOP)/Makefile octave_clean
rm -f $(TARGET).py
check: all

View file

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

View file

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

View file

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

View file

@ -0,0 +1,32 @@
# file: runme.m
example
# ----- Object creation -----
# Print out the value of some enums
printf("*** color ***\n");
printf(" RED = %i\n", example.RED);
printf(" BLUE = %i\n", example.BLUE);
printf(" GREEN = %i\n", example.GREEN);
printf("\n*** Foo::speed ***\n");
printf(" Foo_IMPULSE = %i\n", example.Foo_IMPULSE);
printf(" Foo_WARP = %i\n", example.Foo_WARP);
printf(" Foo_LUDICROUS = %i\n", example.Foo_LUDICROUS);
printf("\nTesting use of enums with functions\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)
printf("\nTesting use of enum with class method\n");
f = example.Foo();
f.enum_test(example.Foo_IMPULSE);
f.enum_test(example.Foo_WARP);
f.enum_test(example.Foo_LUDICROUS);

View file

@ -0,0 +1,21 @@
TOP = ../..
SWIG = $(TOP)/../preinst-swig
CXXSRCS = example.cxx
TARGET = example
INTERFACE = example.i
LIBS = -lm
SWIGOPT =
all::
$(MAKE) -f $(TOP)/Makefile $(SWIGLIB) CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \
SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' octave_cpp
static::
$(MAKE) -f $(TOP)/Makefile $(SWIGLIB) CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \
SWIGOPT='$(SWIGOPT)' TARGET='myoctave' INTERFACE='$(INTERFACE)' octave_cpp_static
clean::
$(MAKE) -f $(TOP)/Makefile octave_clean
rm -f $(TARGET).py
check: all

View file

@ -0,0 +1,4 @@
/* File : example.cxx */
#include "example.h"

View file

@ -0,0 +1,56 @@
/* File : example.h */
#include <cstdio>
#include <iostream>
#include <vector>
#include <string>
#include <cmath>
class Employee {
private:
std::string name;
public:
Employee(const char* n): name(n) {}
virtual std::string getTitle() { return getPosition() + " " + getName(); }
virtual std::string getName() { return name; }
virtual std::string getPosition() const { return "Employee"; }
virtual ~Employee() { printf("~Employee() @ %p\n", this); }
};
class Manager: public Employee {
public:
Manager(const char* n): Employee(n) {}
virtual std::string getPosition() const { return "Manager"; }
};
class EmployeeList {
std::vector<Employee*> list;
public:
EmployeeList() {
list.push_back(new Employee("Bob"));
list.push_back(new Employee("Jane"));
list.push_back(new Manager("Ted"));
}
void addEmployee(Employee *p) {
list.push_back(p);
std::cout << "New employee added. Current employees are:" << std::endl;
std::vector<Employee*>::iterator i;
for (i=list.begin(); i!=list.end(); i++) {
std::cout << " " << (*i)->getTitle() << std::endl;
}
}
const Employee *get_item(int i) {
return list[i];
}
~EmployeeList() {
std::vector<Employee*>::iterator i;
std::cout << "~EmployeeList, deleting " << list.size() << " employees." << std::endl;
for (i=list.begin(); i!=list.end(); i++) {
delete *i;
}
std::cout << "~EmployeeList empty." << std::endl;
}
};

View file

@ -0,0 +1,15 @@
/* File : example.i */
%module(directors="1") example
%{
#include "example.h"
%}
%include "std_vector.i"
%include "std_string.i"
/* turn on director wrapping for Manager */
%feature("director") Employee;
%feature("director") Manager;
%include "example.h"

View file

@ -0,0 +1,74 @@
# file: runme.m
# This file illustrates the cross language polymorphism using directors.
example
# CEO class, which overrides Employee::getPosition().
CEO=@(name) subclass(example.Manager(name),'getPosition',@(self) "CEO");
# Create an instance of our employee extension class, CEO. The calls to
# getName() and getPosition() are standard, the call to getTitle() uses
# the director wrappers to call CEO.getPosition. e = CEO("Alice")
e = CEO("Alice");
printf("%s is a %s\n",e.getName(),e.getPosition());
printf("Just call her \"%s\"\n",e.getTitle());
printf("----------------------\n");
# Create a new EmployeeList instance. This class does not have a C++
# director wrapper, but can be used freely with other classes that do.
list = example.EmployeeList();
# EmployeeList owns its items, so we must surrender ownership of objects
# we add. This involves first calling the __disown__ method to tell the
# C++ director to start reference counting. We reassign the resulting
# weakref.proxy to e so that no hard references remain. This can also be
# done when the object is constructed, as in: e =
# CEO("Alice").__disown()
e = e.__disown();
list.addEmployee(e);
printf("----------------------\n");
# Now we access the first four items in list (three are C++ objects that
# EmployeeList's constructor adds, the last is our CEO). The virtual
# methods of all these instances are treated the same. For items 0, 1, and
# 2, both all methods resolve in C++. For item 3, our CEO, getTitle calls
# getPosition which resolves in Octave. The call to getPosition is
# slightly different, however, from the e.getPosition() call above, since
# now the object reference has been "laundered" by passing through
# EmployeeList as an Employee*. Previously, Octave resolved the call
# immediately in CEO, but now Octave thinks the object is an instance of
# class Employee (actually EmployeePtr). So the call passes through the
# Employee shadow class and on to the C wrappers and C++ director,
# eventually ending up back at the CEO implementation of getPosition().
# The call to getTitle() for item 3 runs the C++ Employee::getTitle()
# method, which in turn calls getPosition(). This virtual method call
# passes down through the C++ director class to the Octave implementation
# in CEO. All this routing takes place transparently.
printf("(position, title) for items 0-3:\n");
for i=0:3,
printf(" %s, \"%s\"\n",list.get_item(i).getPosition(), list.get_item(i).getTitle());
endfor
printf("----------------------\n");
# Time to delete the EmployeeList, which will delete all the Employee*
# items it contains. The last item is our CEO, which gets destroyed as its
# reference count goes to zero. The Octave destructor runs, and is still
# able to call self.getName() since the underlying C++ object still
# exists. After this destructor runs the remaining C++ destructors run as
# usual to destroy the object.
clear list;
printf("----------------------\n");
# All done.
printf("octave exit\n");

View file

@ -0,0 +1,21 @@
TOP = ../..
SWIG = $(TOP)/../preinst-swig
CXXSRCS = example.c
TARGET = example
INTERFACE = example.i
LIBS = -lm
SWIGOPT =
all::
$(MAKE) -f $(TOP)/Makefile $(SWIGLIB) CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \
SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' octave_cpp
static::
$(MAKE) -f $(TOP)/Makefile $(SWIGLIB) CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \
SWIGOPT='$(SWIGOPT)' TARGET='myoctave' INTERFACE='$(INTERFACE)' octave_cpp_static
clean::
$(MAKE) -f $(TOP)/Makefile octave_clean
rm -f $(TARGET).py
check: all

View file

@ -0,0 +1,19 @@
/* File : example.c */
int do_op(int a, int b, int (*op)(int,int)) {
return (*op)(a,b);
}
int add(int a, int b) {
return a+b;
}
int sub(int a, int b) {
return a-b;
}
int mul(int a, int b) {
return a*b;
}
int (*funcvar)(int,int) = add;

View file

@ -0,0 +1,9 @@
/* file: example.h */
extern int do_op(int,int, int (*op)(int,int));
extern int add(int,int);
extern int sub(int,int);
extern int mul(int,int);
extern int (*funcvar)(int,int);

View file

@ -0,0 +1,16 @@
/* File : example.i */
%module example
%{
#include "example.h"
%}
/* Wrap a function taking a pointer to a function */
extern int do_op(int a, int b, int (*op)(int, int));
/* Now install a bunch of "ops" as constants */
%constant int (*ADD)(int,int) = add;
%constant int (*SUB)(int,int) = sub;
%constant int (*MUL)(int,int) = mul;
extern int (*funcvar)(int,int);

View file

@ -0,0 +1,21 @@
# file: runme.m
example
a = 37
b = 42
# Now call our C function with a bunch of callbacks
printf("Trying some C callback functions\n");
printf(" a = %i\n", a);
printf(" b = %i\n", b);
printf(" ADD(a,b) = %i\n", example.do_op(a,b,example.ADD));
printf(" SUB(a,b) = %i\n", example.do_op(a,b,example.SUB));
printf(" MUL(a,b) = %i\n", example.do_op(a,b,example.MUL));
printf("Here is what the C callback function objects look like in Octave\n");
example.ADD
example.SUB
example.MUL

View file

@ -0,0 +1,21 @@
TOP = ../..
SWIG = $(TOP)/../preinst-swig
CXXSRCS = example.c
TARGET = example
INTERFACE = example.i
LIBS = -lm
SWIGOPT =
all::
$(MAKE) -f $(TOP)/Makefile $(SWIGLIB) CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \
SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' octave_cpp
static::
$(MAKE) -f $(TOP)/Makefile $(SWIGLIB) CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \
SWIGOPT='$(SWIGOPT)' TARGET='myoctave' INTERFACE='$(INTERFACE)' octave_cpp_static
clean::
$(MAKE) -f $(TOP)/Makefile octave_clean
rm -f $(TARGET).py
check: all

View file

@ -0,0 +1,19 @@
/* File : example.c */
int do_op(int a, int b, int (*op)(int,int)) {
return (*op)(a,b);
}
int add(int a, int b) {
return a+b;
}
int sub(int a, int b) {
return a-b;
}
int mul(int a, int b) {
return a*b;
}
int (*funcvar)(int,int) = add;

View file

@ -0,0 +1,9 @@
/* file: example.h */
extern int do_op(int,int, int (*op)(int,int));
extern int add(int,int);
extern int sub(int,int);
extern int mul(int,int);
extern int (*funcvar)(int,int);

View file

@ -0,0 +1,18 @@
/* File : example.i */
%module example
%{
#include "example.h"
%}
/* Wrap a function taking a pointer to a function */
extern int do_op(int a, int b, int (*op)(int, int));
/* Now install a bunch of "ops" as constants */
%callback("%(upper)s");
int add(int, int);
int sub(int, int);
int mul(int, int);
%nocallback;
extern int (*funcvar)(int,int);

View file

@ -0,0 +1,24 @@
# file: runme.m
example
a = 37
b = 42
# Now call our C function with a bunch of callbacks
printf("Trying some C callback functions\n");
printf(" a = %i\n", a);
printf(" b = %i\n", b);
printf(" ADD(a,b) = %i\n", example.do_op(a,b,example.ADD));
printf(" SUB(a,b) = %i\n", example.do_op(a,b,example.SUB));
printf(" MUL(a,b) = %i\n", example.do_op(a,b,example.MUL));
printf("Here is what the C callback function objects look like in Octave\n");
example.ADD
example.SUB
example.MUL
printf("Call the functions directly...\n");
printf(" add(a,b) = %i\n", example.add(a,b));
printf(" sub(a,b) = %i\n", example.sub(a,b));

View file

@ -0,0 +1,21 @@
TOP = ../..
SWIG = $(TOP)/../preinst-swig
CXXSRCS =
TARGET = example
INTERFACE = example.i
LIBS = -lm
SWIGOPT =
all::
$(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \
SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' octave_cpp
static::
$(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \
TARGET='myoctave' INTERFACE='$(INTERFACE)' octave_cpp_static
clean::
$(MAKE) -f $(TOP)/Makefile octave_clean
rm -f $(TARGET).py
check: all

View file

@ -0,0 +1,29 @@
/* File : example.i */
%module example
%inline %{
// From B. Strousjoup, "The C++ Programming Language, Third Edition", p. 514
template<class T> class Sum {
T res;
public:
Sum(T i = 0) : res(i) { }
void operator() (T x) { res += x; }
T result() const { return res; }
};
%}
// Rename the application operator to __call__ for python.
// Note: this is normally automatic, but if you had to do it yourself
// you would use this directive:
//
// %rename(__call__) *::operator();
// Instantiate a few versions
%template(intSum) Sum<int>;
%template(doubleSum) Sum<double>;

View file

@ -0,0 +1,18 @@
# Operator overloading example
example
a = example.intSum(0);
b = example.doubleSum(100.0);
# Use the objects. They should be callable just like a normal
# python function.
for i=0:100-1,
a(i); # Note: function call
b(sqrt(i)); # Note: function call
endfor
a.result()
b.result()

View file

@ -0,0 +1,21 @@
TOP = ../..
SWIG = $(TOP)/../preinst-swig
CXXSRCS =
TARGET = example
INTERFACE = example.i
LIBS = -lm
SWIGOPT =
all::
$(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \
SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' octave_cpp
static::
$(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \
TARGET='myoctave' INTERFACE='$(INTERFACE)' octave_cpp_static
clean::
$(MAKE) -f $(TOP)/Makefile octave_clean
rm -f $(TARGET).m
check: all

View file

@ -0,0 +1,36 @@
/* File : example.h */
#include <math.h>
class ComplexVal {
private:
double rpart, ipart;
public:
ComplexVal(double r = 0, double i = 0) : rpart(r), ipart(i) { }
ComplexVal(const ComplexVal &c) : rpart(c.rpart), ipart(c.ipart) { }
ComplexVal &operator=(const ComplexVal &c) {
rpart = c.rpart;
ipart = c.ipart;
return *this;
}
ComplexVal operator+(const ComplexVal &c) const {
return ComplexVal(rpart+c.rpart, ipart+c.ipart);
}
ComplexVal operator-(const ComplexVal &c) const {
return ComplexVal(rpart-c.rpart, ipart-c.ipart);
}
ComplexVal operator*(const ComplexVal &c) const {
return ComplexVal(rpart*c.rpart - ipart*c.ipart,
rpart*c.ipart + c.rpart*ipart);
}
ComplexVal operator-() const {
return ComplexVal(-rpart, -ipart);
}
double re() const { return rpart; }
double im() const { return ipart; }
};

View file

@ -0,0 +1,24 @@
/* File : example.i */
%module example
#pragma SWIG nowarn=SWIGWARN_IGNORE_OPERATOR_EQ
%{
#include "example.h"
%}
/* Now grab the original header file */
%include "example.h"
/* An output method that turns a complex into a short string */
%extend ComplexVal {
char *__str() {
static char temp[512];
sprintf(temp,"(%g,%g)", $self->re(), $self->im());
return temp;
}
ComplexVal __paren(int j) {
return ComplexVal($self->re()*j,$self->im()*j);
}
};

View file

@ -0,0 +1,24 @@
# Operator overloading example
example
a = example.ComplexVal(2,3);
b = example.ComplexVal(-5,10);
printf("a = %s\n",a);
printf("b = %s\n",b);
c = a + b;
printf("c = %s\n",c);
printf("a*b = %s\n",a*b);
printf("a-c = %s\n",a-c);
e = example.ComplexVal(a-c);
printf("e = %s\n",e);
# Big expression
f = ((a+b)*(c+b*e)) + (-a);
printf("f = %s\n",f);
# paren overloading
printf("a(3)= %s\n",a(3));

View file

@ -0,0 +1,21 @@
TOP = ../..
SWIG = $(TOP)/../preinst-swig
CXXSRCS = example.c
TARGET = example
INTERFACE = example.i
LIBS = -lm
SWIGOPT =
all::
$(MAKE) -f $(TOP)/Makefile $(SWIGLIB) CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \
SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' octave_cpp
static::
$(MAKE) -f $(TOP)/Makefile $(SWIGLIB) CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \
SWIGOPT='$(SWIGOPT)' TARGET='myoctave' INTERFACE='$(INTERFACE)' octave_cpp_static
clean::
$(MAKE) -f $(TOP)/Makefile octave_clean
rm -f $(TARGET).py
check: all

View file

@ -0,0 +1,16 @@
/* File : example.c */
void add(int *x, int *y, int *result) {
*result = *x + *y;
}
void sub(int *x, int *y, int *result) {
*result = *x - *y;
}
int divide(int n, int d, int *r) {
int q;
q = n/d;
*r = n - q*d;
return q;
}

View file

@ -0,0 +1,30 @@
/* File : example.i */
%module example
%{
extern void add(int *, int *, int *);
extern void sub(int *, int *, int *);
extern int divide(int, int, int *);
%}
/* This example illustrates a couple of different techniques
for manipulating C pointers */
/* First we'll use the pointer library */
extern void add(int *x, int *y, int *result);
%include cpointer.i
%pointer_functions(int, intp);
/* Next we'll use some typemaps */
%include typemaps.i
extern void sub(int *INPUT, int *INPUT, int *OUTPUT);
/* Next we'll use typemaps and the %apply directive */
%apply int *OUTPUT { int *r };
extern int divide(int n, int d, int *r);

View file

@ -0,0 +1,42 @@
# file: runme.m
example;
# First create some objects using the pointer library.
printf("Testing the pointer library\n");
a = example.new_intp();
b = example.new_intp();
c = example.new_intp();
example.intp_assign(a,37);
example.intp_assign(b,42);
a,b,c
# Call the add() function with some pointers
example.add(a,b,c);
# Now get the result
r = example.intp_value(c);
printf(" 37 + 42 = %i\n",r);
# Clean up the pointers
example.delete_intp(a);
example.delete_intp(b);
example.delete_intp(c);
# Now try the typemap library
# This should be much easier. Now how it is no longer
# necessary to manufacture pointers.
printf("Trying the typemap library\n");
r = example.sub(37,42);
printf(" 37 - 42 = %i\n",r);
# Now try the version with multiple return values
printf("Testing multiple return values\n");
[q,r] = example.divide(42,37);
printf(" 42/37 = %d remainder %d\n",q,r);

View file

@ -0,0 +1,21 @@
TOP = ../..
SWIG = $(TOP)/../preinst-swig
CXXSRCS = example.cxx
TARGET = example
INTERFACE = example.i
LIBS = -lm
SWIGOPT =
all::
$(MAKE) -f $(TOP)/Makefile $(SWIGLIB) CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \
SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' octave_cpp
static::
$(MAKE) -f $(TOP)/Makefile $(SWIGLIB) CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \
SWIGOPT='$(SWIGOPT)' TARGET='myoctave' INTERFACE='$(INTERFACE)' octave_cpp_static
clean::
$(MAKE) -f $(TOP)/Makefile octave_clean
rm -f $(TARGET).py
check: all

View file

@ -0,0 +1,46 @@
/* 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)", this, x,y,z);
return temp;
}
VectorArray::VectorArray(int size) {
items = new Vector[size];
maxsize = size;
}
VectorArray::~VectorArray() {
delete [] items;
}
Vector &VectorArray::operator[](int index) {
if ((index < 0) || (index >= maxsize)) {
printf("Panic! Array index out of bounds.\n");
exit(1);
}
return items[index];
}
int VectorArray::size() {
return maxsize;
}

View file

@ -0,0 +1,26 @@
/* File : example.h */
class 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) { };
friend Vector operator+(const Vector &a, const Vector &b);
char *print();
};
class VectorArray {
private:
Vector *items;
int maxsize;
public:
VectorArray(int maxsize);
~VectorArray();
Vector &operator[](int);
int size();
};

View file

@ -0,0 +1,48 @@
/* File : example.i */
/* This file has a few "typical" uses of C++ references. */
%module example
%{
#include "example.h"
%}
%rename(cprint) print;
class Vector {
public:
Vector(double x, double y, double z);
~Vector();
char *print();
};
/* This helper function calls an overloaded operator */
%inline %{
Vector addv(Vector &a, Vector &b) {
return a+b;
}
%}
/* Wrapper around an array of vectors class */
class VectorArray {
public:
VectorArray(int maxsize);
~VectorArray();
int size();
/* This wrapper provides an alternative to the [] operator */
%extend {
Vector &get(int index) {
return (*$self)[index];
}
void set(int index, Vector &a) {
(*$self)[index] = a;
}
}
};

View file

@ -0,0 +1,63 @@
# file: runme.m
# This file illustrates the manipulation of C++ references in Octave
example
# ----- Object creation -----
printf("Creating some objects:\n");
a = example.Vector(3,4,5)
b = example.Vector(10,11,12)
printf(" Created %s\n",a.cprint());
printf(" Created %s\n",b.cprint());
# ----- Call an overloaded operator -----
# This calls the wrapper we placed around
#
# operator+(const Vector &a, const Vector &)
#
# It returns a new allocated object.
printf("Adding a+b\n");
c = example.addv(a,b);
printf(" a+b = %s\n", c.cprint());
clear c
# ----- Create a vector array -----
# Note: Using the high-level interface here
printf("Creating an array of vectors\n");
va = example.VectorArray(10)
# ----- Set some values in the array -----
# These operators copy the value of $a and $b to the vector array
va.set(0,a);
va.set(1,b);
va.set(2,example.addv(a,b))
# Get some values from the array
printf("Getting some array values\n");
for i=0:4,
printf(" va(%d) = %s\n",i,va.get(i).cprint());
end;
# Watch under resource meter to check on this
printf("Making sure we don't leak memory.\n");
for i=0:1000000-1,
c = va.get(mod(i,10));
end
# ----- Clean up -----
printf("Cleaning up\n");
clear va
clear a
clear b

View file

@ -0,0 +1,21 @@
TOP = ../..
SWIG = $(TOP)/../preinst-swig
CXXSRCS = example.c
TARGET = example
INTERFACE = example.i
LIBS = -lm
SWIGOPT =
all::
$(MAKE) -f $(TOP)/Makefile $(SWIGLIB) CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \
SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' octave_cpp
static::
$(MAKE) -f $(TOP)/Makefile $(SWIGLIB) CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \
SWIGOPT='$(SWIGOPT)' TARGET='myoctave' INTERFACE='$(INTERFACE)' octave_cpp_static
clean::
$(MAKE) -f $(TOP)/Makefile octave_clean
rm -f $(TARGET).py
check: all

View file

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

View file

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

View file

@ -0,0 +1,22 @@
# file: runme.m
example
# Call our gcd() function
x = 42
y = 105
g = example.gcd(x,y)
printf("The gcd of %d and %d is %d\n",x,y,g);
# Manipulate the Foo global variable
# Output its current value
example.cvar.Foo
# Change its value
example.cvar.Foo = 3.1415926
# See if the change took effect
printf("Foo = %f\n", example.cvar.Foo);

View file

@ -0,0 +1,21 @@
TOP = ../..
SWIG = $(TOP)/../preinst-swig
CXXSRCS =
TARGET = example
INTERFACE = example.i
LIBS = -lm
SWIGOPT =
all::
$(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \
SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' octave_cpp
static::
$(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \
SWIGOPT='$(SWIGOPT)' TARGET='myoctave' INTERFACE='$(INTERFACE)' octave_cpp_static
clean::
$(MAKE) -f $(TOP)/Makefile octave_clean
rm -f $(TARGET).py
check: all

View file

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

View file

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

View file

@ -0,0 +1,37 @@
# file: runme.m
example
# Call some templated functions
example.maxint(3,7)
example.maxdouble(3.14,2.18)
# Create some class
iv = example.vecint(100)
dv = example.vecdouble(1000)
for i=0:99,
iv.setitem(i,2*i);
end
for i=0:999,
dv.setitem(i, 1.0/(i+1));
end;
sum = 0;
for i=0:99
sum = sum + iv.getitem(i);
end
sum
sum = 0.0;
for i=0:999,
sum = sum + dv.getitem(i);
end
sum
clear iv
clear dv

View file

@ -0,0 +1,21 @@
TOP = ../..
SWIG = $(TOP)/../preinst-swig
CXXSRCS = example.c
TARGET = example
INTERFACE = example.i
LIBS = -lm
SWIGOPT =
all::
$(MAKE) -f $(TOP)/Makefile $(SWIGLIB) CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \
SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' octave_cpp
static::
$(MAKE) -f $(TOP)/Makefile $(SWIGLIB) CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \
SWIGOPT='$(SWIGOPT)' TARGET='myoctave' INTERFACE='$(INTERFACE)' octave_cpp_static
clean::
$(MAKE) -f $(TOP)/Makefile octave_clean
rm -f $(TARGET).m
check: all

View file

@ -0,0 +1,91 @@
/* File : example.c */
/* I'm a file containing some C global variables */
/* 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 <stdio.h>
#include <stdlib.h>
#include "example.h"
int ivar = 0;
short svar = 0;
long lvar = 0;
unsigned int uivar = 0;
unsigned short usvar = 0;
unsigned long ulvar = 0;
signed char scvar = 0;
unsigned char ucvar = 0;
char cvar = 0;
float fvar = 0;
double dvar = 0;
char *strvar = 0;
const char cstrvar[] = "Goodbye";
int *iptrvar = 0;
char name[256] = "Dave";
char path[256] = "/home/beazley";
/* Global variables involving a structure */
Point *ptptr = 0;
Point pt = { 10, 20 };
/* A variable that we will make read-only in the interface */
int status = 1;
/* A debugging function to print out their values */
void print_vars() {
printf("ivar = %d\n", ivar);
printf("svar = %d\n", svar);
printf("lvar = %ld\n", lvar);
printf("uivar = %u\n", uivar);
printf("usvar = %u\n", usvar);
printf("ulvar = %lu\n", ulvar);
printf("scvar = %d\n", scvar);
printf("ucvar = %u\n", ucvar);
printf("fvar = %g\n", fvar);
printf("dvar = %g\n", dvar);
printf("cvar = %c\n", cvar);
printf("strvar = %s\n", strvar ? strvar : "(null)");
printf("cstrvar = %s\n", cstrvar ? cstrvar : "(null)");
printf("iptrvar = %p\n", iptrvar);
printf("name = %s\n", name);
printf("ptptr = %p (%d, %d)\n", ptptr, ptptr ? ptptr->x : 0, ptptr ? ptptr->y : 0);
printf("pt = (%d, %d)\n", pt.x, pt.y);
printf("status = %d\n", status);
}
/* A function to create an integer (to test iptrvar) */
int *new_int(int value) {
int *ip = (int *) malloc(sizeof(int));
*ip = value;
return ip;
}
/* A function to create a point */
Point *new_Point(int x, int y) {
Point *p = (Point *) malloc(sizeof(Point));
p->x = x;
p->y = y;
return p;
}
char * Point_print(Point *p) {
static char buffer[256];
if (p) {
sprintf(buffer,"(%d,%d)", p->x,p->y);
} else {
sprintf(buffer,"null");
}
return buffer;
}
void pt_print() {
printf("(%d, %d)\n", pt.x, pt.y);
}

View file

@ -0,0 +1,6 @@
/* File: example.h */
typedef struct {
int x,y;
} Point;

View file

@ -0,0 +1,53 @@
/* File : example.i */
%module example
%{
#include "example.h"
%}
#pragma SWIG nowarn=SWIGWARN_TYPEMAP_SWIGTYPELEAK
/* Some global variable declarations */
%inline %{
extern "C" {
extern int ivar;
extern short svar;
extern long lvar;
extern unsigned int uivar;
extern unsigned short usvar;
extern unsigned long ulvar;
extern signed char scvar;
extern unsigned char ucvar;
extern char cvar;
extern float fvar;
extern double dvar;
extern char *strvar;
// extern const char cstrvar[];
extern int *iptrvar;
extern char name[256];
extern Point *ptptr;
extern Point pt;
}
%}
/* Some read-only variables */
%immutable;
%inline %{
extern int status;
extern char path[256];
%}
%mutable;
/* Some helper functions to make it easier to test */
%inline %{
extern void print_vars();
extern int *new_int(int value);
extern Point *new_Point(int x, int y);
extern char *Point_print(Point *p);
extern void pt_print();
%}

View file

@ -0,0 +1,75 @@
# file: runme.m
example
# Try to set the values of some global variables
example.cvar.ivar = 42;
example.cvar.svar = -31000;
example.cvar.lvar = 65537;
example.cvar.uivar = 123456;
example.cvar.usvar = 61000;
example.cvar.ulvar = 654321;
example.cvar.scvar = -13;
example.cvar.ucvar = 251;
example.cvar.cvar = "S";
example.cvar.fvar = 3.14159;
example.cvar.dvar = 2.1828;
example.cvar.strvar = "Hello World";
example.cvar.iptrvar= example.new_int(37);
example.cvar.ptptr = example.new_Point(37,42);
example.cvar.name = "Bill";
# Now print out the values of the variables
printf("Variables (values printed from Octave)\n");
printf("ivar = %i\n", example.cvar.ivar);
printf("svar = %i\n", example.cvar.svar);
printf("lvar = %i\n", example.cvar.lvar);
printf("uivar = %i\n", example.cvar.uivar);
printf("usvar = %i\n", example.cvar.usvar);
printf("ulvar = %i\n", example.cvar.ulvar);
printf("scvar = %i\n", example.cvar.scvar);
printf("ucvar = %i\n", example.cvar.ucvar);
printf("fvar = %i\n", example.cvar.fvar);
printf("dvar = %i\n", example.cvar.dvar);
printf("cvar = %s\n", example.cvar.cvar);
printf("strvar = %s\n", example.cvar.strvar);
#printf("cstrvar = %s\n", example.cvar.cstrvar);
example.cvar.iptrvar
printf("name = %i\n", example.cvar.name);
printf("ptptr = %s\n", example.Point_print(example.cvar.ptptr));
#printf("pt = %s\n", example.cvar.Point_print(example.cvar.pt));
printf("\nVariables (values printed from C)\n");
example.print_vars();
printf("\nNow I'm going to try and modify some read only variables\n");
printf(" Tring to set 'path'\n");
try
example.cvar.path = "Whoa!";
printf("Hey, what's going on?!?! This shouldn't work\n");
catch
printf("Good.\n");
end_try_catch
printf(" Trying to set 'status'\n");
try
example.cvar.status = 0;
printf("Hey, what's going on?!?! This shouldn't work\n");
catch
printf("Good.\n");
end_try_catch
printf("\nI'm going to try and update a structure variable.\n");
example.cvar.pt = example.cvar.ptptr;
printf("The new value is %s\n", example.Point_print(example.cvar.pt));

View file

@ -77,7 +77,7 @@ public:
SWIG_STD_VECTOR_SPECIALIZE_MINIMUM(Flow, Space::Flow)
#endif
#if defined(SWIGJAVA) || defined(SWIGCSHARP) || defined(SWIGPYTHON)||defined(SWIGR) || defined(SWIGRUBY)
#if defined(SWIGJAVA) || defined(SWIGCSHARP) || defined(SWIGPYTHON) || defined(SWIGR) || defined(SWIGOCTAVE) || defined(SWIGRUBY)
#define SWIG_GOOD_VECTOR
%ignore std::vector<Space::Flow>::vector(size_type);
%ignore std::vector<Space::Flow>::resize(size_type);

View file

@ -6,7 +6,7 @@
%module(ruby_minherit="1") minherit
#if defined(SWIGPYTHON) || defined(SWIGRUBY) || defined(SWIGOCAML)
#if defined(SWIGPYTHON) || defined(SWIGRUBY) || defined(SWIGOCAML) || defined(SWIGOCTAVE)
%inline %{

View file

@ -0,0 +1,82 @@
#######################################################################
# Makefile for octave test-suite
#######################################################################
LANGUAGE = octave
ifneq (,$(USE_VALGRIND))
OCTAVE = valgrind --leak-check=full --suppressions=pyswig.supp @OCTAVE@
else
OCTAVE = @OCTAVE@ -q
endif
SCRIPTSUFFIX = _runme.m
srcdir = @srcdir@
top_srcdir = @top_srcdir@
top_builddir = @top_builddir@
#CPP_TEST_CASES +=
#C_TEST_CASES +=
#
# This test only works with modern C compilers
#
#C_TEST_CASES += \
# complextest
include $(srcdir)/../common.mk
# Overridden variables here
LIBS = -L.
# Rules for the different types of tests
%.cpptest:
$(setup)
+$(swig_and_compile_cpp)
$(run_testcase)
%.ctest:
$(setup)
+$(swig_and_compile_cpp)
$(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.m appended after the testcase name.
run_testcase = \
if [ -f $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then ( \
env LD_LIBRARY_PATH=.:$$LD_LIBRARY_PATH OCTAVEPATH=$(srcdir):OCTAVEPATH $(OCTAVE) $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX);) \
fi;
# Clean: remove the generated .m file
%.clean:
@rm -f hugemod.h hugemod_a.i hugemod_b.i hugemod_a.m hugemod_b.m hugemod_runme.m
@rm -f $*.m;
clean:
$(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile octave_clean
cvsignore:
@echo '*wrap* *.mc *.so *.dll *.exp *.lib'
@echo Makefile
@for i in ${CPP_TEST_CASES} ${C_TEST_CASES}; do echo $$i.m; done
@for i in ${CPP_TEST_CASES} ${C_TEST_CASES}; do if grep -q $${i}_runme.m CVS/Entries ; then echo $${i}_runme.m; fi; done
@echo clientdata_prop_a.m
@echo clientdata_prop_b.m
@echo imports_a.m
@echo imports_b.m
@echo mod_a.m mod_b.m
@echo hugemod.h hugemod_a.i hugemod_b.i hugemod_a.m hugemod_b.m hugemod_runme.m
@echo template_typedef_import.m
hugemod:
perl hugemod.pl
$(MAKE) hugemod_a.cpptest
$(MAKE) hugemod_b.cpptest
time $(OCTAVE) hugemod_runme.m
time $(OCTAVE) hugemod_runme.m

View file

@ -0,0 +1,7 @@
abstract_access
d = abstract_access.D();
if (d.do_x() != 1)
error
endif

View file

@ -0,0 +1,8 @@
abstract_typedef2
a = A_UF();

View file

@ -0,0 +1,12 @@
abstract_typedef
e = Engine();
a = A();
if (a.write(e) != 1)
error
endif

View file

@ -0,0 +1,7 @@
abstract_virtual
d = D();
e = E();

View file

@ -0,0 +1,29 @@
argcargvtest
largs={'hi','hola','hello'};
if (mainc(largs) != 3)
error("bad main typemap");
endif
targs={'hi','hola'};
if (mainv(targs,1) != 'hola')
error("bad main typemap");
endif
targs={'hi', 'hola'};
if (mainv(targs,1) != 'hola')
error("bad main typemap");
endif
try
error_flag = 0;
mainv('hello',1);
error_flag = 1;
catch
end_try_catch
if (error_flag)
error("bad main typemap")
endif
initializeApp(largs);

View file

@ -0,0 +1,25 @@
array_member
f = Foo();
f.data = cvar.global_data;
for i=0:7,
if (get_value(f.data,i) != get_value(cvar.global_data,i))
error("Bad array assignment");
endif
endfor
for i=0:7,
set_value(f.data,i,-i);
endfor
cvar.global_data = f.data;
for i=0:7,
if (get_value(f.data,i) != get_value(cvar.global_data,i))
error("Bad array assignment")
endif
endfor

View file

@ -0,0 +1,18 @@
arrays_global
arrays_global.array_i = arrays_global.array_const_i;
BeginString_FIX44a;
BeginString_FIX44b;
BeginString_FIX44c;
BeginString_FIX44d;
BeginString_FIX44d;
BeginString_FIX44b ="12"'\0'"45";
BeginString_FIX44b;
BeginString_FIX44d;
BeginString_FIX44e;
BeginString_FIX44f;
test_a("hello","hi","chello","chi");
test_b("1234567","hi");

View file

@ -0,0 +1,40 @@
_callback
callback
if (foo(2) != 2)
error
endif
if (A_bar(2) != 4)
error
endif
if (foobar(3, _callback.foo) != foo(3))
error
endif
if (foobar(3, foo) != foo(3))
error
endif
if (foobar(3, A_bar) != A_bar(3))
error
endif
if (foobar(3, foof) != foof(3))
error
endif
if (foobar_i(3, foo_i) != foo_i(3))
error
endif
if (foobar_d(3.5, foo_d) != foo_d(3.5))
error
endif
a = A();
if (foobarm(3, a, A.foom_cb_ptr) != a.foom(3))
error
endif

View file

@ -0,0 +1,7 @@
class_ignore
a = class_ignore.Bar();
if (!strcmp(class_ignore.do_blah(a),"Bar::blah"))
error
endif

View file

@ -0,0 +1,7 @@
class_scope_weird
f = class_scope_weird.Foo();
g = class_scope_weird.Foo(3);
if (f.bar(3) != 3)
error
endif

View file

@ -0,0 +1,24 @@
compactdefaultargs
defaults1 = Defaults1(1000);
defaults1 = Defaults1();
if (defaults1.ret(10.0) != 10.0)
error
endif
if (defaults1.ret() != -1.0)
error
endif
defaults2 = Defaults2(1000);
defaults2 = Defaults2();
if (defaults2.ret(10.0) != 10.0)
error
endif
if (defaults2.ret() != -1.0)
error
endif

View file

@ -0,0 +1,19 @@
complextest
a = complex(-1,2);
if (complextest.Conj(a) != a.conjugate())
error("bad complex mapping")
endif
if (complextest.Conjf(a) != a.conjugate())
error("bad complex mapping")
endif
v = (complex(1,2), complex(2,3), complex(4,3), 1);
try
complextest.Copy_h(v);
catch
end_try_catch

View file

@ -0,0 +1,34 @@
constover
p = constover.test("test");
if (!strcmp(p,"test"))
error("test failed!")
endif
p = constover.test_pconst("test")
if (!strcmp(p,"test_pconst"))
error("test_pconst failed!")
endif
f = constover.Foo()
p = f.test("test")
if (!strcmp(p,"test"))
error("member-test failed!")
endif
p = f.test_pconst("test")
if (!strcmp(p,"test_pconst"))
error("member-test_pconst failed!")
endif
p = f.test_constm("test")
if (!strcmp(p,"test_constmethod"))
error("member-test_constm failed!")
endif
p = f.test_pconstm("test")
if (!strcmp(p,"test_pconstmethod"))
error("member-test_pconstm failed!")
endif

View file

@ -0,0 +1,44 @@
constructor_copy
f1 = Foo1(3);
f11 = Foo1(f1);
if (f1.x != f11.x)
error
endif
f8 = Foo8();
try
f81 = Foo8(f8);
good = 0;
catch
good = 1;
end_try_catch
if (!good)
error
endif
bi = Bari(5);
bc = Bari(bi);
if (bi.x != bc.x)
error
endif
bd = Bard(5);
try
bc = Bard(bd);
good = 0;
catch
good = 1;
end_try_catch
if (!good)
error
endif

View file

@ -0,0 +1,135 @@
contract
contract.test_preassert(1,2);
try
contract.test_preassert(-1,0)
error("Failed! Preassertions are broken")
catch
end_try_catch
contract.test_postassert(3);
try
contract.test_postassert(-3);
error("Failed! Postassertions are broken")
catch
end_try_catch
contract.test_prepost(2,3);
contract.test_prepost(5,-4);
try
contract.test_prepost(-3,4);
error("Failed! Preassertions are broken")
catch
end_try_catch
try
contract.test_prepost(4,-10);
error("Failed! Postassertions are broken")
catch
end_try_catch
f = contract.Foo();
f.test_preassert(4,5);
try
f.test_preassert(-2,3);
error("Failed! Method preassertion.")
catch
end_try_catch
f.test_postassert(4);
try
f.test_postassert(-4);
error("Failed! Method postassertion")
catch
end_try_catch
f.test_prepost(3,4);
f.test_prepost(4,-3);
try
f.test_prepost(-4,2);
error("Failed! Method preassertion.")
catch
end_try_catch
try
f.test_prepost(4,-10);
error("Failed! Method postassertion.")
catch
end_try_catch
contract.Foo_stest_prepost(4,0);
try
contract.Foo_stest_prepost(-4,2);
error("Failed! Static method preassertion")
catch
end_try_catch
try
contract.Foo_stest_prepost(4,-10);
error("Failed! Static method posteassertion")
catch
end_try_catch
b = contract.Bar();
try
b.test_prepost(2,-4);
error("Failed! Inherited preassertion.")
catch
end_try_catch
d = contract.D();
try
d.foo(-1,1,1,1,1);
error("Failed! Inherited preassertion (D).")
catch
end_try_catch
try
d.foo(1,-1,1,1,1);
error("Failed! Inherited preassertion (D).")
catch
end_try_catch
try
d.foo(1,1,-1,1,1);
error("Failed! Inherited preassertion (D).")
catch
end_try_catch
try
d.foo(1,1,1,-1,1);
error("Failed! Inherited preassertion (D).")
catch
end_try_catch
try
d.foo(1,1,1,1,-1);
error("Failed! Inherited preassertion (D).")
catch
end_try_catch
try
d.bar(-1,1,1,1,1);
error("Failed! Inherited preassertion (D).")
catch
end_try_catch
try
d.bar(1,-1,1,1,1);
error("Failed! Inherited preassertion (D).")
catch
end_try_catch
try
d.bar(1,1,-1,1,1);
error("Failed! Inherited preassertion (D).")
catch
end_try_catch
try
d.bar(1,1,1,-1,1);
error("Failed! Inherited preassertion (D).")
catch
end_try_catch
try
d.bar(1,1,1,1,-1);
error("Failed! Inherited preassertion (D).")
catch
end_try_catch

View file

@ -0,0 +1,27 @@
cpp_enum
f = cpp_enum.Foo();
if (f.hola != cpp_enum.Foo_Hello)
error(f.hola);
error;
endif
f.hola = cpp_enum.Foo_Hi;
if (f.hola != cpp_enum.Foo_Hi)
error(f.hola);
error;
endif
f.hola = cpp_enum.Foo_Hello;
if (f.hola != cpp_enum.Foo_Hello)
error(f.hola);
error;
endif
cpp_enum.hi = cpp_enum.Hello;
if (cpp_enum.hi != cpp_enum.Hello)
error(cpp_enum.hi);
error;
endif

View file

@ -0,0 +1,55 @@
# Note: This example assumes that namespaces are flattened
cpp_namespace
n = cpp_namespace.fact(4);
if (n != 24)
error("Bad return value!")
endif
if (cpp_namespace.cvar.Foo != 42)
error("Bad variable value!")
endif
t = cpp_namespace.Test();
if (!strcmp(t.method(),"Test::method"))
error("Bad method return value!")
endif
if (!strcmp(cpp_namespace.do_method(t),"Test::method"))
error("Bad return value!")
endif
if (!strcmp(cpp_namespace.do_method2(t),"Test::method"))
error("Bad return value!")
endif
cpp_namespace.weird("hello", 4);
clear t;
t2 = cpp_namespace.Test2();
t3 = cpp_namespace.Test3();
t4 = cpp_namespace.Test4();
t5 = cpp_namespace.Test5();
if (cpp_namespace.foo3(42) != 42)
error("Bad return value!")
endif
if (!strcmp(cpp_namespace.do_method3(t2,40),"Test2::method"))
error("Bad return value!")
endif
if (!strcmp(cpp_namespace.do_method3(t3,40),"Test3::method"))
error("Bad return value!")
endif
if (!strcmp(cpp_namespace.do_method3(t4,40),"Test4::method"))
error("Bad return value!")
endif
if (!strcmp(cpp_namespace.do_method3(t5,40),"Test5::method"))
error("Bad return value!")
endif

View file

@ -0,0 +1,86 @@
default_args
if (default_args.Statics.staticmethod() != 60)
error
endif
if (default_args.cfunc1(1) != 2)
error
endif
if (default_args.cfunc2(1) != 3)
error
endif
if (default_args.cfunc3(1) != 4)
error
endif
f = default_args.Foo();
f.newname();
f.newname(1);
try
f = default_args.Foo(1);
ok = 1;
catch
ok = 0;
end_try_catch
if (ok)
error("Foo::Foo ignore is not working")
endif
try
f = default_args.Foo(1,2);
ok = 1;
catch
ok = 0;
end_try_catch
if (ok)
error("Foo::Foo ignore is not working")
endif
try
f = default_args.Foo(1,2,3);
ok = 1;
catch
ok = 0;
end_try_catch
if (ok)
error("Foo::Foo ignore is not working")
endif
try
m = f.meth(1);
ok = 1;
catch
ok = 0;
end_try_catch
if (ok)
error("Foo::meth ignore is not working")
endif
try
m = f.meth(1,2);
ok = 1;
catch
ok = 0;
end_try_catch
if (ok)
error("Foo::meth ignore is not working")
endif
try
m = f.meth(1,2,3);
ok = 1;
catch
ok = 0;
end_try_catch
if (ok)
error("Foo::meth ignore is not working")
endif

View file

@ -0,0 +1,111 @@
default_constructor
dc = default_constructor;
a = dc.new_A();
dc.delete_A(a);
aa = dc.new_AA();
dc.delete_AA(aa);
try
b = dc.new_B();
error("Whoa. new_BB created.")
catch
end_try_catch
del_b = dc.delete_B;
try
bb = dc.new_BB();
error("Whoa. new_BB created.")
catch
end_try_catch
del_bb = dc.delete_BB;
try
c = dc.new_C();
error("Whoa. new_C created.")
catch
end_try_catch
del_c = dc.delete_C;
cc = dc.new_CC();
dc.delete_CC(cc);
try
d = dc.new_D();
error("Whoa. new_D created")
catch
end_try_catch
del_d = dc.delete_D;
try
dd = dc.new_DD();
error("Whoa. new_DD created")
catch
end_try_catch
dd = dc.delete_DD;
try
ad = dc.new_AD();
error("Whoa. new_AD created")
catch
end_try_catch
del_ad = dc.delete_AD;
e = dc.new_E();
dc.delete_E(e);
ee = dc.new_EE();
dc.delete_EE(ee);
try
eb = dc.new_EB();
error("Whoa. new_EB created")
catch
end_try_catch
del_eb = dc.delete_EB;
f = dc.new_F();
try
del_f = dc.delete_F;
error("Whoa. delete_F created")
catch
end_try_catch
dc.F_destroy(f);
ff = dc.new_FFF();
try
del_ff = dc.delete_FFF;
error("Whoa. delete_FFF created")
catch
end_try_catch
dc.F_destroy(ff);
g = dc.new_G();
try
del_g = dc.delete_G;
error("Whoa. delete_G created")
catch
end_try_catch
dc.G_destroy(g);
gg = dc.new_GG();
dc.delete_GG(gg);
hh = default_constructor.HH(1,1);

View file

@ -0,0 +1,44 @@
director_abstract
MyFoo=@() subclass(director_abstract.Foo(),@ping);
function out=ping(self)
out="MyFoo::ping()";
end
a = MyFoo();
if (!strcmp(a.ping(),"MyFoo::ping()"))
error(a.ping())
endif
if (!strcmp(a.pong(),"Foo::pong();MyFoo::ping()"))
error(a.pong())
endif
MyExample1=@() subclass(director_abstract.Example1(),'Color',@(self,r,g,b) r);
MyExample2=@(a,b) subclass(director_abstract.Example2(a,b),'Color',@(self,r,g,b) g);
MyExample3=@() subclass(director_abstract.Example3_i(),'Color',@(self,r,g,b) b);
me1 = MyExample1();
if (director_abstract.Example1.get_color(me1, 1,2,3) != 1)
error
endif
me2 = MyExample2(1,2);
if (me2.get_color(me2, 1,2,3) != 2)
error
endif
me3 = MyExample3();
if (me3.get_color(me3, 1,2,3) != 3)
error
endif
# don't check that we cannot construct abstract bases, since we have no
# way of disambiguating that with the normal construction case using
# subclass. furthermore, calling a pure virtual method will still generate
# an error.

View file

@ -0,0 +1,110 @@
director_basic
function self=OctFoo()
global director_basic;
self=subclass(director_basic.Foo());
self.ping=@OctFoo_ping;
end
function string=OctFoo_ping(self)
string="OctFoo::ping()";
end
a = OctFoo();
if (!strcmp(a.ping(),"OctFoo::ping()"))
error(a.ping())
endif
if (!strcmp(a.pong(),"Foo::pong();OctFoo::ping()"))
error(a.pong())
endif
b = director_basic.Foo();
if (!strcmp(b.ping(),"Foo::ping()"))
error(b.ping())
endif
if (!strcmp(b.pong(),"Foo::pong();Foo::ping()"))
error(b.pong())
endif
a = director_basic.A1(1);
if (a.rg(2) != 2)
error
endif
function self=OctClass()
global director_basic;
self=subclass(director_basic.MyClass());
self.method=@OctClass_method;
self.vmethod=@OctClass_vmethod;
end
function OctClass_method(self,vptr)
self.cmethod = 7;
end
function out=OctClass_vmethod(self,b)
b.x = b.x + 31;
out=b;
end
b = director_basic.Bar(3);
d = director_basic.MyClass();
c = OctClass();
cc = director_basic.MyClass_get_self(c);
dd = director_basic.MyClass_get_self(d);
bc = cc.cmethod(b);
bd = dd.cmethod(b);
cc.method(b);
if (c.cmethod != 7)
error
endif
if (bc.x != 34)
error
endif
if (bd.x != 16)
error
endif
function self=OctMulti()
global director_basic;
self=subclass(director_basic.Foo(),director_basic.MyClass());
self.vmethod=@OctMulti_vmethod;
self.ping=@OctMulti_ping;
end
function out=OctMulti_vmethod(self,b)
b.x = b.x + 31;
out=b;
end
function out=OctMulti_ping(self)
out="OctFoo::ping()";
end
a = 0;
for i=0:100,
octmult = OctMulti();
octmult.pong();
clear octmult
endfor
octmult = OctMulti();
p1 = director_basic.Foo_get_self(octmult);
p2 = director_basic.MyClass_get_self(octmult);
p1.ping();
p2.vmethod(bc);

View file

@ -0,0 +1,98 @@
director_classic
TargetLangPerson=@() subclass(Person(),'id',@(self) "TargetLangPerson");
TargetLangChild=@() subclass(Child(),'id',@(self) "TargetLangChild");
TargetLangGrandChild=@() subclass(GrandChild(),'id',@(self) "TargetLangGrandChild");
# Semis - don't override id() in target language
TargetLangSemiPerson=@() subclass(Person());
TargetLangSemiChild=@() subclass(Child());
TargetLangSemiGrandChild=@() subclass(GrandChild());
# Orphans - don't override id() in C++
TargetLangOrphanPerson=@() subclass(OrphanPerson(),'id',@(self) "TargetLangOrphanPerson");
TargetLangOrphanChild=@() subclass(OrphanChild(),'id',@(self) "TargetLangOrphanChild");
function check(person,expected)
global Caller;
# Normal target language polymorphic call
ret = person.id();
if (ret != expected)
raise ("Failed. Received: " + ret + " Expected: " + expected);
endif
# Polymorphic call from C++
caller = Caller();
caller.setCallback(person);
ret = caller.call();
if (ret != expected)
error ("Failed. Received: " + ret + " Expected: " + expected);
endif
# Polymorphic call of object created in target language and passed to C++ and back again
baseclass = caller.baseClass();
ret = baseclass.id();
if (ret != expected)
error ("Failed. Received: " + ret + " Expected: " + expected);
endif
caller.resetCallback();
end
person = Person();
check(person, "Person");
clear person;
person = Child();
check(person, "Child");
clear person;
person = GrandChild();
check(person, "GrandChild");
clear person;
person = TargetLangPerson();
check(person, "TargetLangPerson");
clear person;
person = TargetLangChild();
check(person, "TargetLangChild");
clear person;
person = TargetLangGrandChild();
check(person, "TargetLangGrandChild");
clear person;
# Semis - don't override id() in target language
person = TargetLangSemiPerson();
check(person, "Person");
clear person;
person = TargetLangSemiChild();
check(person, "Child");
clear person;
person = TargetLangSemiGrandChild();
check(person, "GrandChild");
clear person;
# Orphans - don't override id() in C++
person = OrphanPerson();
check(person, "Person");
clear person;
person = OrphanChild();
check(person, "Child");
clear person;
person = TargetLangOrphanPerson();
check(person, "TargetLangOrphanPerson");
clear person;
person = TargetLangOrphanChild();
check(person, "TargetLangOrphanChild");
clear person;

View file

@ -0,0 +1,10 @@
director_default
f = Foo();
f = Foo(1);
f = Bar();
f = Bar(1);

View file

@ -0,0 +1,36 @@
director_detect
global MyBar=@(val=2) \
subclass(director_detect.Bar(),'val',val,@get_value,@get_class,@just_do_it,@clone);
function val=get_value(self)
self.val = self.val + 1;
val = self.val;
end
function ptr=get_class(self)
global director_detect;
self.val = self.val + 1;
ptr=director_detect.A();
end
function just_do_it(self)
self.val = self.val + 1;
end
function ptr=clone(self)
global MyBar;
ptr=MyBar(self.val);
end
b = MyBar();
f = b.baseclass();
v = f.get_value();
a = f.get_class();
f.just_do_it();
c = b.clone();
vc = c.get_value();
if ((v != 3) || (b.val != 5) || (vc != 6))
error("Bad virtual detection")
endif

View file

@ -0,0 +1,10 @@
director_enum
MyFoo=@() subclass(director_enum.Foo(),'say_hi',@(self,val) val);
b = director_enum.Foo();
a = MyFoo();
if (a.say_hi(director_enum.hello) != b.say_hello(director_enum.hi))
error
endif

View file

@ -0,0 +1,57 @@
director_exception
MyFoo=@() subclass(Foo(),
'ping',@(self) raise(NotImplementedError("MyFoo::ping() EXCEPTION")));
MyFoo2=@() subclass(Foo(),
'ping',@(self) true);
ok = 0;
a = MyFoo();
b = launder(a);
try
b.pong();
catch
[etype,e]=raised();
if (etype=="NotImplementedError")
ok=1;
endif
end_try_catch
if (!ok)
error
endif
ok = 0;
a = MyFoo2();
b = launder(a);
try
b.pong();
catch
ok = 1;
end_try_catch
if (!ok)
error
endif
try
raise(Exception2());
catch
if (!strcmp(raised,"Exception2"))
rethrow(lasterr);
endif
end_try_catch
try
raise(Exception1());
catch
if (!strcmp(raised,"Exception1"))
rethrow(lasterr);
endif
end_try_catch

View file

@ -0,0 +1,12 @@
director_extend
MyObject=@() subclass(SpObject(),'getFoo',@(self) 123);
m = MyObject();
if (m.dummy() != 666)
error("1st call")
endif
if (m.dummy() != 666)
error("2nd call")
endif

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