diff options
Diffstat (limited to 'Examples/python/extend')
-rw-r--r-- | Examples/python/extend/Makefile | 22 | ||||
-rw-r--r-- | Examples/python/extend/example.cxx | 4 | ||||
-rw-r--r-- | Examples/python/extend/example.h | 56 | ||||
-rw-r--r-- | Examples/python/extend/example.i | 15 | ||||
-rw-r--r-- | Examples/python/extend/index.html | 19 | ||||
-rw-r--r-- | Examples/python/extend/runme.py | 81 |
6 files changed, 197 insertions, 0 deletions
diff --git a/Examples/python/extend/Makefile b/Examples/python/extend/Makefile new file mode 100644 index 0000000..a29276e --- /dev/null +++ b/Examples/python/extend/Makefile @@ -0,0 +1,22 @@ +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)' python_cpp + +static:: + $(MAKE) -f $(TOP)/Makefile $(SWIGLIB) CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + SWIGOPT='$(SWIGOPT)' TARGET='mypython' INTERFACE='$(INTERFACE)' python_cpp_static + +clean:: + $(MAKE) -f $(TOP)/Makefile python_clean + rm -f $(TARGET).py + +check: all + $(MAKE) -f $(TOP)/Makefile python_run diff --git a/Examples/python/extend/example.cxx b/Examples/python/extend/example.cxx new file mode 100644 index 0000000..450d756 --- /dev/null +++ b/Examples/python/extend/example.cxx @@ -0,0 +1,4 @@ +/* File : example.cxx */ + +#include "example.h" + diff --git a/Examples/python/extend/example.h b/Examples/python/extend/example.h new file mode 100644 index 0000000..b27ab97 --- /dev/null +++ b/Examples/python/extend/example.h @@ -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; + } +}; + diff --git a/Examples/python/extend/example.i b/Examples/python/extend/example.i new file mode 100644 index 0000000..c8ec32e --- /dev/null +++ b/Examples/python/extend/example.i @@ -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" + diff --git a/Examples/python/extend/index.html b/Examples/python/extend/index.html new file mode 100644 index 0000000..959e8c6 --- /dev/null +++ b/Examples/python/extend/index.html @@ -0,0 +1,19 @@ +<html> +<head> +<title>SWIG:Examples:python:extend</title> +</head> + +<body bgcolor="#ffffff"> + + +<tt>SWIG/Examples/python/extend/</tt> +<hr> + +<H2>Extending a simple C++ class in Python</H2> + +<p> +This example illustrates the extending of a C++ class with cross language polymorphism. + +<hr> +</body> +</html> diff --git a/Examples/python/extend/runme.py b/Examples/python/extend/runme.py new file mode 100644 index 0000000..240b098 --- /dev/null +++ b/Examples/python/extend/runme.py @@ -0,0 +1,81 @@ +# file: runme.py + +# This file illustrates the cross language polymorphism using directors. + +import example + + +# CEO class, which overrides Employee::getPosition(). + +class CEO(example.Manager): + def __init__(self, name): + example.Manager.__init__(self, name) + def getPosition(self): + return "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") +print e.getName(), "is a", e.getPosition() +print "Just call her \"%s\"" % e.getTitle() +print "----------------------" + + +# 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) +print "----------------------" + +# 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 Python. 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, Python resolved the call +# immediately in CEO, but now Python thinks the object is an instance of +# class Employee (actually EmployeePtr). So the call passes through the +# Employee proxy 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 Python implementation +# in CEO. All this routing takes place transparently. + +print "(position, title) for items 0-3:" + +print " %s, \"%s\"" % (list.get_item(0).getPosition(), list.get_item(0).getTitle()) +print " %s, \"%s\"" % (list.get_item(1).getPosition(), list.get_item(1).getTitle()) +print " %s, \"%s\"" % (list.get_item(2).getPosition(), list.get_item(2).getTitle()) +print " %s, \"%s\"" % (list.get_item(3).getPosition(), list.get_item(3).getTitle()) +print "----------------------" + +# 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 Python 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. + +del list +print "----------------------" + +# All done. + +print "python exit" + |