diff options
-rw-r--r-- | Examples/go/callback/Makefile | 16 | ||||
-rw-r--r-- | Examples/go/callback/callback.cxx | 4 | ||||
-rw-r--r-- | Examples/go/callback/example.h | 23 | ||||
-rw-r--r-- | Examples/go/callback/example.i | 11 | ||||
-rw-r--r-- | Examples/go/callback/index.html | 81 | ||||
-rw-r--r-- | Examples/go/callback/runme.go | 41 | ||||
-rw-r--r-- | Examples/go/check.list | 2 | ||||
-rw-r--r-- | Examples/go/extend/Makefile | 16 | ||||
-rw-r--r-- | Examples/go/extend/example.h | 56 | ||||
-rw-r--r-- | Examples/go/extend/example.i | 15 | ||||
-rw-r--r-- | Examples/go/extend/extend.cxx | 4 | ||||
-rw-r--r-- | Examples/go/extend/index.html | 27 | ||||
-rw-r--r-- | Examples/go/extend/runme.go | 76 | ||||
-rw-r--r-- | Examples/go/index.html | 3 |
14 files changed, 374 insertions, 1 deletions
diff --git a/Examples/go/callback/Makefile b/Examples/go/callback/Makefile new file mode 100644 index 000000000..bf5275f14 --- /dev/null +++ b/Examples/go/callback/Makefile @@ -0,0 +1,16 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +CXXSRCS = callback.cxx +TARGET = example +INTERFACE = example.i +SWIGOPT = + +check: build + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go_run + +build: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go_cpp + +clean: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' INTERFACE='$(INTERFACE)' go_clean diff --git a/Examples/go/callback/callback.cxx b/Examples/go/callback/callback.cxx new file mode 100644 index 000000000..450d75608 --- /dev/null +++ b/Examples/go/callback/callback.cxx @@ -0,0 +1,4 @@ +/* File : example.cxx */ + +#include "example.h" + diff --git a/Examples/go/callback/example.h b/Examples/go/callback/example.h new file mode 100644 index 000000000..1a0e8c432 --- /dev/null +++ b/Examples/go/callback/example.h @@ -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(); } +}; + diff --git a/Examples/go/callback/example.i b/Examples/go/callback/example.i new file mode 100644 index 000000000..cf61ef9d2 --- /dev/null +++ b/Examples/go/callback/example.i @@ -0,0 +1,11 @@ +/* File : example.i */ +%module(directors="1") example +%{ +#include "example.h" +%} + +/* turn on director wrapping Callback */ +%feature("director") Callback; + +%include "example.h" + diff --git a/Examples/go/callback/index.html b/Examples/go/callback/index.html new file mode 100644 index 000000000..b053cf547 --- /dev/null +++ b/Examples/go/callback/index.html @@ -0,0 +1,81 @@ +<html> +<head> +<title>SWIG:Examples:go:callback</title> +</head> + +<body bgcolor="#ffffff"> + + +<tt>SWIG/Examples/go/callback/</tt> +<hr> + +<H2>Implementing C++ callbacks in Go</H2> + +<p> +This example illustrates how to use directors to implement C++ +callbacks in Go. +</p> + +<p> +Because Go and C++ use inheritance differently, you must call a +different function to create a class which uses callbacks. Instead of +calling the usual constructor function whose name is <tt>New</tt> +followed by the capitalized name of the class, you call a function +named <tt>NewDirector</tt> followed by the capitalized name of the +class. +</p> + +<p> +The first argument to the <tt>NewDirector</tt> function is an instance +of a type. The <tt>NewDirector</tt> function will return an interface +value as usual. However, when calling any method on the returned +value, the program will first check whether the value passed +to <tt>NewDirector</tt> implements that method. If it does, the +method will be called in Go. This is true whether the method is +called from Go code or C++ code. +</p> + +<p> +Note that the Go code will be called with just the Go value, not the +C++ value. If the Go code needs to call a C++ method on itself, you +need to get a copy of the C++ object. This is typically done as +follows: + +<blockquote> +<pre> +type Child struct { abi Parent } +func (p *Child) ChildMethod() { + p.abi.ParentMethod() +} +func f() { + p := &Child{nil} + d := NewDirectorParent(p) + p.abi = d + ... +} +</pre> +</blockquote> + +In other words, we first create the Go value. We pass that to +the <tt>NewDirector</tt> function to create the C++ value; this C++ +value will be created with an association to the Go value. We then +store the C++ value in the Go value, giving us the reverse +association. That permits us to call parent methods from the child. + +</p> + +<p> +To delete a director object, use the function <tt>DeleteDirector</tt> +followed by the capitalized name of the class. +</p> + +<p> +<ul> +<li><a href="example.h">example.h</a>. Header file containing some enums. +<li><a href="example.i">example.i</a>. Interface file. +<li><a href="runme.go">runme.go</a>. Sample Go program. +</ul> + +<hr> +</body> +</html> diff --git a/Examples/go/callback/runme.go b/Examples/go/callback/runme.go new file mode 100644 index 000000000..2eef77fdb --- /dev/null +++ b/Examples/go/callback/runme.go @@ -0,0 +1,41 @@ +package main + +import ( + . "./example" + "fmt" +) + +func main() { + fmt.Println("Adding and calling a normal C++ callback") + fmt.Println("----------------------------------------") + + caller := NewCaller() + callback := NewCallback() + + caller.SetCallback(callback) + caller.Call() + caller.DelCallback() + + callback = NewDirectorCallback(new(GoCallback)) + + fmt.Println() + fmt.Println("Adding and calling a Go callback") + fmt.Println("------------------------------------") + + caller.SetCallback(callback) + caller.Call() + caller.DelCallback() + + // Test that a double delete does not occur as the object has + // already been deleted from the C++ layer. + DeleteDirectorCallback(callback) + + fmt.Println() + fmt.Println("Go exit") +} + +type GoCallback struct{} + +func (p *GoCallback) Run() { + fmt.Println("GoCallback.Run") +} diff --git a/Examples/go/check.list b/Examples/go/check.list index 25322352a..b3f34b306 100644 --- a/Examples/go/check.list +++ b/Examples/go/check.list @@ -1,8 +1,10 @@ # see top-level Makefile.in +callback class constants director enum +extend funcptr multimap pointer diff --git a/Examples/go/extend/Makefile b/Examples/go/extend/Makefile new file mode 100644 index 000000000..290694210 --- /dev/null +++ b/Examples/go/extend/Makefile @@ -0,0 +1,16 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +CXXSRCS = extend.cxx +TARGET = example +INTERFACE = example.i +SWIGOPT = + +check: build + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go_run + +build: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go_cpp + +clean: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' INTERFACE='$(INTERFACE)' go_clean diff --git a/Examples/go/extend/example.h b/Examples/go/extend/example.h new file mode 100644 index 000000000..ca1aed28f --- /dev/null +++ b/Examples/go/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", (void *)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/go/extend/example.i b/Examples/go/extend/example.i new file mode 100644 index 000000000..c8ec32e09 --- /dev/null +++ b/Examples/go/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/go/extend/extend.cxx b/Examples/go/extend/extend.cxx new file mode 100644 index 000000000..450d75608 --- /dev/null +++ b/Examples/go/extend/extend.cxx @@ -0,0 +1,4 @@ +/* File : example.cxx */ + +#include "example.h" + diff --git a/Examples/go/extend/index.html b/Examples/go/extend/index.html new file mode 100644 index 000000000..471fa9cdc --- /dev/null +++ b/Examples/go/extend/index.html @@ -0,0 +1,27 @@ +<html> +<head> +<title>SWIG:Examples:go:extend</title> +</head> + +<body bgcolor="#ffffff"> + + +<tt>SWIG/Examples/go/extend/</tt> +<hr> + +<H2>Extending a simple C++ class in Go</H2> + +<p> +This example illustrates the extending of a C++ class with cross +language polymorphism. + +<p> +<ul> +<li><a href="example.h">example.h</a>. Header file containing some enums. +<li><a href="example.i">example.i</a>. Interface file. +<li><a href="runme.go">runme.go</a>. Sample Go program. +</ul> + +<hr> +</body> +</html> diff --git a/Examples/go/extend/runme.go b/Examples/go/extend/runme.go new file mode 100644 index 000000000..770e27802 --- /dev/null +++ b/Examples/go/extend/runme.go @@ -0,0 +1,76 @@ +// This file illustrates the cross language polymorphism using directors. + +package main + +import ( + . "./example" + "fmt" +) + +type CEO struct{} + +func (p *CEO) GetPosition() string { + return "CEO" +} + +func main() { + // Create an instance of CEO, a class derived from the Go + // proxy of the underlying C++ class. The calls to getName() + // and getPosition() are standard, the call to getTitle() uses + // the director wrappers to call CEO.getPosition(). + + e := NewDirectorManager(new(CEO), "Alice") + fmt.Println(e.GetName(), " is a ", e.GetPosition()) + fmt.Println("Just call her \"", e.GetTitle(), "\"") + fmt.Println("----------------------") + + // 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 := NewEmployeeList() + + // EmployeeList owns its items, so we must surrender ownership + // of objects we add. + // e.DisownMemory() + list.AddEmployee(e) + fmt.Println("----------------------") + + // 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, all methods + // resolve in C++. For item 3, our CEO, GetTitle calls + // GetPosition which resolves in Go. The call to GetPosition + // is slightly different, however, because of the overridden + // GetPosition() call, since now the object reference has been + // "laundered" by passing through EmployeeList as an + // Employee*. Previously, Go resolved the call immediately in + // CEO, but now Go thinks the object is an instance of class + // Employee. So the call passes through the Employee proxy + // class and on to the C wrappers and C++ director, eventually + // ending up back at the Java 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 Java implementation + // in CEO. All this routing takes place transparently. + + fmt.Println("(position, title) for items 0-3:") + + fmt.Println(" ", list.Get_item(0).GetPosition(), ", \"", list.Get_item(0).GetTitle(), "\"") + fmt.Println(" ", list.Get_item(1).GetPosition(), ", \"", list.Get_item(1).GetTitle(), "\"") + fmt.Println(" ", list.Get_item(2).GetPosition(), ", \"", list.Get_item(2).GetTitle(), "\"") + fmt.Println(" ", list.Get_item(3).GetPosition(), ", \"", list.Get_item(3).GetTitle(), "\"") + fmt.Println("----------------------") + + // Time to delete the EmployeeList, which will delete all the + // Employee* items it contains. The last item is our CEO, + // which gets destroyed as well. + DeleteEmployeeList(list) + fmt.Println("----------------------") + + // All done. + + fmt.Println("Go exit") +} diff --git a/Examples/go/index.html b/Examples/go/index.html index b7d7017d3..ed6a6b707 100644 --- a/Examples/go/index.html +++ b/Examples/go/index.html @@ -21,7 +21,8 @@ certain C declarations are turned into constants. <li><a href="pointer/index.html">pointer</a>. Simple pointer handling. <li><a href="funcptr/index.html">funcptr</a>. Pointers to functions. <li><a href="template/index.html">template</a>. C++ templates. -<li><a href="director/index.html">director</a>. Example how to utilize the director feature. +<li><a href="callback/index.html">callback</a>. C++ callbacks using directors. +<li><a href="extend/index.html">extend</a>. Polymorphism using directors. </ul> <h2>Compilation Issues</h2> |