Merge pull request #493 from michael-schaller/dir-examples
[Go] Undelete and updated the 'callback' and 'extend' examples.
This commit is contained in:
commit
01edfef3b8
22 changed files with 552 additions and 145 deletions
|
|
@ -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>
|
<H4><a name="Go_director_example_cpp_code"></a>23.4.7.1 Example C++ code</H4>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
The step by step guide is based on two example C++ classes. FooBarAbs is an
|
The step by step guide is based on two example C++ classes. FooBarAbstract is
|
||||||
abstract C++ class and the FooBarCpp class inherits from it. This guide
|
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.
|
explains how to implement a FooBarGo class similar to the FooBarCpp class.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<tt>FooBarAbs</tt> abstract C++ class:
|
<tt>FooBarAbstract</tt> abstract C++ class:
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div class="code">
|
<div class="code">
|
||||||
<pre>
|
<pre>
|
||||||
class FooBarAbs
|
class FooBarAbstract
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FooBarAbs() {};
|
FooBarAbstract() {};
|
||||||
virtual ~FooBarAbs() {};
|
virtual ~FooBarAbstract() {};
|
||||||
|
|
||||||
std::string FooBar() {
|
std::string FooBar() {
|
||||||
return this->Foo() + ", " + this->Bar();
|
return this->Foo() + ", " + this->Bar();
|
||||||
|
|
@ -643,11 +643,11 @@ protected:
|
||||||
|
|
||||||
<div class="code">
|
<div class="code">
|
||||||
<pre>
|
<pre>
|
||||||
class FooBarCpp : public FooBarAbs
|
class FooBarCpp : public FooBarAbstract
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
virtual std::string Foo() {
|
virtual std::string Foo() {
|
||||||
return "C++ " + FooBarAbs::Foo();
|
return "C++ " + FooBarAbstract::Foo();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual std::string Bar() {
|
virtual std::string Bar() {
|
||||||
|
|
@ -691,14 +691,14 @@ directive, like this:
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Second, you must use the %feature("director") directive to tell SWIG which
|
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
|
director feature enabled so that the FooBarGo class can inherit from it, like
|
||||||
this:
|
this:
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div class="code">
|
<div class="code">
|
||||||
<pre>
|
<pre>
|
||||||
%feature("director") FooBarAbs;
|
%feature("director") FooBarAbstract;
|
||||||
</pre>
|
</pre>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -782,21 +782,21 @@ As an example see part of the <tt>FooBarGo</tt> class:
|
||||||
|
|
||||||
<div class="code">
|
<div class="code">
|
||||||
<pre>
|
<pre>
|
||||||
type overwrittenMethodsOnFooBarAbs struct {
|
type overwrittenMethodsOnFooBarAbstract struct {
|
||||||
fb FooBarAbs
|
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 {
|
func NewFooBarGo() FooBarGo {
|
||||||
om := &overwrittenMethodsOnFooBarAbs{}
|
om := &overwrittenMethodsOnFooBarAbstract{}
|
||||||
fb := NewDirectorFooBarAbs(om)
|
fb := NewDirectorFooBarAbstract(om)
|
||||||
om.fb = fb
|
om.fb = fb
|
||||||
...
|
...
|
||||||
}
|
}
|
||||||
|
|
@ -806,25 +806,25 @@ func NewFooBarGo() FooBarGo {
|
||||||
<p>
|
<p>
|
||||||
The complete example, including the <tt>FooBarGoo</tt> class implementation, can
|
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
|
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
|
this part of the example the virtual methods <tt>FooBarAbstract::Foo</tt> and
|
||||||
<tt>FooBarAbs::Bar</tt> have been overwritten with Go methods similarly to how
|
<tt>FooBarAbstract::Bar</tt> have been overwritten with Go methods similarly to
|
||||||
the <tt>FooBarAbs</tt> virtual methods are overwritten by the <tt>FooBarCpp</tt>
|
how the <tt>FooBarAbstract</tt> virtual methods are overwritten by the
|
||||||
class.
|
<tt>FooBarCpp</tt> class.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
The <tt>DirectorInterface</tt> in the example is implemented by the
|
The <tt>DirectorInterface</tt> in the example is implemented by the
|
||||||
<tt>overwrittenMethodsOnFooBarAbs</tt> Go struct type. A pointer to a
|
<tt>overwrittenMethodsOnFooBarAbstract</tt> Go struct type. A pointer to a
|
||||||
<tt>overwrittenMethodsOnFooBarAbs</tt> struct instance will be given to the
|
<tt>overwrittenMethodsOnFooBarAbstract</tt> struct instance will be given to the
|
||||||
<tt>NewDirectorFooBarAbs</tt> constructor function. The constructor return
|
<tt>NewDirectorFooBarAbstract</tt> constructor function. The constructor return
|
||||||
value implements the <tt>FooBarAbs</tt> interface.
|
value implements the <tt>FooBarAbstract</tt> interface.
|
||||||
<tt>overwrittenMethodsOnFooBarAbs</tt> could in theory be any Go type but in
|
<tt>overwrittenMethodsOnFooBarAbstract</tt> could in theory be any Go type but
|
||||||
practice a struct is used as it typically contains at least a value of the
|
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 interface so that the overwritten methods can use the rest of the
|
||||||
C++ class. If the <tt>FooBarGo</tt> class would receive additional constructor
|
C++ class. If the <tt>FooBarGo</tt> class would receive additional constructor
|
||||||
arguments then these would also typically be stored in the
|
arguments then these would also typically be stored in the
|
||||||
<tt>overwrittenMethodsOnFooBarAbs</tt> struct so that they can be used by the
|
<tt>overwrittenMethodsOnFooBarAbstract</tt> struct so that they can be used by
|
||||||
Go methods.
|
the Go methods.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -840,7 +840,7 @@ the method in the base class. This is also the case for the
|
||||||
<div class="code">
|
<div class="code">
|
||||||
<pre>
|
<pre>
|
||||||
virtual std::string Foo() {
|
virtual std::string Foo() {
|
||||||
return "C++ " + FooBarAbs::Foo();
|
return "C++ " + FooBarAbstract::Foo();
|
||||||
}
|
}
|
||||||
</pre>
|
</pre>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -853,8 +853,8 @@ The <tt>FooBarGo.Foo</tt> implementation in the example looks like this:
|
||||||
|
|
||||||
<div class="code">
|
<div class="code">
|
||||||
<pre>
|
<pre>
|
||||||
func (om *overwrittenMethodsOnFooBarAbs) Foo() string {
|
func (om *overwrittenMethodsOnFooBarAbstract) Foo() string {
|
||||||
return "Go " + DirectorFooBarAbsFoo(om.fb)
|
return "Go " + DirectorFooBarAbstractFoo(om.fb)
|
||||||
}
|
}
|
||||||
</pre>
|
</pre>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -887,31 +887,31 @@ this:
|
||||||
<div class="code">
|
<div class="code">
|
||||||
<pre>
|
<pre>
|
||||||
type FooBarGo interface {
|
type FooBarGo interface {
|
||||||
FooBarAbs
|
FooBarAbstract
|
||||||
deleteFooBarAbs()
|
deleteFooBarAbstract()
|
||||||
IsFooBarGo()
|
IsFooBarGo()
|
||||||
}
|
}
|
||||||
|
|
||||||
type fooBarGo struct {
|
type fooBarGo struct {
|
||||||
FooBarAbs
|
FooBarAbstract
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fbgs *fooBarGo) deleteFooBarAbs() {
|
func (fbgs *fooBarGo) deleteFooBarAbstract() {
|
||||||
DeleteDirectorFooBarAbs(fbgs.FooBarAbs)
|
DeleteDirectorFooBarAbstract(fbgs.FooBarAbstract)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fbgs *fooBarGo) IsFooBarGo() {}
|
func (fbgs *fooBarGo) IsFooBarGo() {}
|
||||||
|
|
||||||
func NewFooBarGo() FooBarGo {
|
func NewFooBarGo() FooBarGo {
|
||||||
om := &overwrittenMethodsOnFooBarAbs{}
|
om := &overwrittenMethodsOnFooBarAbstract{}
|
||||||
fb := NewDirectorFooBarAbs(om)
|
fb := NewDirectorFooBarAbstract(om)
|
||||||
om.fb = fb
|
om.fb = fb
|
||||||
|
|
||||||
return &fooBarGo{FooBarAbs: fb}
|
return &fooBarGo{FooBarAbstract: fb}
|
||||||
}
|
}
|
||||||
|
|
||||||
func DeleteFooBarGo(fbg FooBarGo) {
|
func DeleteFooBarGo(fbg FooBarGo) {
|
||||||
fbg.deleteFooBarAbs()
|
fbg.deleteFooBarAbstract()
|
||||||
}
|
}
|
||||||
</pre>
|
</pre>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -921,12 +921,12 @@ func DeleteFooBarGo(fbg FooBarGo) {
|
||||||
The complete example, including the <tt>FooBarGoo</tt> class implementation, can
|
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
|
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>
|
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
|
FooBarAbstract</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
|
methods of the <tt>FooBarAbstract</tt> C++ class by means of embedding. The
|
||||||
<tt>FooBarGo</tt> interface type includes the <tt>FooBarAbs</tt> interface and
|
public <tt>FooBarGo</tt> interface type includes the <tt>FooBarAbstract</tt>
|
||||||
hence <tt>FooBarGo</tt> can be used as a drop in replacement for
|
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
|
<tt>FooBarAbstract</tt> while the reverse isn't possible and would raise a
|
||||||
time error. Furthemore the constructor and destructor functions <tt>
|
compile time error. Furthemore the constructor and destructor functions <tt>
|
||||||
NewFooBarGo</tt> and <tt>DeleteFooBarGo</tt> take care of all the director
|
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++
|
specifics and to the user the class appears as any other SWIG wrapped C++
|
||||||
class.
|
class.
|
||||||
|
|
@ -946,13 +946,13 @@ in the <tt>FooBarGo</tt> class is here:
|
||||||
|
|
||||||
<div class="code">
|
<div class="code">
|
||||||
<pre>
|
<pre>
|
||||||
type overwrittenMethodsOnFooBarAbs struct {
|
type overwrittenMethodsOnFooBarAbstract struct {
|
||||||
fb FooBarAbs
|
fb FooBarAbstract
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewFooBarGo() FooBarGo {
|
func NewFooBarGo() FooBarGo {
|
||||||
om := &overwrittenMethodsOnFooBarAbs{}
|
om := &overwrittenMethodsOnFooBarAbstract{}
|
||||||
fb := NewDirectorFooBarAbs(om) // fb.v = om
|
fb := NewDirectorFooBarAbstract(om) // fb.v = om
|
||||||
om.fb = fb // Backlink causes cycle as 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
|
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
|
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>
|
the director object instance. In the <tt>FooBarGo</tt> class example the <tt>
|
||||||
FooBarAbs</tt> director instance can be automatically deleted by setting the
|
FooBarAbstract</tt> director instance can be automatically deleted by setting
|
||||||
finalizer on <tt>fooBarGo</tt>:
|
the finalizer on <tt>fooBarGo</tt>:
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div class="code">
|
<div class="code">
|
||||||
<pre>
|
<pre>
|
||||||
type fooBarGo struct {
|
type fooBarGo struct {
|
||||||
FooBarAbs
|
FooBarAbstract
|
||||||
}
|
}
|
||||||
|
|
||||||
type overwrittenMethodsOnFooBarAbs struct {
|
type overwrittenMethodsOnFooBarAbstract struct {
|
||||||
fb FooBarAbs
|
fb FooBarAbstract
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewFooBarGo() FooBarGo {
|
func NewFooBarGo() FooBarGo {
|
||||||
om := &overwrittenMethodsOnFooBarAbs{}
|
om := &overwrittenMethodsOnFooBarAbstract{}
|
||||||
fb := NewDirectorFooBarAbs(om)
|
fb := NewDirectorFooBarAbstract(om)
|
||||||
om.fb = fb // Backlink causes cycle as fb.v = om!
|
om.fb = fb // Backlink causes cycle as fb.v = om!
|
||||||
|
|
||||||
fbgs := &fooBarGo{FooBarAbs: fb}
|
fbgs := &fooBarGo{FooBarAbstract: fb}
|
||||||
runtime.SetFinalizer(fbgs, FooBarGo.deleteFooBarAbs)
|
runtime.SetFinalizer(fbgs, FooBarGo.deleteFooBarAbstract)
|
||||||
return fbgs
|
return fbgs
|
||||||
}
|
}
|
||||||
</pre>
|
</pre>
|
||||||
|
|
@ -1007,73 +1007,75 @@ The complete and annotated <tt>FooBarGo</tt> class looks like this:
|
||||||
|
|
||||||
<div class="code">
|
<div class="code">
|
||||||
<pre>
|
<pre>
|
||||||
// FooBarGo is a superset of FooBarAbs and hence FooBarGo can be used as a drop
|
// FooBarGo is a superset of FooBarAbstract and hence FooBarGo can be used as a
|
||||||
// in replacement for FooBarAbs but the reverse causes a compile time error.
|
// drop in replacement for FooBarAbstract but the reverse causes a compile time
|
||||||
|
// error.
|
||||||
type FooBarGo interface {
|
type FooBarGo interface {
|
||||||
FooBarAbs
|
FooBarAbstract
|
||||||
deleteFooBarAbs()
|
deleteFooBarAbstract()
|
||||||
IsFooBarGo()
|
IsFooBarGo()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Via embedding fooBarGo "inherits" all methods of FooBarAbs.
|
// Via embedding fooBarGo "inherits" all methods of FooBarAbstract.
|
||||||
type fooBarGo struct {
|
type fooBarGo struct {
|
||||||
FooBarAbs
|
FooBarAbstract
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fbgs *fooBarGo) deleteFooBarAbs() {
|
func (fbgs *fooBarGo) deleteFooBarAbstract() {
|
||||||
DeleteDirectorFooBarAbs(fbgs.FooBarAbs)
|
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
|
// This is also how the class hierarchy gets represented by the SWIG generated
|
||||||
// wrapper code. For an instance FooBarCpp has the IsFooBarAbs and IsFooBarCpp
|
// wrapper code. For an instance FooBarCpp has the IsFooBarAbstract and
|
||||||
// methods.
|
// IsFooBarCpp methods.
|
||||||
func (fbgs *fooBarGo) IsFooBarGo() {}
|
func (fbgs *fooBarGo) IsFooBarGo() {}
|
||||||
|
|
||||||
// Go type that defines the DirectorInterface. It contains the Foo and Bar
|
// Go type that defines the DirectorInterface. It contains the Foo and Bar
|
||||||
// methods that overwrite the respective virtual C++ methods on FooBarAbs.
|
// methods that overwrite the respective virtual C++ methods on FooBarAbstract.
|
||||||
type overwrittenMethodsOnFooBarAbs struct {
|
type overwrittenMethodsOnFooBarAbstract struct {
|
||||||
// Backlink to FooBarAbs so that the rest of the class can be used by the
|
// Backlink to FooBarAbstract so that the rest of the class can be used by
|
||||||
// overridden methods.
|
// the overridden methods.
|
||||||
fb FooBarAbs
|
fb FooBarAbstract
|
||||||
|
|
||||||
// If additional constructor arguments have been given they are typically
|
// If additional constructor arguments have been given they are typically
|
||||||
// stored here so that the overriden methods can use them.
|
// stored here so that the overriden methods can use them.
|
||||||
}
|
}
|
||||||
|
|
||||||
func (om *overwrittenMethodsOnFooBarAbs) Foo() string {
|
func (om *overwrittenMethodsOnFooBarAbstract) Foo() string {
|
||||||
// DirectorFooBarAbsFoo calls the base method FooBarAbs::Foo.
|
// DirectorFooBarAbstractFoo calls the base method FooBarAbstract::Foo.
|
||||||
return "Go " + DirectorFooBarAbsFoo(om.fb)
|
return "Go " + DirectorFooBarAbstractFoo(om.fb)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (om *overwrittenMethodsOnFooBarAbs) Bar() string {
|
func (om *overwrittenMethodsOnFooBarAbstract) Bar() string {
|
||||||
return "Go Bar"
|
return "Go Bar"
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewFooBarGo() FooBarGo {
|
func NewFooBarGo() FooBarGo {
|
||||||
// Instantiate FooBarAbs with selected methods overridden. The methods that
|
// Instantiate FooBarAbstract with selected methods overridden. The methods
|
||||||
// will be overwritten are defined on overwrittenMethodsOnFooBarAbs and have
|
// that will be overwritten are defined on
|
||||||
// a compatible signature to the respective virtual C++ methods.
|
// overwrittenMethodsOnFooBarAbstract and have a compatible signature to the
|
||||||
// Furthermore additional constructor arguments will be typically stored in
|
// respective virtual C++ methods. Furthermore additional constructor
|
||||||
// the overwrittenMethodsOnFooBarAbs struct.
|
// arguments will be typically stored in the
|
||||||
om := &overwrittenMethodsOnFooBarAbs{}
|
// overwrittenMethodsOnFooBarAbstract struct.
|
||||||
fb := NewDirectorFooBarAbs(om)
|
om := &overwrittenMethodsOnFooBarAbstract{}
|
||||||
|
fb := NewDirectorFooBarAbstract(om)
|
||||||
om.fb = fb // Backlink causes cycle as fb.v = om!
|
om.fb = fb // Backlink causes cycle as fb.v = om!
|
||||||
|
|
||||||
fbgs := &fooBarGo{FooBarAbs: fb}
|
fbgs := &fooBarGo{FooBarAbstract: fb}
|
||||||
// The memory of the FooBarAbs director object instance can be automatically
|
// The memory of the FooBarAbstract director object instance can be
|
||||||
// freed once the FooBarGo instance is garbage collected by uncommenting the
|
// automatically freed once the FooBarGo instance is garbage collected by
|
||||||
// following line. Please make sure to understand the runtime.SetFinalizer
|
// uncommenting the following line. Please make sure to understand the
|
||||||
// specific gotchas before doing this. Furthemore DeleteFooBarGo should be
|
// runtime.SetFinalizer specific gotchas before doing this. Furthemore
|
||||||
// deleted if a finalizer is in use or the fooBarGo struct needs additional
|
// DeleteFooBarGo should be deleted if a finalizer is in use or the fooBarGo
|
||||||
// data to prevent double deletion.
|
// struct needs additional data to prevent double deletion.
|
||||||
// runtime.SetFinalizer(fbgs, FooBarGo.deleteFooBarAbs)
|
// runtime.SetFinalizer(fbgs, FooBarGo.deleteFooBarAbstract)
|
||||||
return fbgs
|
return fbgs
|
||||||
}
|
}
|
||||||
|
|
||||||
// Recommended to be removed if runtime.SetFinalizer is in use.
|
// Recommended to be removed if runtime.SetFinalizer is in use.
|
||||||
func DeleteFooBarGo(fbg FooBarGo) {
|
func DeleteFooBarGo(fbg FooBarGo) {
|
||||||
fbg.deleteFooBarAbs()
|
fbg.deleteFooBarAbstract()
|
||||||
}
|
}
|
||||||
</pre>
|
</pre>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -1094,11 +1096,11 @@ For comparison the <tt>FooBarCpp</tt> class looks like this:
|
||||||
|
|
||||||
<div class="code">
|
<div class="code">
|
||||||
<pre>
|
<pre>
|
||||||
class FooBarCpp : public FooBarAbs
|
class FooBarCpp : public FooBarAbstract
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
virtual std::string Foo() {
|
virtual std::string Foo() {
|
||||||
return "C++ " + FooBarAbs::Foo();
|
return "C++ " + FooBarAbstract::Foo();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual std::string Bar() {
|
virtual std::string Bar() {
|
||||||
|
|
|
||||||
24
Examples/go/callback/Makefile
Normal file
24
Examples/go/callback/Makefile
Normal file
|
|
@ -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
|
||||||
4
Examples/go/callback/callback.cxx
Normal file
4
Examples/go/callback/callback.cxx
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
/* File : example.cxx */
|
||||||
|
|
||||||
|
#include "example.h"
|
||||||
|
|
||||||
22
Examples/go/callback/example.h
Normal file
22
Examples/go/callback/example.h
Normal file
|
|
@ -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(); }
|
||||||
|
};
|
||||||
11
Examples/go/callback/example.i
Normal file
11
Examples/go/callback/example.i
Normal file
|
|
@ -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"
|
||||||
|
|
||||||
41
Examples/go/callback/gocallback.go
Normal file
41
Examples/go/callback/gocallback.go
Normal file
|
|
@ -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")
|
||||||
|
}
|
||||||
31
Examples/go/callback/index.html
Normal file
31
Examples/go/callback/index.html
Normal file
|
|
@ -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>
|
||||||
33
Examples/go/callback/runme.go
Normal file
33
Examples/go/callback/runme.go
Normal file
|
|
@ -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")
|
||||||
|
}
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
# see top-level Makefile.in
|
# see top-level Makefile.in
|
||||||
|
callback
|
||||||
class
|
class
|
||||||
constants
|
constants
|
||||||
director
|
director
|
||||||
enum
|
enum
|
||||||
|
extend
|
||||||
funcptr
|
funcptr
|
||||||
multimap
|
multimap
|
||||||
pointer
|
pointer
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
TOP = ../..
|
TOP = ../..
|
||||||
SWIG = $(TOP)/../preinst-swig
|
SWIG = $(TOP)/../preinst-swig
|
||||||
CXXSRCS =
|
CXXSRCS =
|
||||||
GOSRCS = example.go director.go # example.go gets generated by SWIG
|
GOSRCS = director.go
|
||||||
TARGET = example
|
TARGET = example
|
||||||
INTERFACE = example.i
|
INTERFACE = example.i
|
||||||
SWIGOPT =
|
SWIGOPT =
|
||||||
|
|
@ -11,13 +11,14 @@ check: build
|
||||||
|
|
||||||
build:
|
build:
|
||||||
if [ -n '$(SRCDIR)' ]; then \
|
if [ -n '$(SRCDIR)' ]; then \
|
||||||
cp $(SRCDIR)/director.go .; \
|
cp $(GOSRCS:%=$(SRCDIR)/%) .; \
|
||||||
fi
|
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
|
SWIG='$(SWIG)' SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go_cpp
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
if [ -n '$(SRCDIR)' ]; then \
|
if [ -n '$(SRCDIR)' ]; then \
|
||||||
rm director.go || true; \
|
rm $(GOSRCS) || true; \
|
||||||
fi
|
fi
|
||||||
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' INTERFACE='$(INTERFACE)' go_clean
|
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' INTERFACE='$(INTERFACE)' go_clean
|
||||||
|
|
|
||||||
|
|
@ -1,70 +1,72 @@
|
||||||
package example
|
package example
|
||||||
|
|
||||||
// FooBarGo is a superset of FooBarAbs and hence FooBarGo can be used as a drop
|
// FooBarGo is a superset of FooBarAbstract and hence FooBarGo can be used as a
|
||||||
// in replacement for FooBarAbs but the reverse causes a compile time error.
|
// drop in replacement for FooBarAbstract but the reverse causes a compile time
|
||||||
|
// error.
|
||||||
type FooBarGo interface {
|
type FooBarGo interface {
|
||||||
FooBarAbs
|
FooBarAbstract
|
||||||
deleteFooBarAbs()
|
deleteFooBarAbstract()
|
||||||
IsFooBarGo()
|
IsFooBarGo()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Via embedding fooBarGo "inherits" all methods of FooBarAbs.
|
// Via embedding fooBarGo "inherits" all methods of FooBarAbstract.
|
||||||
type fooBarGo struct {
|
type fooBarGo struct {
|
||||||
FooBarAbs
|
FooBarAbstract
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fbgs *fooBarGo) deleteFooBarAbs() {
|
func (fbgs *fooBarGo) deleteFooBarAbstract() {
|
||||||
DeleteDirectorFooBarAbs(fbgs.FooBarAbs)
|
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
|
// This is also how the class hierarchy gets represented by the SWIG generated
|
||||||
// wrapper code. For an instance FooBarCpp has the IsFooBarAbs and IsFooBarCpp
|
// wrapper code. For an instance FooBarCpp has the IsFooBarAbstract and
|
||||||
// methods.
|
// IsFooBarCpp methods.
|
||||||
func (fbgs *fooBarGo) IsFooBarGo() {}
|
func (fbgs *fooBarGo) IsFooBarGo() {}
|
||||||
|
|
||||||
// Go type that defines the DirectorInterface. It contains the Foo and Bar
|
// Go type that defines the DirectorInterface. It contains the Foo and Bar
|
||||||
// methods that overwrite the respective virtual C++ methods on FooBarAbs.
|
// methods that overwrite the respective virtual C++ methods on FooBarAbstract.
|
||||||
type overwrittenMethodsOnFooBarAbs struct {
|
type overwrittenMethodsOnFooBarAbstract struct {
|
||||||
// Backlink to FooBarAbs so that the rest of the class can be used by the
|
// Backlink to FooBarAbstract so that the rest of the class can be used by
|
||||||
// overridden methods.
|
// the overridden methods.
|
||||||
fb FooBarAbs
|
fb FooBarAbstract
|
||||||
|
|
||||||
// If additional constructor arguments have been given they are typically
|
// If additional constructor arguments have been given they are typically
|
||||||
// stored here so that the overriden methods can use them.
|
// stored here so that the overriden methods can use them.
|
||||||
}
|
}
|
||||||
|
|
||||||
func (om *overwrittenMethodsOnFooBarAbs) Foo() string {
|
func (om *overwrittenMethodsOnFooBarAbstract) Foo() string {
|
||||||
// DirectorFooBarAbsFoo calls the base method FooBarAbs::Foo.
|
// DirectorFooBarAbstractFoo calls the base method FooBarAbstract::Foo.
|
||||||
return "Go " + DirectorFooBarAbsFoo(om.fb)
|
return "Go " + DirectorFooBarAbstractFoo(om.fb)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (om *overwrittenMethodsOnFooBarAbs) Bar() string {
|
func (om *overwrittenMethodsOnFooBarAbstract) Bar() string {
|
||||||
return "Go Bar"
|
return "Go Bar"
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewFooBarGo() FooBarGo {
|
func NewFooBarGo() FooBarGo {
|
||||||
// Instantiate FooBarAbs with selected methods overridden. The methods that
|
// Instantiate FooBarAbstract with selected methods overridden. The methods
|
||||||
// will be overwritten are defined on overwrittenMethodsOnFooBarAbs and have
|
// that will be overwritten are defined on
|
||||||
// a compatible signature to the respective virtual C++ methods.
|
// overwrittenMethodsOnFooBarAbstract and have a compatible signature to the
|
||||||
// Furthermore additional constructor arguments will be typically stored in
|
// respective virtual C++ methods. Furthermore additional constructor
|
||||||
// the overwrittenMethodsOnFooBarAbs struct.
|
// arguments will be typically stored in the
|
||||||
om := &overwrittenMethodsOnFooBarAbs{}
|
// overwrittenMethodsOnFooBarAbstract struct.
|
||||||
fb := NewDirectorFooBarAbs(om)
|
om := &overwrittenMethodsOnFooBarAbstract{}
|
||||||
|
fb := NewDirectorFooBarAbstract(om)
|
||||||
om.fb = fb // Backlink causes cycle as fb.v = om!
|
om.fb = fb // Backlink causes cycle as fb.v = om!
|
||||||
|
|
||||||
fbgs := &fooBarGo{FooBarAbs: fb}
|
fbgs := &fooBarGo{FooBarAbstract: fb}
|
||||||
// The memory of the FooBarAbs director object instance can be automatically
|
// The memory of the FooBarAbstract director object instance can be
|
||||||
// freed once the FooBarGo instance is garbage collected by uncommenting the
|
// automatically freed once the FooBarGo instance is garbage collected by
|
||||||
// following line. Please make sure to understand the runtime.SetFinalizer
|
// uncommenting the following line. Please make sure to understand the
|
||||||
// specific gotchas before doing this. Furthemore DeleteFooBarGo should be
|
// runtime.SetFinalizer specific gotchas before doing this. Furthemore
|
||||||
// deleted if a finalizer is in use or the fooBarGo struct needs additional
|
// DeleteFooBarGo should be deleted if a finalizer is in use or the fooBarGo
|
||||||
// data to prevent double deletion.
|
// struct needs additional data to prevent double deletion.
|
||||||
// runtime.SetFinalizer(fbgs, FooBarGo.deleteFooBarAbs)
|
// runtime.SetFinalizer(fbgs, FooBarGo.deleteFooBarAbstract)
|
||||||
return fbgs
|
return fbgs
|
||||||
}
|
}
|
||||||
|
|
||||||
// Recommended to be removed if runtime.SetFinalizer is in use.
|
// Recommended to be removed if runtime.SetFinalizer is in use.
|
||||||
func DeleteFooBarGo(fbg FooBarGo) {
|
func DeleteFooBarGo(fbg FooBarGo) {
|
||||||
fbg.deleteFooBarAbs()
|
fbg.deleteFooBarAbstract()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,11 +6,11 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
|
||||||
class FooBarAbs
|
class FooBarAbstract
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FooBarAbs() {};
|
FooBarAbstract() {};
|
||||||
virtual ~FooBarAbs() {};
|
virtual ~FooBarAbstract() {};
|
||||||
|
|
||||||
std::string FooBar() {
|
std::string FooBar() {
|
||||||
return this->Foo() + ", " + this->Bar();
|
return this->Foo() + ", " + this->Bar();
|
||||||
|
|
@ -25,11 +25,11 @@ protected:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class FooBarCpp : public FooBarAbs
|
class FooBarCpp : public FooBarAbstract
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
virtual std::string Foo() {
|
virtual std::string Foo() {
|
||||||
return "C++ " + FooBarAbs::Foo();
|
return "C++ " + FooBarAbstract::Foo();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual std::string Bar() {
|
virtual std::string Bar() {
|
||||||
|
|
|
||||||
|
|
@ -7,5 +7,5 @@
|
||||||
#include "director.h"
|
#include "director.h"
|
||||||
%}
|
%}
|
||||||
|
|
||||||
%feature("director") FooBarAbs;
|
%feature("director") FooBarAbstract;
|
||||||
%include "director.h"
|
%include "director.h"
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ Classes</a> documentation subsection for an explanation of this example.
|
||||||
<p>
|
<p>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="director.go">director.go</a>. Go source with the definition of the FooBarGo class.
|
<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="example.i">example.i</a>. SWIG interface file.
|
||||||
<li><a href="runme.go">runme.go</a>. Sample Go program.
|
<li><a href="runme.go">runme.go</a>. Sample Go program.
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
||||||
24
Examples/go/extend/Makefile
Normal file
24
Examples/go/extend/Makefile
Normal file
|
|
@ -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
|
||||||
37
Examples/go/extend/ceo.go
Normal file
37
Examples/go/extend/ceo.go
Normal file
|
|
@ -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"
|
||||||
|
}
|
||||||
56
Examples/go/extend/example.h
Normal file
56
Examples/go/extend/example.h
Normal file
|
|
@ -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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
15
Examples/go/extend/example.i
Normal file
15
Examples/go/extend/example.i
Normal file
|
|
@ -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"
|
||||||
|
|
||||||
4
Examples/go/extend/extend.cxx
Normal file
4
Examples/go/extend/extend.cxx
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
/* File : example.cxx */
|
||||||
|
|
||||||
|
#include "example.h"
|
||||||
|
|
||||||
30
Examples/go/extend/index.html
Normal file
30
Examples/go/extend/index.html
Normal file
|
|
@ -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>
|
||||||
66
Examples/go/extend/runme.go
Normal file
66
Examples/go/extend/runme.go
Normal file
|
|
@ -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")
|
||||||
|
}
|
||||||
|
|
@ -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="pointer/index.html">pointer</a>. Simple pointer handling.
|
||||||
<li><a href="funcptr/index.html">funcptr</a>. Pointers to functions.
|
<li><a href="funcptr/index.html">funcptr</a>. Pointers to functions.
|
||||||
<li><a href="template/index.html">template</a>. C++ templates.
|
<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.
|
<li><a href="director/index.html">director</a>. Example how to utilize the director feature.
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue