diff options
author | Dave Beazley <dave-swig@dabeaz.com> | 2000-08-31 21:21:15 +0000 |
---|---|---|
committer | Dave Beazley <dave-swig@dabeaz.com> | 2000-08-31 21:21:15 +0000 |
commit | 53bf5fb4658b93ca4659cf11eeda04ce7383c8a9 (patch) | |
tree | b615fed7142a38c119e859a85a9e0819aa1b0595 /Examples/python | |
parent | cb4255a08696cb07e2f24ef6bc61b1d8159aa461 (diff) | |
download | swig-53bf5fb4658b93ca4659cf11eeda04ce7383c8a9.tar.gz |
New example
git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk/SWIG@775 626c5289-ae23-0410-ae9c-e8d60b6d4f22
Diffstat (limited to 'Examples/python')
-rw-r--r-- | Examples/python/class/Makefile | 19 | ||||
-rw-r--r-- | Examples/python/class/example.cxx | 28 | ||||
-rw-r--r-- | Examples/python/class/example.h | 39 | ||||
-rw-r--r-- | Examples/python/class/example.i | 11 | ||||
-rw-r--r-- | Examples/python/class/example.py | 70 | ||||
-rw-r--r-- | Examples/python/class/index.html | 239 | ||||
-rw-r--r-- | Examples/python/index.html | 1 |
7 files changed, 407 insertions, 0 deletions
diff --git a/Examples/python/class/Makefile b/Examples/python/class/Makefile new file mode 100644 index 000000000..71af176f9 --- /dev/null +++ b/Examples/python/class/Makefile @@ -0,0 +1,19 @@ +TOP = ../.. +SWIG = $(TOP)/../swig +CXXSRCS = example.cxx +TARGET = example +INTERFACE = example.i +LIBS = -lm + +all:: + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' python_cpp + +static:: + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + TARGET='mypython' INTERFACE='$(INTERFACE)' python_cpp_static + +clean:: + rm -f *_wrap* *.o *~ *.so mypython *.pyc .~* core + +check: all diff --git a/Examples/python/class/example.cxx b/Examples/python/class/example.cxx new file mode 100644 index 000000000..21582f4d1 --- /dev/null +++ b/Examples/python/class/example.cxx @@ -0,0 +1,28 @@ +/* File : example.c */ + +#include "example.h" +#include <math.h> + +/* Move the shape to a new location */ +void Shape::move(double dx, double dy) { + x += dx; + y += dy; +} + +int Shape::nshapes = 0; + +double Circle::area() { + return M_PI*radius*radius; +} + +double Circle::perimeter() { + return 2*M_PI*radius; +} + +double Square::area() { + return width*width; +} + +double Square::perimeter() { + return 4*width; +} diff --git a/Examples/python/class/example.h b/Examples/python/class/example.h new file mode 100644 index 000000000..849071dd3 --- /dev/null +++ b/Examples/python/class/example.h @@ -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() = 0; + virtual double perimeter() = 0; + static int nshapes; +}; + +class Circle : public Shape { +private: + double radius; +public: + Circle(double r) : radius(r) { }; + virtual double area(); + virtual double perimeter(); +}; + +class Square : public Shape { +private: + double width; +public: + Square(double w) : width(w) { }; + virtual double area(); + virtual double perimeter(); +}; + + + + + diff --git a/Examples/python/class/example.i b/Examples/python/class/example.i new file mode 100644 index 000000000..23ee8a822 --- /dev/null +++ b/Examples/python/class/example.i @@ -0,0 +1,11 @@ +/* File : example.i */ +%module example + +%{ +#include "example.h" +%} + +/* Let's just grab the original header file here */ + +%include "example.h" + diff --git a/Examples/python/class/example.py b/Examples/python/class/example.py new file mode 100644 index 000000000..0e578da7b --- /dev/null +++ b/Examples/python/class/example.py @@ -0,0 +1,70 @@ +# file: example.py + +# This file illustrates the low-level C++ interface +# created by SWIG. In this case, all of our C++ classes +# get converted into function calls. + +import example + +# ----- Object creation ----- + +print "Creating some objects:" +c = example.new_Circle(10) +print " Created circle", c +s = example.new_Square(10) +print " Created square", s + +# ----- Access a static member ----- + +print "\nA total of", example.cvar.Shape_nshapes,"shapes were created" + +# ----- Member data access ----- + +# Set the location of the object + +# Notice how we can do this using functions specific to +# the 'Circle' class. +example.Circle_x_set(c, 20) +example.Circle_y_set(c, 30) + +# Now use the same functions in the base class +example.Shape_x_set(s,-10) +example.Shape_y_set(s,5) + +print "\nHere is their current position:" +print " Circle = (%f, %f)" % (example.Shape_x_get(c), example.Shape_y_get(c)) +print " Square = (%f, %f)" % (example.Shape_x_get(s), example.Shape_y_get(s)) + +# ----- Call some methods ----- + +print "\nHere are some properties of the shapes:" +for o in [c,s]: + print " ", o + print " area = ", example.Shape_area(o) + print " perimeter = ", example.Shape_perimeter(o) + +# Notice how the Shape_area() and Shape_perimeter() functions really +# invoke the appropriate virtual method on each object. + +# ----- Try to cause a type error ----- + +print "\nI'm going to try and break the type system" +try: + # Bad script! + Square_area(c) # Try to invoke Square method on a Circle + print " Bad bad SWIG!" +except: + print " Well, it didn't work. Good SWIG." + + +# ----- Delete everything ----- + +print "\nGuess I'll clean up now" + +# Note: this invokes the virtual destructor +example.delete_Shape(c) +example.delete_Shape(s) + +print example.cvar.Shape_nshapes,"shapes remain" +print "Goodbye" + diff --git a/Examples/python/class/index.html b/Examples/python/class/index.html new file mode 100644 index 000000000..3529b3ca9 --- /dev/null +++ b/Examples/python/class/index.html @@ -0,0 +1,239 @@ +<html> +<head> +<title>SWIG:Examples:python:class</title> +</head> + +<body bgcolor="#ffffff"> + + +<tt>SWIG/Examples/python/class/</tt> +<hr> + +<H2>Wrapping a simple C++ class</H2> + +<tt>$Header$</tt><br> + +<p> +This example illustrates the most primitive form of C++ class wrapping performed +by SWIG. In this case, C++ classes are simply transformed into a collection of +C-style functions that provide access to class members. + +<h2>The C++ Code</h2> + +Suppose you have some C++ classes described by the following (and admittedly lame) +header file: + +<blockquote> +<pre> +/* File : example.h */ + +class Shape { +public: + Shape() { + nshapes++; + } + virtual ~Shape() { + nshapes--; + }; + double x, y; + void move(double dx, double dy); + virtual double area() = 0; + virtual double perimeter() = 0; + static int nshapes; +}; + +class Circle : public Shape { +private: + double radius; +public: + Circle(double r) : radius(r) { }; + virtual double area(); + virtual double perimeter(); +}; + +class Square : public Shape { +private: + double width; +public: + Square(double w) : width(w) { }; + virtual double area(); + virtual double perimeter(); +}; +</pre> +</blockquote> + +<h2>The SWIG interface</h2> + +A simple SWIG interface for this can be built by simply grabbing the header file +like this: + +<blockquote> +<pre> +/* File : example.i */ +%module example + +%{ +#include "example.h" +%} + +/* Let's just grab the original header file here */ +%include "example.h" +</pre> +</blockquote> + +Note: when creating a C++ extension, you must run SWIG with the <tt>-c++</tt> option like this: +<blockquote> +<pre> +% swig -c++ -python example.i +</pre> +</blockquote> + +<h2>A sample Python script</h2> + +Click <a href="example.py">here</a> to see a script that calls the C++ functions from Python. + +<h2>Key points</h2> + +<ul> +<li>To create a new object, you call a constructor like this: + +<blockquote> +<pre> +c = example.new_Circle(10.0) +</pre> +</blockquote> + +<p> +<li>To access member data, a pair of accessor functions are used. +For example: + +<blockquote> +<pre> +example.Circle_x_set(c,15) # Set member data +x = example.Shape_x_get(c) # Get member data +</pre> +</blockquote> + +Note: when accessing member data, the name of the base class or the derived class can be +used in the function name as shown above. Of course, it would probably be more +proper to just use the base class version such as <tt>Shape_x_get()</tt> + +<p> +<li>To invoke a member function, you simply do this + +<blockquote> +<pre> +print "The area is ", example.Shape_area(c) +</pre> +</blockquote> + +<p> +<li>Type checking knows about the inheritance structure of C++. For example: + +<blockquote> +<pre> +example.Shape_area(c) # Works (c is a Shape) +example.Circle_area(c) # Works (c is a Circle) +example.Square_area(c) # Fails (c is definitely not a Square) +</pre> +</blockquote> + +<p> +<li>To invoke a destructor, simply do this + +<blockquote> +<pre> +example.delete_Shape(c) # Deletes a shape +</pre> +</blockquote> + +(Note: destructors are currently not inherited. This might change later). + +<p> +<li>Static member variables are wrapped as C global variables. For example: + +<blockquote> +<pre> +n = example.cvar.Shape_nshapes # Get a static data member +example.cvar.Shapes_nshapes = 13 # Set a static data member +</pre> +</blockquote> + +</ul> + +<h2>General Comments</h2> + +<ul> +<li>This low-level interface is not the only way to handle C++ code. Shadow classes +provide a much higher-level interface. + +<p> +<li>SWIG *does* know how to properly perform upcasting of objects in an inheritance +hierarchy (including multiple inheritance). Therefore it is perfectly safe to pass +an object of a derived class to any function involving a base class. + +<p> +<li>A wide variety of C++ features are not currently supported by SWIG. Here is the +short and incomplete list: + +<p> +<ul> +<li>Overloaded methods and functions. SWIG wrappers don't know how to resolve name +conflicts so you must give an alternative name to any overloaded method name using the +%name directive like this: + +<blockquote> +<pre> +void foo(int a); +%name(foo2) void foo(double a, double b); +</pre> +</blockquote> + +<p> +<li>Overloaded operators. Not supported at all. The only workaround for this is +to write a helper function. For example: + +<blockquote> +<pre> +%inline %{ + Vector *vector_add(Vector *a, Vector *b) { + ... whatever ... + } +%} +</pre> +</blockquote> + +<p> +<li>Namespaces. Not supported at all. Won't be supported until SWIG2.0 (if at all). + +<p> +<li>Templates. Not supported at all. SWIG throws out anything that looks like a template. +You can work around the problem by aliasing a template class behind a typedef however. +For example: + +<blockquote> +<pre> +%{ +typedef vector<int> IntVector; +%} + +class IntVector { +public: + ... methods ... +}; +</pre> +</blockquote> +</ul> +<p> +<li>There is no guarantee that an extremely complex C++ application will be able to compile +as a Python extension. Sorry. + +<p> +<li>Dave's snide remark: Like a large bottle of strong Tequilla, it's better to +use C++ in moderation. + +</ul> + +<hr> +</body> +</html> diff --git a/Examples/python/index.html b/Examples/python/index.html index 802db9b75..68b0bdfa1 100644 --- a/Examples/python/index.html +++ b/Examples/python/index.html @@ -18,6 +18,7 @@ be used to wrap a C function, a global variable, and a constant. certain C declarations are turned into constants. <li><a href="variables/index.html">variables</a>. An example showing how to access C global variables from Python. <li><a href="value/index.html">value</a>. How to pass and return structures by value. +<li><a href="class/index.html">class</a>. Wrapping a simple C++ class. </ul> <h2>Compilation Issues</h2> |