diff options
Diffstat (limited to 'Examples/octave/extend')
| -rw-r--r-- | Examples/octave/extend/Makefile | 21 | ||||
| -rw-r--r-- | Examples/octave/extend/example.cxx | 4 | ||||
| -rw-r--r-- | Examples/octave/extend/example.h | 56 | ||||
| -rw-r--r-- | Examples/octave/extend/example.i | 15 | ||||
| -rw-r--r-- | Examples/octave/extend/runme.m | 74 |
5 files changed, 170 insertions, 0 deletions
diff --git a/Examples/octave/extend/Makefile b/Examples/octave/extend/Makefile new file mode 100644 index 0000000..2bce9df --- /dev/null +++ b/Examples/octave/extend/Makefile @@ -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 diff --git a/Examples/octave/extend/example.cxx b/Examples/octave/extend/example.cxx new file mode 100644 index 0000000..450d756 --- /dev/null +++ b/Examples/octave/extend/example.cxx @@ -0,0 +1,4 @@ +/* File : example.cxx */ + +#include "example.h" + diff --git a/Examples/octave/extend/example.h b/Examples/octave/extend/example.h new file mode 100644 index 0000000..b27ab97 --- /dev/null +++ b/Examples/octave/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/octave/extend/example.i b/Examples/octave/extend/example.i new file mode 100644 index 0000000..c8ec32e --- /dev/null +++ b/Examples/octave/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/octave/extend/runme.m b/Examples/octave/extend/runme.m new file mode 100644 index 0000000..c64c082 --- /dev/null +++ b/Examples/octave/extend/runme.m @@ -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 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 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"); + |
