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>
|
||||
|
||||
<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() {
|
||||
|
|
|
|||
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
|
||||
callback
|
||||
class
|
||||
constants
|
||||
director
|
||||
enum
|
||||
extend
|
||||
funcptr
|
||||
multimap
|
||||
pointer
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -7,5 +7,5 @@
|
|||
#include "director.h"
|
||||
%}
|
||||
|
||||
%feature("director") FooBarAbs;
|
||||
%feature("director") FooBarAbstract;
|
||||
%include "director.h"
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
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="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>
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue