diff options
author | Ian Lance Taylor <iant@golang.org> | 2015-08-09 07:31:09 -0700 |
---|---|---|
committer | Ian Lance Taylor <iant@golang.org> | 2015-08-09 07:31:09 -0700 |
commit | 01edfef3b8bd63ad9041b8da9525e0dfb6b2101a (patch) | |
tree | f38c017e1731d32ca4eb5d74a466a251e7f93fca | |
parent | 19a20c794bea67fb7e3530da362473c05cf87cad (diff) | |
parent | 608ef60ecf7774533b3344622be5b8df64bf133e (diff) | |
download | swig-01edfef3b8bd63ad9041b8da9525e0dfb6b2101a.tar.gz |
Merge pull request #493 from michael-schaller/dir-examples
[Go] Undelete and updated the 'callback' and 'extend' examples.
-rw-r--r-- | Doc/Manual/Go.html | 196 | ||||
-rw-r--r-- | Examples/go/callback/Makefile | 24 | ||||
-rw-r--r-- | Examples/go/callback/callback.cxx | 4 | ||||
-rw-r--r-- | Examples/go/callback/example.h | 22 | ||||
-rw-r--r-- | Examples/go/callback/example.i | 11 | ||||
-rw-r--r-- | Examples/go/callback/gocallback.go | 41 | ||||
-rw-r--r-- | Examples/go/callback/index.html | 31 | ||||
-rw-r--r-- | Examples/go/callback/runme.go | 33 | ||||
-rw-r--r-- | Examples/go/check.list | 2 | ||||
-rw-r--r-- | Examples/go/director/Makefile | 11 | ||||
-rw-r--r-- | Examples/go/director/director.go | 74 | ||||
-rw-r--r-- | Examples/go/director/director.h | 10 | ||||
-rw-r--r-- | Examples/go/director/example.i | 2 | ||||
-rw-r--r-- | Examples/go/director/index.html | 2 | ||||
-rw-r--r-- | Examples/go/extend/Makefile | 24 | ||||
-rw-r--r-- | Examples/go/extend/ceo.go | 37 | ||||
-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 | 30 | ||||
-rw-r--r-- | Examples/go/extend/runme.go | 66 | ||||
-rw-r--r-- | Examples/go/index.html | 2 |
22 files changed, 552 insertions, 145 deletions
diff --git a/Doc/Manual/Go.html b/Doc/Manual/Go.html index c008ef22c..ca12410ad 100644 --- a/Doc/Manual/Go.html +++ b/Doc/Manual/Go.html @@ -606,22 +606,22 @@ completely to avoid common pitfalls with directors in Go. <H4><a name="Go_director_example_cpp_code"></a>23.4.7.1 Example C++ code</H4> <p> -The step by step guide is based on two example C++ classes. FooBarAbs is an -abstract C++ class and the FooBarCpp class inherits from it. This guide +The step by step guide is based on two example C++ classes. FooBarAbstract is +an abstract C++ class and the FooBarCpp class inherits from it. This guide explains how to implement a FooBarGo class similar to the FooBarCpp class. </p> <p> -<tt>FooBarAbs</tt> abstract C++ class: +<tt>FooBarAbstract</tt> abstract C++ class: </p> <div class="code"> <pre> -class FooBarAbs +class FooBarAbstract { public: - FooBarAbs() {}; - virtual ~FooBarAbs() {}; + FooBarAbstract() {}; + virtual ~FooBarAbstract() {}; std::string FooBar() { return this->Foo() + ", " + this->Bar(); @@ -643,11 +643,11 @@ protected: <div class="code"> <pre> -class FooBarCpp : public FooBarAbs +class FooBarCpp : public FooBarAbstract { protected: virtual std::string Foo() { - return "C++ " + FooBarAbs::Foo(); + return "C++ " + FooBarAbstract::Foo(); } virtual std::string Bar() { @@ -691,14 +691,14 @@ directive, like this: <p> Second, you must use the %feature("director") directive to tell SWIG which -classes should get directors. In the example the FooBarAbs class needs the +classes should get directors. In the example the FooBarAbstract class needs the director feature enabled so that the FooBarGo class can inherit from it, like this: </p> <div class="code"> <pre> -%feature("director") FooBarAbs; +%feature("director") FooBarAbstract; </pre> </div> @@ -782,21 +782,21 @@ As an example see part of the <tt>FooBarGo</tt> class: <div class="code"> <pre> -type overwrittenMethodsOnFooBarAbs struct { - fb FooBarAbs +type overwrittenMethodsOnFooBarAbstract struct { + fb FooBarAbstract } -func (om *overwrittenMethodsOnFooBarAbs) Foo() string { +func (om *overwrittenMethodsOnFooBarAbstract) Foo() string { ... } -func (om *overwrittenMethodsOnFooBarAbs) Bar() string { +func (om *overwrittenMethodsOnFooBarAbstract) Bar() string { ... } func NewFooBarGo() FooBarGo { - om := &overwrittenMethodsOnFooBarAbs{} - fb := NewDirectorFooBarAbs(om) + om := &overwrittenMethodsOnFooBarAbstract{} + fb := NewDirectorFooBarAbstract(om) om.fb = fb ... } @@ -806,25 +806,25 @@ func NewFooBarGo() FooBarGo { <p> The complete example, including the <tt>FooBarGoo</tt> class implementation, can be found in <a href="#Go_director_foobargo_class">the end of the guide</a>. In -this part of the example the virtual methods <tt>FooBarAbs::Foo</tt> and -<tt>FooBarAbs::Bar</tt> have been overwritten with Go methods similarly to how -the <tt>FooBarAbs</tt> virtual methods are overwritten by the <tt>FooBarCpp</tt> -class. +this part of the example the virtual methods <tt>FooBarAbstract::Foo</tt> and +<tt>FooBarAbstract::Bar</tt> have been overwritten with Go methods similarly to +how the <tt>FooBarAbstract</tt> virtual methods are overwritten by the +<tt>FooBarCpp</tt> class. </p> <p> The <tt>DirectorInterface</tt> in the example is implemented by the -<tt>overwrittenMethodsOnFooBarAbs</tt> Go struct type. A pointer to a -<tt>overwrittenMethodsOnFooBarAbs</tt> struct instance will be given to the -<tt>NewDirectorFooBarAbs</tt> constructor function. The constructor return -value implements the <tt>FooBarAbs</tt> interface. -<tt>overwrittenMethodsOnFooBarAbs</tt> could in theory be any Go type but in -practice a struct is used as it typically contains at least a value of the +<tt>overwrittenMethodsOnFooBarAbstract</tt> Go struct type. A pointer to a +<tt>overwrittenMethodsOnFooBarAbstract</tt> struct instance will be given to the +<tt>NewDirectorFooBarAbstract</tt> constructor function. The constructor return +value implements the <tt>FooBarAbstract</tt> interface. +<tt>overwrittenMethodsOnFooBarAbstract</tt> could in theory be any Go type but +in practice a struct is used as it typically contains at least a value of the C++ class interface so that the overwritten methods can use the rest of the C++ class. If the <tt>FooBarGo</tt> class would receive additional constructor arguments then these would also typically be stored in the -<tt>overwrittenMethodsOnFooBarAbs</tt> struct so that they can be used by the -Go methods. +<tt>overwrittenMethodsOnFooBarAbstract</tt> struct so that they can be used by +the Go methods. </p> @@ -840,7 +840,7 @@ the method in the base class. This is also the case for the <div class="code"> <pre> virtual std::string Foo() { - return "C++ " + FooBarAbs::Foo(); + return "C++ " + FooBarAbstract::Foo(); } </pre> </div> @@ -853,8 +853,8 @@ The <tt>FooBarGo.Foo</tt> implementation in the example looks like this: <div class="code"> <pre> -func (om *overwrittenMethodsOnFooBarAbs) Foo() string { - return "Go " + DirectorFooBarAbsFoo(om.fb) +func (om *overwrittenMethodsOnFooBarAbstract) Foo() string { + return "Go " + DirectorFooBarAbstractFoo(om.fb) } </pre> </div> @@ -887,31 +887,31 @@ this: <div class="code"> <pre> type FooBarGo interface { - FooBarAbs - deleteFooBarAbs() + FooBarAbstract + deleteFooBarAbstract() IsFooBarGo() } type fooBarGo struct { - FooBarAbs + FooBarAbstract } -func (fbgs *fooBarGo) deleteFooBarAbs() { - DeleteDirectorFooBarAbs(fbgs.FooBarAbs) +func (fbgs *fooBarGo) deleteFooBarAbstract() { + DeleteDirectorFooBarAbstract(fbgs.FooBarAbstract) } func (fbgs *fooBarGo) IsFooBarGo() {} func NewFooBarGo() FooBarGo { - om := &overwrittenMethodsOnFooBarAbs{} - fb := NewDirectorFooBarAbs(om) + om := &overwrittenMethodsOnFooBarAbstract{} + fb := NewDirectorFooBarAbstract(om) om.fb = fb - return &fooBarGo{FooBarAbs: fb} + return &fooBarGo{FooBarAbstract: fb} } func DeleteFooBarGo(fbg FooBarGo) { - fbg.deleteFooBarAbs() + fbg.deleteFooBarAbstract() } </pre> </div> @@ -921,12 +921,12 @@ func DeleteFooBarGo(fbg FooBarGo) { The complete example, including the <tt>FooBarGoo</tt> class implementation, can be found in <a href="#Go_director_foobargo_class">the end of the guide</a>. In this part of the example the private <tt>fooBarGo</tt> struct embeds <tt> -FooBarAbs</tt> which lets the <tt>fooBarGo</tt> Go type "inherit" all the -methods of the <tt>FooBarAbs</tt> C++ class by means of embedding. The public -<tt>FooBarGo</tt> interface type includes the <tt>FooBarAbs</tt> interface and -hence <tt>FooBarGo</tt> can be used as a drop in replacement for -<tt>FooBarAbs</tt> while the reverse isn't possible and would raise a compile -time error. Furthemore the constructor and destructor functions <tt> +FooBarAbstract</tt> which lets the <tt>fooBarGo</tt> Go type "inherit" all the +methods of the <tt>FooBarAbstract</tt> C++ class by means of embedding. The +public <tt>FooBarGo</tt> interface type includes the <tt>FooBarAbstract</tt> +interface and hence <tt>FooBarGo</tt> can be used as a drop in replacement for +<tt>FooBarAbstract</tt> while the reverse isn't possible and would raise a +compile time error. Furthemore the constructor and destructor functions <tt> NewFooBarGo</tt> and <tt>DeleteFooBarGo</tt> take care of all the director specifics and to the user the class appears as any other SWIG wrapped C++ class. @@ -946,13 +946,13 @@ in the <tt>FooBarGo</tt> class is here: <div class="code"> <pre> -type overwrittenMethodsOnFooBarAbs struct { - fb FooBarAbs +type overwrittenMethodsOnFooBarAbstract struct { + fb FooBarAbstract } func NewFooBarGo() FooBarGo { - om := &overwrittenMethodsOnFooBarAbs{} - fb := NewDirectorFooBarAbs(om) // fb.v = om + om := &overwrittenMethodsOnFooBarAbstract{} + fb := NewDirectorFooBarAbstract(om) // fb.v = om om.fb = fb // Backlink causes cycle as fb.v = om! ... } @@ -963,27 +963,27 @@ func NewFooBarGo() FooBarGo { In order to be able to use <tt>runtime.SetFinalizer</tt> nevertheless the finalizer needs to be set on something that isn't in a cycle and that references the director object instance. In the <tt>FooBarGo</tt> class example the <tt> -FooBarAbs</tt> director instance can be automatically deleted by setting the -finalizer on <tt>fooBarGo</tt>: +FooBarAbstract</tt> director instance can be automatically deleted by setting +the finalizer on <tt>fooBarGo</tt>: </p> <div class="code"> <pre> type fooBarGo struct { - FooBarAbs + FooBarAbstract } -type overwrittenMethodsOnFooBarAbs struct { - fb FooBarAbs +type overwrittenMethodsOnFooBarAbstract struct { + fb FooBarAbstract } func NewFooBarGo() FooBarGo { - om := &overwrittenMethodsOnFooBarAbs{} - fb := NewDirectorFooBarAbs(om) + om := &overwrittenMethodsOnFooBarAbstract{} + fb := NewDirectorFooBarAbstract(om) om.fb = fb // Backlink causes cycle as fb.v = om! - fbgs := &fooBarGo{FooBarAbs: fb} - runtime.SetFinalizer(fbgs, FooBarGo.deleteFooBarAbs) + fbgs := &fooBarGo{FooBarAbstract: fb} + runtime.SetFinalizer(fbgs, FooBarGo.deleteFooBarAbstract) return fbgs } </pre> @@ -1007,73 +1007,75 @@ The complete and annotated <tt>FooBarGo</tt> class looks like this: <div class="code"> <pre> -// FooBarGo is a superset of FooBarAbs and hence FooBarGo can be used as a drop -// in replacement for FooBarAbs but the reverse causes a compile time error. +// FooBarGo is a superset of FooBarAbstract and hence FooBarGo can be used as a +// drop in replacement for FooBarAbstract but the reverse causes a compile time +// error. type FooBarGo interface { - FooBarAbs - deleteFooBarAbs() + FooBarAbstract + deleteFooBarAbstract() IsFooBarGo() } -// Via embedding fooBarGo "inherits" all methods of FooBarAbs. +// Via embedding fooBarGo "inherits" all methods of FooBarAbstract. type fooBarGo struct { - FooBarAbs + FooBarAbstract } -func (fbgs *fooBarGo) deleteFooBarAbs() { - DeleteDirectorFooBarAbs(fbgs.FooBarAbs) +func (fbgs *fooBarGo) deleteFooBarAbstract() { + DeleteDirectorFooBarAbstract(fbgs.FooBarAbstract) } -// The IsFooBarGo method ensures that FooBarGo is a superset of FooBarAbs. +// The IsFooBarGo method ensures that FooBarGo is a superset of FooBarAbstract. // This is also how the class hierarchy gets represented by the SWIG generated -// wrapper code. For an instance FooBarCpp has the IsFooBarAbs and IsFooBarCpp -// methods. +// wrapper code. For an instance FooBarCpp has the IsFooBarAbstract and +// IsFooBarCpp methods. func (fbgs *fooBarGo) IsFooBarGo() {} // Go type that defines the DirectorInterface. It contains the Foo and Bar -// methods that overwrite the respective virtual C++ methods on FooBarAbs. -type overwrittenMethodsOnFooBarAbs struct { - // Backlink to FooBarAbs so that the rest of the class can be used by the - // overridden methods. - fb FooBarAbs +// methods that overwrite the respective virtual C++ methods on FooBarAbstract. +type overwrittenMethodsOnFooBarAbstract struct { + // Backlink to FooBarAbstract so that the rest of the class can be used by + // the overridden methods. + fb FooBarAbstract // If additional constructor arguments have been given they are typically // stored here so that the overriden methods can use them. } -func (om *overwrittenMethodsOnFooBarAbs) Foo() string { - // DirectorFooBarAbsFoo calls the base method FooBarAbs::Foo. - return "Go " + DirectorFooBarAbsFoo(om.fb) +func (om *overwrittenMethodsOnFooBarAbstract) Foo() string { + // DirectorFooBarAbstractFoo calls the base method FooBarAbstract::Foo. + return "Go " + DirectorFooBarAbstractFoo(om.fb) } -func (om *overwrittenMethodsOnFooBarAbs) Bar() string { +func (om *overwrittenMethodsOnFooBarAbstract) Bar() string { return "Go Bar" } func NewFooBarGo() FooBarGo { - // Instantiate FooBarAbs with selected methods overridden. The methods that - // will be overwritten are defined on overwrittenMethodsOnFooBarAbs and have - // a compatible signature to the respective virtual C++ methods. - // Furthermore additional constructor arguments will be typically stored in - // the overwrittenMethodsOnFooBarAbs struct. - om := &overwrittenMethodsOnFooBarAbs{} - fb := NewDirectorFooBarAbs(om) + // Instantiate FooBarAbstract with selected methods overridden. The methods + // that will be overwritten are defined on + // overwrittenMethodsOnFooBarAbstract and have a compatible signature to the + // respective virtual C++ methods. Furthermore additional constructor + // arguments will be typically stored in the + // overwrittenMethodsOnFooBarAbstract struct. + om := &overwrittenMethodsOnFooBarAbstract{} + fb := NewDirectorFooBarAbstract(om) om.fb = fb // Backlink causes cycle as fb.v = om! - fbgs := &fooBarGo{FooBarAbs: fb} - // The memory of the FooBarAbs director object instance can be automatically - // freed once the FooBarGo instance is garbage collected by uncommenting the - // following line. Please make sure to understand the runtime.SetFinalizer - // specific gotchas before doing this. Furthemore DeleteFooBarGo should be - // deleted if a finalizer is in use or the fooBarGo struct needs additional - // data to prevent double deletion. - // runtime.SetFinalizer(fbgs, FooBarGo.deleteFooBarAbs) + fbgs := &fooBarGo{FooBarAbstract: fb} + // The memory of the FooBarAbstract director object instance can be + // automatically freed once the FooBarGo instance is garbage collected by + // uncommenting the following line. Please make sure to understand the + // runtime.SetFinalizer specific gotchas before doing this. Furthemore + // DeleteFooBarGo should be deleted if a finalizer is in use or the fooBarGo + // struct needs additional data to prevent double deletion. + // runtime.SetFinalizer(fbgs, FooBarGo.deleteFooBarAbstract) return fbgs } // Recommended to be removed if runtime.SetFinalizer is in use. func DeleteFooBarGo(fbg FooBarGo) { - fbg.deleteFooBarAbs() + fbg.deleteFooBarAbstract() } </pre> </div> @@ -1094,11 +1096,11 @@ For comparison the <tt>FooBarCpp</tt> class looks like this: <div class="code"> <pre> -class FooBarCpp : public FooBarAbs +class FooBarCpp : public FooBarAbstract { protected: virtual std::string Foo() { - return "C++ " + FooBarAbs::Foo(); + return "C++ " + FooBarAbstract::Foo(); } virtual std::string Bar() { diff --git a/Examples/go/callback/Makefile b/Examples/go/callback/Makefile new file mode 100644 index 000000000..7441e09bd --- /dev/null +++ b/Examples/go/callback/Makefile @@ -0,0 +1,24 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +CXXSRCS = callback.cxx +GOSRCS = gocallback.go +TARGET = example +INTERFACE = example.i +SWIGOPT = + +check: build + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go_run + +build: + if [ -n '$(SRCDIR)' ]; then \ + cp $(GOSRCS:%=$(SRCDIR)/%) .; \ + fi + @# Note: example.go gets generated by SWIG + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' GOSRCS='example.go $(GOSRCS)' \ + SWIG='$(SWIG)' SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go_cpp + +clean: + if [ -n '$(SRCDIR)' ]; then \ + rm $(GOSRCS) || true; \ + fi + $(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..74ddad954 --- /dev/null +++ b/Examples/go/callback/example.h @@ -0,0 +1,22 @@ +/* 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/gocallback.go b/Examples/go/callback/gocallback.go new file mode 100644 index 000000000..20fd0627a --- /dev/null +++ b/Examples/go/callback/gocallback.go @@ -0,0 +1,41 @@ +package example + +import ( + "fmt" +) + +type GoCallback interface { + Callback + deleteCallback() + IsGoCallback() +} + +type goCallback struct { + Callback +} + +func (p *goCallback) deleteCallback() { + DeleteDirectorCallback(p.Callback) +} + +func (p *goCallback) IsGoCallback() {} + +type overwrittenMethodsOnCallback struct { + p Callback +} + +func NewGoCallback() GoCallback { + om := &overwrittenMethodsOnCallback{} + p := NewDirectorCallback(om) + om.p = p + + return &goCallback{Callback: p} +} + +func DeleteGoCallback(p GoCallback) { + p.deleteCallback() +} + +func (p *goCallback) Run() { + fmt.Println("GoCallback.Run") +} diff --git a/Examples/go/callback/index.html b/Examples/go/callback/index.html new file mode 100644 index 000000000..9a53065b0 --- /dev/null +++ b/Examples/go/callback/index.html @@ -0,0 +1,31 @@ +<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. +See the <a href="../../../Doc/Manual/Go.html#Go_director_classes">Go Director +Classes</a> documentation subsection for an in-depth explanation how to use the +director feature. +</p> + +<p> +<ul> +<li><a href="example.h">example.h</a>. Header with the definition of the Caller and Callback classes. +<li><a href="example.i">example.i</a>. SWIG interface file. +<li><a href="gocallback.go">gocallback.go</a>. Go source with the definition of the GoCallback class. +<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..03ab0c5e2 --- /dev/null +++ b/Examples/go/callback/runme.go @@ -0,0 +1,33 @@ +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() + + go_callback := NewGoCallback() + + fmt.Println() + fmt.Println("Adding and calling a Go callback") + fmt.Println("--------------------------------") + + caller.SetCallback(go_callback) + caller.Call() + caller.DelCallback() + + DeleteGoCallback(go_callback) + + fmt.Println() + fmt.Println("Go exit") +} 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/director/Makefile b/Examples/go/director/Makefile index 84de5855d..2e9e87b89 100644 --- a/Examples/go/director/Makefile +++ b/Examples/go/director/Makefile @@ -1,7 +1,7 @@ TOP = ../.. SWIG = $(TOP)/../preinst-swig -CXXSRCS = -GOSRCS = example.go director.go # example.go gets generated by SWIG +CXXSRCS = +GOSRCS = director.go TARGET = example INTERFACE = example.i SWIGOPT = @@ -11,13 +11,14 @@ check: build build: if [ -n '$(SRCDIR)' ]; then \ - cp $(SRCDIR)/director.go .; \ + cp $(GOSRCS:%=$(SRCDIR)/%) .; \ fi - $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' GOSRCS='$(GOSRCS)' \ + @# Note: example.go gets generated by SWIG + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' GOSRCS='example.go $(GOSRCS)' \ SWIG='$(SWIG)' SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go_cpp clean: if [ -n '$(SRCDIR)' ]; then \ - rm director.go || true; \ + rm $(GOSRCS) || true; \ fi $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' INTERFACE='$(INTERFACE)' go_clean diff --git a/Examples/go/director/director.go b/Examples/go/director/director.go index a5078fe58..4f99bfc6d 100644 --- a/Examples/go/director/director.go +++ b/Examples/go/director/director.go @@ -1,70 +1,72 @@ package example -// FooBarGo is a superset of FooBarAbs and hence FooBarGo can be used as a drop -// in replacement for FooBarAbs but the reverse causes a compile time error. +// FooBarGo is a superset of FooBarAbstract and hence FooBarGo can be used as a +// drop in replacement for FooBarAbstract but the reverse causes a compile time +// error. type FooBarGo interface { - FooBarAbs - deleteFooBarAbs() + FooBarAbstract + deleteFooBarAbstract() IsFooBarGo() } -// Via embedding fooBarGo "inherits" all methods of FooBarAbs. +// Via embedding fooBarGo "inherits" all methods of FooBarAbstract. type fooBarGo struct { - FooBarAbs + FooBarAbstract } -func (fbgs *fooBarGo) deleteFooBarAbs() { - DeleteDirectorFooBarAbs(fbgs.FooBarAbs) +func (fbgs *fooBarGo) deleteFooBarAbstract() { + DeleteDirectorFooBarAbstract(fbgs.FooBarAbstract) } -// The IsFooBarGo method ensures that FooBarGo is a superset of FooBarAbs. +// The IsFooBarGo method ensures that FooBarGo is a superset of FooBarAbstract. // This is also how the class hierarchy gets represented by the SWIG generated -// wrapper code. For an instance FooBarCpp has the IsFooBarAbs and IsFooBarCpp -// methods. +// wrapper code. For an instance FooBarCpp has the IsFooBarAbstract and +// IsFooBarCpp methods. func (fbgs *fooBarGo) IsFooBarGo() {} // Go type that defines the DirectorInterface. It contains the Foo and Bar -// methods that overwrite the respective virtual C++ methods on FooBarAbs. -type overwrittenMethodsOnFooBarAbs struct { - // Backlink to FooBarAbs so that the rest of the class can be used by the - // overridden methods. - fb FooBarAbs +// methods that overwrite the respective virtual C++ methods on FooBarAbstract. +type overwrittenMethodsOnFooBarAbstract struct { + // Backlink to FooBarAbstract so that the rest of the class can be used by + // the overridden methods. + fb FooBarAbstract // If additional constructor arguments have been given they are typically // stored here so that the overriden methods can use them. } -func (om *overwrittenMethodsOnFooBarAbs) Foo() string { - // DirectorFooBarAbsFoo calls the base method FooBarAbs::Foo. - return "Go " + DirectorFooBarAbsFoo(om.fb) +func (om *overwrittenMethodsOnFooBarAbstract) Foo() string { + // DirectorFooBarAbstractFoo calls the base method FooBarAbstract::Foo. + return "Go " + DirectorFooBarAbstractFoo(om.fb) } -func (om *overwrittenMethodsOnFooBarAbs) Bar() string { +func (om *overwrittenMethodsOnFooBarAbstract) Bar() string { return "Go Bar" } func NewFooBarGo() FooBarGo { - // Instantiate FooBarAbs with selected methods overridden. The methods that - // will be overwritten are defined on overwrittenMethodsOnFooBarAbs and have - // a compatible signature to the respective virtual C++ methods. - // Furthermore additional constructor arguments will be typically stored in - // the overwrittenMethodsOnFooBarAbs struct. - om := &overwrittenMethodsOnFooBarAbs{} - fb := NewDirectorFooBarAbs(om) + // Instantiate FooBarAbstract with selected methods overridden. The methods + // that will be overwritten are defined on + // overwrittenMethodsOnFooBarAbstract and have a compatible signature to the + // respective virtual C++ methods. Furthermore additional constructor + // arguments will be typically stored in the + // overwrittenMethodsOnFooBarAbstract struct. + om := &overwrittenMethodsOnFooBarAbstract{} + fb := NewDirectorFooBarAbstract(om) om.fb = fb // Backlink causes cycle as fb.v = om! - fbgs := &fooBarGo{FooBarAbs: fb} - // The memory of the FooBarAbs director object instance can be automatically - // freed once the FooBarGo instance is garbage collected by uncommenting the - // following line. Please make sure to understand the runtime.SetFinalizer - // specific gotchas before doing this. Furthemore DeleteFooBarGo should be - // deleted if a finalizer is in use or the fooBarGo struct needs additional - // data to prevent double deletion. - // runtime.SetFinalizer(fbgs, FooBarGo.deleteFooBarAbs) + fbgs := &fooBarGo{FooBarAbstract: fb} + // The memory of the FooBarAbstract director object instance can be + // automatically freed once the FooBarGo instance is garbage collected by + // uncommenting the following line. Please make sure to understand the + // runtime.SetFinalizer specific gotchas before doing this. Furthemore + // DeleteFooBarGo should be deleted if a finalizer is in use or the fooBarGo + // struct needs additional data to prevent double deletion. + // runtime.SetFinalizer(fbgs, FooBarGo.deleteFooBarAbstract) return fbgs } // Recommended to be removed if runtime.SetFinalizer is in use. func DeleteFooBarGo(fbg FooBarGo) { - fbg.deleteFooBarAbs() + fbg.deleteFooBarAbstract() } diff --git a/Examples/go/director/director.h b/Examples/go/director/director.h index e08c11594..339a9adcd 100644 --- a/Examples/go/director/director.h +++ b/Examples/go/director/director.h @@ -6,11 +6,11 @@ #include <string> -class FooBarAbs +class FooBarAbstract { public: - FooBarAbs() {}; - virtual ~FooBarAbs() {}; + FooBarAbstract() {}; + virtual ~FooBarAbstract() {}; std::string FooBar() { return this->Foo() + ", " + this->Bar(); @@ -25,11 +25,11 @@ protected: }; -class FooBarCpp : public FooBarAbs +class FooBarCpp : public FooBarAbstract { protected: virtual std::string Foo() { - return "C++ " + FooBarAbs::Foo(); + return "C++ " + FooBarAbstract::Foo(); } virtual std::string Bar() { diff --git a/Examples/go/director/example.i b/Examples/go/director/example.i index b56998e6d..e832bd8c6 100644 --- a/Examples/go/director/example.i +++ b/Examples/go/director/example.i @@ -7,5 +7,5 @@ #include "director.h" %} -%feature("director") FooBarAbs; +%feature("director") FooBarAbstract; %include "director.h" diff --git a/Examples/go/director/index.html b/Examples/go/director/index.html index d1d5a74bc..b93e780e5 100644 --- a/Examples/go/director/index.html +++ b/Examples/go/director/index.html @@ -18,7 +18,7 @@ Classes</a> documentation subsection for an explanation of this example. <p> <ul> <li><a href="director.go">director.go</a>. Go source with the definition of the FooBarGo class. -<li><a href="director.h">director.h</a>. Header with the definition of the FooBarAbs and FooBarCpp classes. +<li><a href="director.h">director.h</a>. Header with the definition of the FooBarAbstract and FooBarCpp classes. <li><a href="example.i">example.i</a>. SWIG interface file. <li><a href="runme.go">runme.go</a>. Sample Go program. </ul> diff --git a/Examples/go/extend/Makefile b/Examples/go/extend/Makefile new file mode 100644 index 000000000..a9f2d8d7d --- /dev/null +++ b/Examples/go/extend/Makefile @@ -0,0 +1,24 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +CXXSRCS = extend.cxx +GOSRCS = ceo.go +TARGET = example +INTERFACE = example.i +SWIGOPT = + +check: build + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go_run + +build: + if [ -n '$(SRCDIR)' ]; then \ + cp $(GOSRCS:%=$(SRCDIR)/%) .; \ + fi + @# Note: example.go gets generated by SWIG + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' GOSRCS='example.go $(GOSRCS)' \ + SWIG='$(SWIG)' SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go_cpp + +clean: + if [ -n '$(SRCDIR)' ]; then \ + rm $(GOSRCS) || true; \ + fi + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' INTERFACE='$(INTERFACE)' go_clean diff --git a/Examples/go/extend/ceo.go b/Examples/go/extend/ceo.go new file mode 100644 index 000000000..8f00c92f2 --- /dev/null +++ b/Examples/go/extend/ceo.go @@ -0,0 +1,37 @@ +package example + +type CEO interface { + Manager + deleteManager() + IsCEO() +} + +type ceo struct { + Manager +} + +func (p *ceo) deleteManager() { + DeleteDirectorManager(p.Manager) +} + +func (p *ceo) IsCEO() {} + +type overwrittenMethodsOnManager struct { + p Manager +} + +func NewCEO(name string) CEO { + om := &overwrittenMethodsOnManager{} + p := NewDirectorManager(om, name) + om.p = p + + return &ceo{Manager: p} +} + +func DeleteCEO(p CEO) { + p.deleteManager() +} + +func (p *ceo) GetPosition() string { + return "CEO" +} diff --git a/Examples/go/extend/example.h b/Examples/go/extend/example.h new file mode 100644 index 000000000..0c3b721bd --- /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..31788b2aa --- /dev/null +++ b/Examples/go/extend/index.html @@ -0,0 +1,30 @@ +<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 how to inherit from a C++ class in Go. +See the <a href="../../../Doc/Manual/Go.html#Go_director_classes">Go Director +Classes</a> documentation subsection for an in-depth explanation how to use the +director feature. +<p> + +<ul> +<li><a href="ceo.go">ceo.go</a>. Go source with the definition of the CEO class. +<li><a href="example.h">example.h</a>. Header with the definition of the Employee, Manager and EmployeeList classes. +<li><a href="example.i">example.i</a>. SWIG 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..a56968937 --- /dev/null +++ b/Examples/go/extend/runme.go @@ -0,0 +1,66 @@ +// This file illustrates the cross language polymorphism using directors. + +package main + +import ( + . "./example" + "fmt" +) + +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 := NewCEO("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 Go 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 Go 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 and hence there is no need to + // call DeleteCEO. + DeleteEmployeeList(list) + fmt.Println("----------------------") + + // All done. + fmt.Println("Go exit") +} diff --git a/Examples/go/index.html b/Examples/go/index.html index b7d7017d3..467f4ecb7 100644 --- a/Examples/go/index.html +++ b/Examples/go/index.html @@ -21,6 +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="callback/index.html">callback</a>. C++ callbacks using directors. +<li><a href="extend/index.html">extend</a>. Polymorphism using directors. <li><a href="director/index.html">director</a>. Example how to utilize the director feature. </ul> |