diff options
Diffstat (limited to 'Examples/perl5/reference')
| -rw-r--r-- | Examples/perl5/reference/Makefile | 20 | ||||
| -rw-r--r-- | Examples/perl5/reference/example.cxx | 46 | ||||
| -rw-r--r-- | Examples/perl5/reference/example.h | 26 | ||||
| -rw-r--r-- | Examples/perl5/reference/example.i | 46 | ||||
| -rw-r--r-- | Examples/perl5/reference/index.html | 146 | ||||
| -rw-r--r-- | Examples/perl5/reference/runme.pl | 74 |
6 files changed, 358 insertions, 0 deletions
diff --git a/Examples/perl5/reference/Makefile b/Examples/perl5/reference/Makefile new file mode 100644 index 0000000..4a80425 --- /dev/null +++ b/Examples/perl5/reference/Makefile @@ -0,0 +1,20 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +CXXSRCS = example.cxx +TARGET = example +INTERFACE = example.i +LIBS = -lm +SWIGOPT = -noproxy + +all:: + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' SWIGOPT='$(SWIGOPT)' perl5_cpp + +static:: + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + TARGET='myperl' INTERFACE='$(INTERFACE)' SWIGOPT='$(SWIGOPT)' perl5_cpp_static + +clean:: + $(MAKE) -f $(TOP)/Makefile perl5_clean + +check: all diff --git a/Examples/perl5/reference/example.cxx b/Examples/perl5/reference/example.cxx new file mode 100644 index 0000000..8a513bf --- /dev/null +++ b/Examples/perl5/reference/example.cxx @@ -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; +} + diff --git a/Examples/perl5/reference/example.h b/Examples/perl5/reference/example.h new file mode 100644 index 0000000..4915adb --- /dev/null +++ b/Examples/perl5/reference/example.h @@ -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(); +}; + + + + diff --git a/Examples/perl5/reference/example.i b/Examples/perl5/reference/example.i new file mode 100644 index 0000000..6daa3b1 --- /dev/null +++ b/Examples/perl5/reference/example.i @@ -0,0 +1,46 @@ +/* File : example.i */ + +/* This file has a few "typical" uses of C++ references. */ + +%module example + +%{ +#include "example.h" +%} + +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; + } + } +}; + + + + diff --git a/Examples/perl5/reference/index.html b/Examples/perl5/reference/index.html new file mode 100644 index 0000000..70b4f3d --- /dev/null +++ b/Examples/perl5/reference/index.html @@ -0,0 +1,146 @@ +<html> +<head> +<title>SWIG:Examples:perl5:reference</title> +</head> + +<body bgcolor="#ffffff"> + + +<tt>SWIG/Examples/perl5/reference/</tt> +<hr> + +<H2>C++ Reference Handling</H2> + +<p> +This example tests SWIG's handling of C++ references. Since C++ +references are closely related to pointers (as both refer to a +location in memory), SWIG simply collapses all references into +pointers when creating wrappers. + +<h2>Some examples</h2> + +References are most commonly used as function parameter. For example, +you might have an operator like this: + +<blockquote> +<pre> +Vector operator+(const Vector &a, const Vector &b) { + Vector result; + result.x = a.x + b.x; + result.y = a.y + b.y; + result.z = a.z + b.z; + return result; +} +</pre> +</blockquote> + +or a function: + +<blockquote> +<pre> +Vector addv(const Vector &a, const Vector &b) { + Vector result; + result.x = a.x + b.x; + result.y = a.y + b.y; + result.z = a.z + b.z; + return result; +} +</pre> +</blockquote> + +In these cases, SWIG transforms everything into a pointer and creates a wrapper +that looks like this: + +<blockquote> +<pre> +Vector wrap_addv(Vector *a, Vector *b) { + return addv(*a,*b); +} +</pre> +</blockquote> + +Occasionally, a reference is used as a return value of a function +when the return result is to be used as an lvalue in an expression. +The prototypical example is an operator like this: + +<blockquote> +<pre> +Vector &operator[](int index); +</pre> +</blockquote> + +or a method: + +<blockquote> +<pre> +Vector &get(int index); +</pre> +</blockquote> + +For functions returning references, a wrapper like this is created: + +<blockquote> +<pre> +Vector *wrap_Object_get(Object *self, int index) { + Vector &result = self->get(index); + return &result; +} +</pre> +</blockquote> + +The following <a href="example.h">header file</a> contains some class +definitions with some operators and use of references. + +<h2>SWIG Interface</h2> + +SWIG does NOT support overloaded operators so it can not directly build +an interface to the classes in the above file. However, a number of workarounds +can be made. For example, an overloaded operator can be stuck behind a function +call such as the <tt>addv()</tt> function above. Array access can be handled +with a pair of set/get functions like this: + +<blockquote> +<pre> +class VectorArray { +public: + ... + %addmethods { + Vector &get(int index) { + return (*self)[index]; + } + void set(int index, Vector &a) { + (*self)[index] = a; + } + } + ... +} +</pre> +</blockquote> + +Click <a href="example.i">here</a> to see a SWIG interface file with these additions. + +<h2>Sample Perl script</h2> + +Click <a href="runme.pl">here</a> to see a script that manipulates some C++ references. + +<h2>Notes:</h2> + +<ul> +<li>C++ references primarily provide notational convenience for C++ +source code. However, it doesn't much matter to Perl. + +<p> +<li>When a program returns a reference, a pointer is returned. +Unlike return by value, memory is not allocated to hold the +return result. + +<p> +<li>SWIG has particular trouble handling various combinations of references +and pointers. This is side effect of an old parsing scheme and +type representation that will be replaced in future versions. + +</ul> + +<hr> +</body> +</html> diff --git a/Examples/perl5/reference/runme.pl b/Examples/perl5/reference/runme.pl new file mode 100644 index 0000000..41dc0b8 --- /dev/null +++ b/Examples/perl5/reference/runme.pl @@ -0,0 +1,74 @@ +# file: runme.pl + +# This file illustrates the manipulation of C++ references in Perl. +# This uses the low-level interface. Proxy classes work differently. + +use example; + +# ----- Object creation ----- + +print "Creating some objects:\n"; +$a = example::new_Vector(3,4,5); +$b = example::new_Vector(10,11,12); + +print " Created",example::Vector_print($a),"\n"; +print " Created",example::Vector_print($b),"\n"; + +# ----- Call an overloaded operator ----- + +# This calls the wrapper we placed around +# +# operator+(const Vector &a, const Vector &) +# +# It returns a new allocated object. + +print "Adding a+b\n"; +$c = example::addv($a,$b); +print " a+b =", example::Vector_print($c),"\n"; + +# Note: Unless we free the result, a memory leak will occur +example::delete_Vector($c); + +# ----- Create a vector array ----- + +# Note: Using the high-level interface here +print "Creating an array of vectors\n"; +$va = example::new_VectorArray(10); +print " va = $va\n"; + +# ----- Set some values in the array ----- + +# These operators copy the value of $a and $b to the vector array +example::VectorArray_set($va,0,$a); +example::VectorArray_set($va,1,$b); + +# This will work, but it will cause a memory leak! + +example::VectorArray_set($va,2,example::addv($a,$b)); + +# The non-leaky way to do it + +$c = example::addv($a,$b); +example::VectorArray_set($va,3,$c); +example::delete_Vector($c); + +# Get some values from the array + +print "Getting some array values\n"; +for ($i = 0; $i < 5; $i++) { + print " va($i) = ", example::Vector_print(example::VectorArray_get($va,$i)), "\n"; +} + +# Watch under resource meter to check on this +print "Making sure we don't leak memory.\n"; +for ($i = 0; $i < 1000000; $i++) { + $c = example::VectorArray_get($va,$i % 10); +} + +# ----- Clean up ----- +print "Cleaning up\n"; + +example::delete_VectorArray($va); +example::delete_Vector($a); +example::delete_Vector($b); + |
