summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilliam S Fulton <wsf@fultondesigns.co.uk>2015-08-12 18:30:49 +0100
committerWilliam S Fulton <wsf@fultondesigns.co.uk>2015-08-12 18:30:49 +0100
commit4de4123b6a990b0e6747499cb6b3d0c14643876f (patch)
tree19ddd198af1859705da972bb2984123991212d15
parent5817a1163dd3ec01cbcd2c314484d69f7e4e27cf (diff)
parent9aa0f85cdacff59180cde416d5b10406cff1bda1 (diff)
downloadswig-travis-osx.tar.gz
Merge branch 'master' into travis-osxtravis-osx
* master: Workaround Appveyor random failures due to nuget install errors Revert "Merge pull request #494 from richardbeare/enumR2015B" This is a modification to support use of tricky enumerations in R. It includes the addition of a _runme for an existing test - preproc_constants that was previously not run. That tests includes a preprocessor based setting of an enumeration which is ignored by the existing r enumeration infrastructure. The new version correctly reports the enumeration value as 4 - previous versions set it to 0. Traditional enumerations are unchanged. [Go] Renamed 'FooBarAbs' to 'FooBarAbstract' in the documentation and examples. [Go] Updated the 'callback' and 'extend' examples to match the 'director' one. [Go] Revert commit 5e88857 to undelete the 'callback' and 'extend' examples. update CHANGES.current check ranges in perlprimtype.swg more carefully to avoid clang warnings capture the current behavior of perlprimtypes.swg is more detail Changes entry for numpydoc conforming docstrings. pep257 & numpydoc conforming docstrings Make (char*, size_t) typemap usable for strings of other types in Java. [Go] update build instructions in Examples/go/index.html [Go] Documentation cleanup of obsolete 'callback' and 'extend' examples. Some minor changes after first code review by ianlancetaylor. Fixed Examples/go/director/Makefile as there might be no copy of director.go during clean if a separate build directory is in use. Fixed Examples/go/director/Makefile as the copy of director.go wasn't cleaned up in separate build directories. Fixed Examples/go/director/Makefile as director.go was missing in separate build directories. Removed empty line in table of contents of the Go documentation. Fleshed out Go's documentation about the director feature and added a director example. Bump version to 3.0.8 Update Scilab test-suite output wording Add 3.0.7 release summary and release date Test case warning suppression for visual c++ fix
-rw-r--r--ANNOUNCE13
-rw-r--r--CHANGES117
-rw-r--r--CHANGES.current126
-rw-r--r--Doc/Manual/Go.html554
-rw-r--r--Doc/Manual/Python.html37
-rw-r--r--Doc/Manual/Sections.html2
-rw-r--r--Examples/go/callback/Makefile12
-rw-r--r--Examples/go/callback/example.h1
-rw-r--r--Examples/go/callback/gocallback.go41
-rw-r--r--Examples/go/callback/index.html64
-rw-r--r--Examples/go/callback/runme.go16
-rw-r--r--Examples/go/check.list1
-rw-r--r--Examples/go/director/Makefile24
-rw-r--r--Examples/go/director/director.go72
-rw-r--r--Examples/go/director/director.h41
-rw-r--r--Examples/go/director/example.i11
-rw-r--r--Examples/go/director/index.html28
-rw-r--r--Examples/go/director/runme.go39
-rw-r--r--Examples/go/extend/Makefile12
-rw-r--r--Examples/go/extend/ceo.go37
-rw-r--r--Examples/go/extend/example.h2
-rw-r--r--Examples/go/extend/index.html13
-rw-r--r--Examples/go/extend/runme.go20
-rw-r--r--Examples/go/index.html45
-rw-r--r--Examples/test-suite/array_typedef_memberin.i8
-rw-r--r--Examples/test-suite/autodoc.i4
-rw-r--r--Examples/test-suite/char_binary.i4
-rw-r--r--Examples/test-suite/java/char_binary_runme.java6
-rw-r--r--Examples/test-suite/javascript/char_binary_runme.js10
-rw-r--r--Examples/test-suite/perl5/char_binary_runme.pl5
-rw-r--r--Examples/test-suite/perl5/overload_simple_runme.pl39
-rw-r--r--Examples/test-suite/perl5/wrapmacro_runme.pl43
-rw-r--r--Examples/test-suite/python/autodoc_runme.py222
-rw-r--r--Examples/test-suite/python/char_binary_runme.py7
-rw-r--r--Examples/test-suite/scilab/Makefile.in4
-rw-r--r--Lib/java/java.swg4
-rw-r--r--Lib/perl5/perlprimtypes.swg31
-rw-r--r--README2
-rw-r--r--RELEASENOTES8
-rw-r--r--Source/Modules/python.cxx17
-rw-r--r--Tools/nuget-install.cmd28
-rw-r--r--appveyor.yml2
-rw-r--r--configure.ac2
43 files changed, 1370 insertions, 404 deletions
diff --git a/ANNOUNCE b/ANNOUNCE
index f7d7eb8a9..d9b932e2c 100644
--- a/ANNOUNCE
+++ b/ANNOUNCE
@@ -1,8 +1,8 @@
-*** ANNOUNCE: SWIG 3.0.7 (in progress) ***
+*** ANNOUNCE: SWIG 3.0.8 (in progress) ***
http://www.swig.org
-We're pleased to announce SWIG-3.0.7, the latest SWIG release.
+We're pleased to announce SWIG-3.0.8, the latest SWIG release.
What is SWIG?
=============
@@ -18,15 +18,20 @@ include generation of scripting language extension modules, rapid
prototyping, testing, and user interface development for large
C/C++ systems.
+Release Notes
+=============
+Detailed release notes are available with the release and are also
+published on the SWIG web site at http://swig.org/release.html.
+
Availability
============
The release is available for download on Sourceforge at
- http://prdownloads.sourceforge.net/swig/swig-3.0.7.tar.gz
+ http://prdownloads.sourceforge.net/swig/swig-3.0.8.tar.gz
A Windows version is also available at
- http://prdownloads.sourceforge.net/swig/swigwin-3.0.7.zip
+ http://prdownloads.sourceforge.net/swig/swigwin-3.0.8.zip
Please report problems with this release to the swig-devel mailing list,
details at http://www.swig.org/mail.html.
diff --git a/CHANGES b/CHANGES
index 691fa5544..29b36352c 100644
--- a/CHANGES
+++ b/CHANGES
@@ -3,6 +3,123 @@ SWIG (Simplified Wrapper and Interface Generator)
See the CHANGES.current file for changes in the current version.
See the RELEASENOTES file for a summary of changes in each release.
+Version 3.0.7 (3 Aug 2015)
+==========================
+
+2015-08-02: wsfulton
+ [Java] Fix potential security exploit in generated Java classes.
+ The swigCPtr and swigCMemOwn member variables in the generated Java
+ classes are now declared 'transient' by default. Further details of the exploit
+ in Android is being published in an academic paper as part of USENIX WOOT '15:
+ https://www.usenix.org/conference/woot15/workshop-program/presentation/peles.
+
+ In the unlikely event that you are relying on these members being serializable,
+ then you will need to override the default javabody and javabody_derived typemaps
+ to generate the old generated code. The relevant typemaps are in the Lib directory
+ in the java.swg, boost_shared_ptr.i and boost_intrusive_ptr.i files. Copy the
+ relevant default typemaps into your interface file and remove the 'transient' keyword.
+
+ *** POTENTIAL INCOMPATIBILITY ***
+
+2015-08-01: vadz
+ Make configure --without-alllang option more useful: it can now be overridden by the following
+ --with-xxx options, allowing to easily enable just one or two languages.
+
+2015-07-30: wsfulton
+ Fix #440 - Initialise all newly created arrays when using %array_functions and %array_class
+ in the carrays.i library - bug is only relevant when using C++.
+
+2015-07-29: wsfulton
+ [Python] Improve indentation warning and error messages for code in the following directives:
+
+ %pythonprepend
+ %pythonappend
+ %pythoncode
+ %pythonbegin
+ %feature("shadow")
+
+ Old error example:
+ Error: Line indented less than expected (line 3 of pythoncode)
+
+ New error example:
+ Error: Line indented less than expected (line 3 of %pythoncode or %insert("python") block)
+ as no line should be indented less than the indentation in line 1
+
+ Old warning example:
+ Warning 740: Whitespace prefix doesn't match (line 2 of %pythoncode or %insert("python") block)
+
+ New warning example:
+ Warning 740: Whitespace indentation is inconsistent compared to earlier lines (line 3 of
+ %pythoncode or %insert("python") block)
+
+
+2015-07-28: wsfulton
+ [Python] Fix #475. Improve docstring indentation handling.
+
+ SWIG-3.0.5 and earlier sometimes truncated text provided in the docstring feature.
+ This occurred when the indentation (whitespace) in the docstring was less in the
+ second or later lines when compared to the first line.
+ SWIG-3.0.6 gave a 'Line indented less than expected' error instead of truncating
+ the docstring text.
+ Now the indentation for the 'docstring' feature is smarter and is appropriately
+ adjusted so that no truncation occurs.
+
+2015-07-22: wsfulton
+ Support for special variable expansion in typemap attributes. Example usage expansion
+ in the 'out' attribute (C# specific):
+
+ %typemap(ctype, out="$*1_ltype") unsigned int& "$*1_ltype"
+
+ is equivalent to the following as $*1_ltype expands to 'unsigned int':
+
+ %typemap(ctype, out="unsigned int") unsigned int& "unsigned int"
+
+ Special variables can be used within special variable macros too. Example usage expansion:
+
+ %typemap(cstype) unsigned int "uint"
+ %typemap(cstype, out="$typemap(cstype, $*1_ltype)") unsigned int& "$typemap(cstype, $*1_ltype)"
+
+ Special variables are expanded first and hence the above is equivalent to:
+
+ %typemap(cstype, out="$typemap(cstype, unsigned int)") unsigned int& "$typemap(cstype, unsigned int)"
+
+ which then expands to:
+
+ %typemap(cstype, out="uint") unsigned int& "uint"
+
+2015-07-22: lindleyf
+ Apply patch #439 - support for $typemap() (aka embedded typemaps or special variable
+ macros) in typemap attributes. A simple example where $typemap() is expanded in the
+ 'out' attribute (C# specific):
+
+ %typemap(cstype) unsigned int "uint"
+ %typemap(cstype, out="$typemap(cstype, unsigned int)") unsigned int& "$typemap(cstype, unsigned int)"
+
+ is equivalent to:
+
+ %typemap(cstype, out="uint") unsigned int& "uint"
+
+2015-07-18: m7thon
+ [Python] Docstrings provided via %feature("docstring") are now quoted and added to
+ the tp_doc slot when using python builtin classes (-builtin). When no docstring is
+ provided, the tp_doc slot is set to the fully qualified C/C++ class name.
+ Github issues #445 and #461.
+
+2015-07-17: kwwette
+ [octave] Support Octave version 4.0.0 (thanks to patches from Orion Poplawski).
+
+2015-07-07: wsfulton
+ SWIG no longer generates a wrapper for a class' constructor if that class has
+ any base class with a private destructor. This is because your compiler should
+ not allow a class to be instantiated if a base has a private destructor. Some
+ compilers do, so if you need the old behaviour, use the "notabstract" feature, eg:
+
+ %feature("notabstract") Derived;
+ class Base {
+ ~Base() {}
+ };
+ struct Derived : Base {};
+
Version 3.0.6 (5 Jul 2015)
==========================
diff --git a/CHANGES.current b/CHANGES.current
index 48ccc2036..8c269f295 100644
--- a/CHANGES.current
+++ b/CHANGES.current
@@ -2,120 +2,20 @@ Below are the changes for the current release.
See the CHANGES file for changes in older releases.
See the RELEASENOTES file for a summary of changes in each release.
-Version 3.0.7 (in progress)
+Version 3.0.8 (in progress)
===========================
-2015-08-02: wsfulton
- [Java] Fix potential security exploit in generated Java classes.
- The swigCPtr and swigCMemOwn member variables in the generated Java
- classes are now declared 'transient' by default. Further details of the exploit
- in Android is being published in an academic paper as part of USENIX WOOT '15:
- https://www.usenix.org/conference/woot15/workshop-program/presentation/peles.
+2015-08-07: talby
+ [Perl] tidy -Wtautological-constant-out-of-range-compare warnings when building generated code under clang
- In the unlikely event that you are relying on these members being serializable,
- then you will need to override the default javabody and javabody_derived typemaps
- to generate the old generated code. The relevant typemaps are in the Lib directory
- in the java.swg, boost_shared_ptr.i and boost_intrusive_ptr.i files. Copy the
- relevant default typemaps into your interface file and remove the 'transient' keyword.
-
- *** POTENTIAL INCOMPATIBILITY ***
-
-2015-08-01: vadz
- Make configure --without-alllang option more useful: it can now be overridden by the following
- --with-xxx options, allowing to easily enable just one or two languages.
-
-2015-07-30: wsfulton
- Fix #440 - Initialise all newly created arrays when using %array_functions and %array_class
- in the carrays.i library - bug is only relevant when using C++.
-
-2015-07-29: wsfulton
- [Python] Improve indentation warning and error messages for code in the following directives:
-
- %pythonprepend
- %pythonappend
- %pythoncode
- %pythonbegin
- %feature("shadow")
-
- Old error example:
- Error: Line indented less than expected (line 3 of pythoncode)
-
- New error example:
- Error: Line indented less than expected (line 3 of %pythoncode or %insert("python") block)
- as no line should be indented less than the indentation in line 1
-
- Old warning example:
- Warning 740: Whitespace prefix doesn't match (line 2 of %pythoncode or %insert("python") block)
-
- New warning example:
- Warning 740: Whitespace indentation is inconsistent compared to earlier lines (line 3 of
- %pythoncode or %insert("python") block)
-
-
-2015-07-28: wsfulton
- [Python] Fix #475. Improve docstring indentation handling.
-
- SWIG-3.0.5 and earlier sometimes truncated text provided in the docstring feature.
- This occurred when the indentation (whitespace) in the docstring was less in the
- second or later lines when compared to the first line.
- SWIG-3.0.6 gave a 'Line indented less than expected' error instead of truncating
- the docstring text.
- Now the indentation for the 'docstring' feature is smarter and is appropriately
- adjusted so that no truncation occurs.
-
-2015-07-22: wsfulton
- Support for special variable expansion in typemap attributes. Example usage expansion
- in the 'out' attribute (C# specific):
-
- %typemap(ctype, out="$*1_ltype") unsigned int& "$*1_ltype"
-
- is equivalent to the following as $*1_ltype expands to 'unsigned int':
-
- %typemap(ctype, out="unsigned int") unsigned int& "unsigned int"
-
- Special variables can be used within special variable macros too. Example usage expansion:
-
- %typemap(cstype) unsigned int "uint"
- %typemap(cstype, out="$typemap(cstype, $*1_ltype)") unsigned int& "$typemap(cstype, $*1_ltype)"
-
- Special variables are expanded first and hence the above is equivalent to:
-
- %typemap(cstype, out="$typemap(cstype, unsigned int)") unsigned int& "$typemap(cstype, unsigned int)"
-
- which then expands to:
-
- %typemap(cstype, out="uint") unsigned int& "uint"
-
-2015-07-22: lindleyf
- Apply patch #439 - support for $typemap() (aka embedded typemaps or special variable
- macros) in typemap attributes. A simple example where $typemap() is expanded in the
- 'out' attribute (C# specific):
-
- %typemap(cstype) unsigned int "uint"
- %typemap(cstype, out="$typemap(cstype, unsigned int)") unsigned int& "$typemap(cstype, unsigned int)"
-
- is equivalent to:
-
- %typemap(cstype, out="uint") unsigned int& "uint"
-
-2015-07-18: m7thon
- [Python] Docstrings provided via %feature("docstring") are now quoted and added to
- the tp_doc slot when using python builtin classes (-builtin). When no docstring is
- provided, the tp_doc slot is set to the fully qualified C/C++ class name.
- Github issues #445 and #461.
-
-2015-07-17: kwwette
- [octave] Support Octave version 4.0.0 (thanks to patches from Orion Poplawski).
-
-2015-07-07: wsfulton
- SWIG no longer generates a wrapper for a class' constructor if that class has
- any base class with a private destructor. This is because your compiler should
- not allow a class to be instantiated if a base has a private destructor. Some
- compilers do, so if you need the old behaviour, use the "notabstract" feature, eg:
-
- %feature("notabstract") Derived;
- class Base {
- ~Base() {}
- };
- struct Derived : Base {};
+2015-08-07: xantares
+ [Python] pep257 & numpydoc conforming docstrings:
+ - Mono-line module docsstring
+ - Rewrite autodoc parameters section in numpydoc style:
+ https://github.com/numpy/numpy/blob/master/doc/HOWTO_DOCUMENT.rst.txt
+ - One line summary should end with "."
+ - Adds a blank line after class docstring
+2015-08-05: vadz
+ [Java] Make (char* STRING, size_t LENGTH) typemaps usable for
+ strings of other types, e.g. "unsigned char*".
diff --git a/Doc/Manual/Go.html b/Doc/Manual/Go.html
index 20e923d19..ca12410ad 100644
--- a/Doc/Manual/Go.html
+++ b/Doc/Manual/Go.html
@@ -29,6 +29,16 @@
</ul>
<li><a href="#Go_templates">Go Templates</a>
<li><a href="#Go_director_classes">Go Director Classes</a>
+<ul>
+<li><a href="#Go_director_example_cpp_code">Example C++ code</a>
+<li><a href="#Go_director_enable">Enable director feature</a>
+<li><a href="#Go_director_ctor_dtor">Constructor and destructor</a>
+<li><a href="#Go_director_overriding">Override virtual methods</a>
+<li><a href="#Go_director_base_methods">Call base methods</a>
+<li><a href="#Go_director_subclass">Subclass via embedding</a>
+<li><a href="#Go_director_finalizer">Memory management with runtime.SetFinalizer</a>
+<li><a href="#Go_director_foobargo_class">Complete FooBarGo example class</a>
+</ul>
<li><a href="#Go_primitive_type_mappings">Default Go primitive type mappings</a>
<li><a href="#Go_output_arguments">Output arguments</a>
<li><a href="#Go_adding_additional_code">Adding additional go code</a>
@@ -574,49 +584,549 @@ In order to use C++ templates in Go, you must tell SWIG to create
wrappers for a particular template instantation. To do this, use
the <tt>%template</tt> directive.
+
<H3><a name="Go_director_classes"></a>23.4.7 Go Director Classes</H3>
<p>
-SWIG's director feature permits a Go type to act as the subclass of a
-C++ class with virtual methods. This is complicated by the fact that
-C++ and Go define inheritance differently. In Go, structs can inherit
-methods via anonymous field embedding. However, when a method is
-called for an embedded struct, if that method calls any other methods,
-they are called for the embedded struct, not for the original type.
-Therefore, SWIG must use Go interfaces to represent C++ inheritance.
+SWIG's director feature permits a Go type to act as the subclass of a C++ class.
+This is complicated by the fact that C++ and Go define inheritance differently.
+SWIG normally represents the C++ class inheritance automatically in Go via
+interfaces but with a Go type representing a subclass of a C++ class some manual
+work is necessary.
+<p>
+
+<p>
+This subchapter gives a step by step guide how to properly sublass a C++ class
+with a Go type. In general it is strongly recommended to follow this guide
+completely to avoid common pitfalls with directors in Go.
+</p>
+
+
+<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. 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>FooBarAbstract</tt> abstract C++ class:
+</p>
+
+<div class="code">
+<pre>
+class FooBarAbstract
+{
+public:
+ FooBarAbstract() {};
+ virtual ~FooBarAbstract() {};
+
+ std::string FooBar() {
+ return this->Foo() + ", " + this->Bar();
+ };
+
+protected:
+ virtual std::string Foo() {
+ return "Foo";
+ };
+
+ virtual std::string Bar() = 0;
+};
+</pre>
+</div>
+
+<p>
+<tt>FooBarCpp</tt> C++ class:
+</p>
+
+<div class="code">
+<pre>
+class FooBarCpp : public FooBarAbstract
+{
+protected:
+ virtual std::string Foo() {
+ return "C++ " + FooBarAbstract::Foo();
+ }
+
+ virtual std::string Bar() {
+ return "C++ Bar";
+ }
+};
+</pre>
+</div>
+
+<p>
+Returned string by the <tt>FooBarCpp::FooBar</tt> method is:
+</p>
+
+<div class="code">
+<pre>
+C++ Foo, C++ Bar
+</pre>
+</div>
+
+
+<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>.
+</p>
+
+
+<H4><a name="Go_director_enable"></a>23.4.7.2 Enable director feature</H4>
+
+
+<p>
+The director feature is disabled by default. To use directors you must make two
+changes to the interface file. First, add the "directors" option to the %module
+directive, like this:
+</p>
+
+<div class="code">
+<pre>
+%module(directors="1") modulename
+</pre>
+</div>
+
+<p>
+Second, you must use the %feature("director") directive to tell SWIG which
+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") FooBarAbstract;
+</pre>
+</div>
+
+<p>
+For a more detailed documentation of the director feature and how to enable or
+disable it for specific classes and virtual methods see SWIG's Java
+documentation on directors.
+</p>
+
+
+<H4><a name="Go_director_ctor_dtor"></a>23.4.7.3 Constructor and destructor</H4>
+
+
+<p>
+SWIG creates an additional set of constructor and destructor functions once the
+director feature has been enabled for a C++ class.
+<tt>NewDirectorClassName</tt> allows overriding virtual methods on the new
+object instance and <tt>DeleteDirectorClassName</tt> needs to be used to free a
+director object instance created with <tt>NewDirectorClassName</tt>.
+More on overriding virtual methods follows later in this guide under
+<a href="#Go_director_overriding">overriding virtual methods</a>.
+</p>
+
+<p>
+The default constructor and destructor functions <tt>NewClassName</tt> and
+<tt>DeleteClassName</tt> can still be used as before so that existing code
+doesn't break just because the director feature has been enabled for a C++
+class. The behavior is undefined if the default and director constructor and
+destructor functions get mixed and so great care needs to be taken that only one
+of the constructor and destructor function pairs is used for any object
+instance. Both constructor functions, the default and the director one, return
+the same interface type. This makes it potentially hard to know which
+destructor function, the default or the director one, needs to be called to
+delete an object instance.
+</p>
+
+<p>
+In <b>theory</b> the <tt>DirectorInterface</tt> method could be used to
+determine if an object instance was created via <tt>NewDirectorClassName</tt>:
+</p>
+
+<div class="code">
+<pre>
+if o.DirectorInterface() != nil {
+ DeleteDirectorClassName(o)
+} else {
+ DeleteClassName(o)
+}
+</pre>
+</div>
+
+<p>
+In <b>practice</b> it is strongly recommended to embed a director object
+instance in a Go struct so that a director object instance will be represented
+as a distinct Go type that subclasses a C++ class. For this Go type custom
+constructor and destructor functions take care of the director constructor and
+destructor function calls and the resulting Go class will appear to the user as
+any other SWIG wrapped C++ class. More on properly subclassing a C++ class
+follows later in this guide under <a href="#Go_director_subclass">subclass via
+embedding</a>.
+</p>
+
+
+<H4><a name="Go_director_overriding"></a>23.4.7.4 Override virtual methods</H4>
+
+
+<p>
+In order to override virtual methods on a C++ class with Go methods the
+<tt>NewDirectorClassName</tt> constructor functions receives a
+<tt>DirectorInterface</tt> argument. The methods in the <tt>
+DirectorInterface</tt> are a subset of the public and protected virtual methods
+of the C++ class. If the <tt>DirectorInterface</tt> contains a method with a
+matching signature to a virtual method of the C++ class then the virtual C++
+method will be overwritten with the Go method. As Go doesn't support protected
+methods all overriden protected virtual C++ methods will be public in Go.
+</p>
+
+<p>
+As an example see part of the <tt>FooBarGo</tt> class:
+</p>
+
+<div class="code">
+<pre>
+type overwrittenMethodsOnFooBarAbstract struct {
+ fb FooBarAbstract
+}
+
+func (om *overwrittenMethodsOnFooBarAbstract) Foo() string {
+ ...
+}
+
+func (om *overwrittenMethodsOnFooBarAbstract) Bar() string {
+ ...
+}
+
+func NewFooBarGo() FooBarGo {
+ om := &amp;overwrittenMethodsOnFooBarAbstract{}
+ fb := NewDirectorFooBarAbstract(om)
+ om.fb = fb
+ ...
+}
+</pre>
+</div>
+
+<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>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>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>overwrittenMethodsOnFooBarAbstract</tt> struct so that they can be used by
+the Go methods.
+</p>
+
+
+<H4><a name="Go_director_base_methods"></a>23.4.7.5 Call base methods</H4>
+
+
+<p>
+Often a virtual method will be overwritten to extend the original behavior of
+the method in the base class. This is also the case for the
+<tt>FooBarCpp::Foo</tt> method of the example code:
+</p>
+
+<div class="code">
+<pre>
+virtual std::string Foo() {
+ return "C++ " + FooBarAbstract::Foo();
+}
+</pre>
+</div>
+
+<p>
+To use base methods the <tt>DirectorClassNameMethodName</tt> wrapper functions
+are automatically generated by SWIG for public and protected virtual methods.
+The <tt>FooBarGo.Foo</tt> implementation in the example looks like this:
+</p>
+
+<div class="code">
+<pre>
+func (om *overwrittenMethodsOnFooBarAbstract) Foo() string {
+ return "Go " + DirectorFooBarAbstractFoo(om.fb)
+}
+</pre>
+</div>
+
+<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>.
+</p>
+
+
+<H4><a name="Go_director_subclass"></a>23.4.7.6 Subclass via embedding</H4>
+
+
+<p>
+<a href="#Go_director_ctor_dtor">As previously mentioned in this guide</a> the
+default and director constructor functions return the same interface type. To
+properly subclass a C++ class with a Go type the director object instance
+returned by the <tt>NewDirectorClassName</tt> constructor function should be
+embedded into a Go struct so that it represents a distinct but compatible type
+in Go's type system. This Go struct should be private and the constructor and
+destructor functions should instead work with a public interface type so that
+the Go class that subclasses a C++ class can be used as a compatible drop in.
+</p>
+
+<p>
+The subclassing part of the <tt>FooBarGo</tt> class for an example looks like
+this:
+</p>
+
+<div class="code">
+<pre>
+type FooBarGo interface {
+ FooBarAbstract
+ deleteFooBarAbstract()
+ IsFooBarGo()
+}
+
+type fooBarGo struct {
+ FooBarAbstract
+}
+
+func (fbgs *fooBarGo) deleteFooBarAbstract() {
+ DeleteDirectorFooBarAbstract(fbgs.FooBarAbstract)
+}
+
+func (fbgs *fooBarGo) IsFooBarGo() {}
+
+func NewFooBarGo() FooBarGo {
+ om := &amp;overwrittenMethodsOnFooBarAbstract{}
+ fb := NewDirectorFooBarAbstract(om)
+ om.fb = fb
+
+ return &amp;fooBarGo{FooBarAbstract: fb}
+}
+
+func DeleteFooBarGo(fbg FooBarGo) {
+ fbg.deleteFooBarAbstract()
+}
+</pre>
+</div>
+
+
+<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 private <tt>fooBarGo</tt> struct embeds <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.
+</p>
+
+
+<H4><a name="Go_director_finalizer"></a>23.4.7.7 Memory management with runtime.SetFinalizer</H4>
+
+
+<p>
+In general all guidelines for <a href="#Go_class_memory">C++ class memory
+management</a> apply as well to director classes. One often overlooked
+limitation with <tt>runtime.SetFinalizer</tt> is that a finalizer doesn't run
+in case of a cycle and director classes typically have a cycle. The cycle
+in the <tt>FooBarGo</tt> class is here:
+</p>
+
+<div class="code">
+<pre>
+type overwrittenMethodsOnFooBarAbstract struct {
+ fb FooBarAbstract
+}
+
+func NewFooBarGo() FooBarGo {
+ om := &amp;overwrittenMethodsOnFooBarAbstract{}
+ fb := NewDirectorFooBarAbstract(om) // fb.v = om
+ om.fb = fb // Backlink causes cycle as fb.v = om!
+ ...
+}
+</pre>
+</div>
+
+<p>
+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>
+FooBarAbstract</tt> director instance can be automatically deleted by setting
+the finalizer on <tt>fooBarGo</tt>:
</p>
+<div class="code">
+<pre>
+type fooBarGo struct {
+ FooBarAbstract
+}
+
+type overwrittenMethodsOnFooBarAbstract struct {
+ fb FooBarAbstract
+}
+
+func NewFooBarGo() FooBarGo {
+ om := &amp;overwrittenMethodsOnFooBarAbstract{}
+ fb := NewDirectorFooBarAbstract(om)
+ om.fb = fb // Backlink causes cycle as fb.v = om!
+
+ fbgs := &amp;fooBarGo{FooBarAbstract: fb}
+ runtime.SetFinalizer(fbgs, FooBarGo.deleteFooBarAbstract)
+ return fbgs
+}
+</pre>
+</div>
+
<p>
-In order to use the director feature in Go, you must define a type in
-your Go code. You must then add methods for the type. Define a
-method in Go for each C++ virtual function that you want to override.
-You must then create a value of your new type, and pass a pointer to
-it to the function <tt>NewDirectorClassName</tt>,
-where <tt>ClassName</tt> is the name of the C++ class. That will
-return a value of type <tt>ClassName</tt>.
+Furthermore if <tt>runtime.SetFinalizer</tt> is in use either the <tt>
+DeleteClassName</tt> destructor function needs to be removed or the <tt>
+fooBarGo</tt> struct needs additional data to prevent double deletion. Please
+read the <a href="#Go_class_memory">C++ class memory management</a> subchapter
+before using <tt>runtime.SetFinalizer</tt> to know all of its gotchas.
</p>
+
+<H4><a name="Go_director_foobargo_class"></a>23.4.7.8 Complete FooBarGo example class</H4>
+
+
<p>
-For example:
+The complete and annotated <tt>FooBarGo</tt> class looks like this:
</p>
<div class="code">
<pre>
-type GoClass struct { }
-func (p *GoClass) VirtualFunction() { }
-func MakeClass() ClassName {
- return NewDirectorClassName(&amp;GoClass{})
+// 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 {
+ FooBarAbstract
+ deleteFooBarAbstract()
+ IsFooBarGo()
+}
+
+// Via embedding fooBarGo "inherits" all methods of FooBarAbstract.
+type fooBarGo struct {
+ FooBarAbstract
+}
+
+func (fbgs *fooBarGo) deleteFooBarAbstract() {
+ DeleteDirectorFooBarAbstract(fbgs.FooBarAbstract)
+}
+
+// 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 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 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 *overwrittenMethodsOnFooBarAbstract) Foo() string {
+ // DirectorFooBarAbstractFoo calls the base method FooBarAbstract::Foo.
+ return "Go " + DirectorFooBarAbstractFoo(om.fb)
+}
+
+func (om *overwrittenMethodsOnFooBarAbstract) Bar() string {
+ return "Go Bar"
+}
+
+func NewFooBarGo() FooBarGo {
+ // 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 := &amp;overwrittenMethodsOnFooBarAbstract{}
+ fb := NewDirectorFooBarAbstract(om)
+ om.fb = fb // Backlink causes cycle as fb.v = om!
+
+ fbgs := &amp;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.deleteFooBarAbstract()
}
</pre>
</div>
<p>
-Any call in C++ code to the virtual function will wind up calling the
-method defined in Go. The Go code may of course call other methods on
-itself, and those methods may be defined either in Go or in C++.
+Returned string by the <tt>FooBarGo.FooBar</tt> method is:
</p>
+<div class="code">
+<pre>
+Go Foo, Go Bar
+</pre>
+</div>
+
+<p>
+For comparison the <tt>FooBarCpp</tt> class looks like this:
+</p>
+
+<div class="code">
+<pre>
+class FooBarCpp : public FooBarAbstract
+{
+protected:
+ virtual std::string Foo() {
+ return "C++ " + FooBarAbstract::Foo();
+ }
+
+ virtual std::string Bar() {
+ return "C++ Bar";
+ }
+};
+</pre>
+</div>
+
+<p>
+For comparison the returned string by the <tt>FooBarCpp::FooBar</tt> method is:
+</p>
+
+<div class="code">
+<pre>
+C++ Foo, C++ Bar
+</pre>
+</div>
+
+<p>
+The complete source of this example can be found under
+<a href="https://github.com/swig/swig/tree/master/Examples/go/director">
+SWIG/Examples/go/director/</a>.
+</p>
+
+
<H3><a name="Go_primitive_type_mappings"></a>23.4.8 Default Go primitive type mappings</H3>
diff --git a/Doc/Manual/Python.html b/Doc/Manual/Python.html
index 57a2cd3ef..3af79e8d6 100644
--- a/Doc/Manual/Python.html
+++ b/Doc/Manual/Python.html
@@ -5273,8 +5273,8 @@ def function_name(*args, **kwargs):
<p>
Level "2" results in the function prototype as per level "0". In addition, a line of
-documentation is generated for each parameter. Using the previous example, the generated
-code will be:
+documentation is generated for each parameter using <a href="https://github.com/numpy/numpy/blob/master/doc/HOWTO_DOCUMENT.rst.txt">numpydoc</a> style.
+Using the previous example, the generated code will be:
</p>
<div class="targetlang">
@@ -5283,11 +5283,12 @@ def function_name(*args, **kwargs):
"""
function_name(x, y, foo=None, bar=None) -&gt; bool
- Parameters:
- x: int
- y: int
- foo: Foo *
- bar: Bar *
+ Parameters
+ ----------
+ x: int
+ y: int
+ foo: Foo *
+ bar: Bar *
"""
...
@@ -5318,11 +5319,12 @@ def function_name(*args, **kwargs):
"""
function_name(x, y, foo=None, bar=None) -&gt; bool
- Parameters:
- x (C++ type: int) -- Input x dimension
- y: int
- foo: Foo *
- bar: Bar *
+ Parameters
+ ----------
+ x (C++ type: int) -- Input x dimension
+ y: int
+ foo: Foo *
+ bar: Bar *
"""
</pre>
@@ -5341,11 +5343,12 @@ def function_name(*args, **kwargs):
"""
function_name(int x, int y, Foo foo=None, Bar bar=None) -&gt; bool
- Parameters:
- x: int
- y: int
- foo: Foo *
- bar: Bar *
+ Parameters
+ ----------
+ x: int
+ y: int
+ foo: Foo *
+ bar: Bar *
"""
...
diff --git a/Doc/Manual/Sections.html b/Doc/Manual/Sections.html
index 4bf40c969..b917c4cd8 100644
--- a/Doc/Manual/Sections.html
+++ b/Doc/Manual/Sections.html
@@ -6,7 +6,7 @@
<body bgcolor="#ffffff">
<H1><a name="Sections"></a>SWIG-3.0 Documentation</H1>
-Last update : SWIG-3.0.7 (in progress)
+Last update : SWIG-3.0.8 (in progress)
<H2>Sections</H2>
diff --git a/Examples/go/callback/Makefile b/Examples/go/callback/Makefile
index bf5275f14..7441e09bd 100644
--- a/Examples/go/callback/Makefile
+++ b/Examples/go/callback/Makefile
@@ -1,6 +1,7 @@
TOP = ../..
SWIG = $(TOP)/../preinst-swig
CXXSRCS = callback.cxx
+GOSRCS = gocallback.go
TARGET = example
INTERFACE = example.i
SWIGOPT =
@@ -9,8 +10,15 @@ check: build
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go_run
build:
- $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \
- SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go_cpp
+ 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/example.h b/Examples/go/callback/example.h
index 1a0e8c432..74ddad954 100644
--- a/Examples/go/callback/example.h
+++ b/Examples/go/callback/example.h
@@ -20,4 +20,3 @@ public:
void setCallback(Callback *cb) { delCallback(); _callback = cb; }
void call() { if (_callback) _callback->run(); }
};
-
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
index b053cf547..9a53065b0 100644
--- a/Examples/go/callback/index.html
+++ b/Examples/go/callback/index.html
@@ -12,67 +12,17 @@
<H2>Implementing C++ callbacks in Go</H2>
<p>
-This example illustrates how to use directors to implement C++
-callbacks in Go.
-</p>
-
-<p>
-Because Go and C++ use inheritance differently, you must call a
-different function to create a class which uses callbacks. Instead of
-calling the usual constructor function whose name is <tt>New</tt>
-followed by the capitalized name of the class, you call a function
-named <tt>NewDirector</tt> followed by the capitalized name of the
-class.
-</p>
-
-<p>
-The first argument to the <tt>NewDirector</tt> function is an instance
-of a type. The <tt>NewDirector</tt> function will return an interface
-value as usual. However, when calling any method on the returned
-value, the program will first check whether the value passed
-to <tt>NewDirector</tt> implements that method. If it does, the
-method will be called in Go. This is true whether the method is
-called from Go code or C++ code.
-</p>
-
-<p>
-Note that the Go code will be called with just the Go value, not the
-C++ value. If the Go code needs to call a C++ method on itself, you
-need to get a copy of the C++ object. This is typically done as
-follows:
-
-<blockquote>
-<pre>
-type Child struct { abi Parent }
-func (p *Child) ChildMethod() {
- p.abi.ParentMethod()
-}
-func f() {
- p := &Child{nil}
- d := NewDirectorParent(p)
- p.abi = d
- ...
-}
-</pre>
-</blockquote>
-
-In other words, we first create the Go value. We pass that to
-the <tt>NewDirector</tt> function to create the C++ value; this C++
-value will be created with an association to the Go value. We then
-store the C++ value in the Go value, giving us the reverse
-association. That permits us to call parent methods from the child.
-
-</p>
-
-<p>
-To delete a director object, use the function <tt>DeleteDirector</tt>
-followed by the capitalized name of the class.
+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 file containing some enums.
-<li><a href="example.i">example.i</a>. Interface file.
+<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>
diff --git a/Examples/go/callback/runme.go b/Examples/go/callback/runme.go
index 2eef77fdb..03ab0c5e2 100644
--- a/Examples/go/callback/runme.go
+++ b/Examples/go/callback/runme.go
@@ -16,26 +16,18 @@ func main() {
caller.Call()
caller.DelCallback()
- callback = NewDirectorCallback(new(GoCallback))
+ go_callback := NewGoCallback()
fmt.Println()
fmt.Println("Adding and calling a Go callback")
- fmt.Println("------------------------------------")
+ fmt.Println("--------------------------------")
- caller.SetCallback(callback)
+ caller.SetCallback(go_callback)
caller.Call()
caller.DelCallback()
- // Test that a double delete does not occur as the object has
- // already been deleted from the C++ layer.
- DeleteDirectorCallback(callback)
+ DeleteGoCallback(go_callback)
fmt.Println()
fmt.Println("Go exit")
}
-
-type GoCallback struct{}
-
-func (p *GoCallback) Run() {
- fmt.Println("GoCallback.Run")
-}
diff --git a/Examples/go/check.list b/Examples/go/check.list
index 5399b8979..b3f34b306 100644
--- a/Examples/go/check.list
+++ b/Examples/go/check.list
@@ -2,6 +2,7 @@
callback
class
constants
+director
enum
extend
funcptr
diff --git a/Examples/go/director/Makefile b/Examples/go/director/Makefile
new file mode 100644
index 000000000..2e9e87b89
--- /dev/null
+++ b/Examples/go/director/Makefile
@@ -0,0 +1,24 @@
+TOP = ../..
+SWIG = $(TOP)/../preinst-swig
+CXXSRCS =
+GOSRCS = director.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/director/director.go b/Examples/go/director/director.go
new file mode 100644
index 000000000..4f99bfc6d
--- /dev/null
+++ b/Examples/go/director/director.go
@@ -0,0 +1,72 @@
+package example
+
+// 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 {
+ FooBarAbstract
+ deleteFooBarAbstract()
+ IsFooBarGo()
+}
+
+// Via embedding fooBarGo "inherits" all methods of FooBarAbstract.
+type fooBarGo struct {
+ FooBarAbstract
+}
+
+func (fbgs *fooBarGo) deleteFooBarAbstract() {
+ DeleteDirectorFooBarAbstract(fbgs.FooBarAbstract)
+}
+
+// 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 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 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 *overwrittenMethodsOnFooBarAbstract) Foo() string {
+ // DirectorFooBarAbstractFoo calls the base method FooBarAbstract::Foo.
+ return "Go " + DirectorFooBarAbstractFoo(om.fb)
+}
+
+func (om *overwrittenMethodsOnFooBarAbstract) Bar() string {
+ return "Go Bar"
+}
+
+func NewFooBarGo() FooBarGo {
+ // 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{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.deleteFooBarAbstract()
+}
diff --git a/Examples/go/director/director.h b/Examples/go/director/director.h
new file mode 100644
index 000000000..339a9adcd
--- /dev/null
+++ b/Examples/go/director/director.h
@@ -0,0 +1,41 @@
+#ifndef DIRECTOR_H
+#define DIRECTOR_H
+
+
+#include <stdio.h>
+#include <string>
+
+
+class FooBarAbstract
+{
+public:
+ FooBarAbstract() {};
+ virtual ~FooBarAbstract() {};
+
+ std::string FooBar() {
+ return this->Foo() + ", " + this->Bar();
+ };
+
+protected:
+ virtual std::string Foo() {
+ return "Foo";
+ };
+
+ virtual std::string Bar() = 0;
+};
+
+
+class FooBarCpp : public FooBarAbstract
+{
+protected:
+ virtual std::string Foo() {
+ return "C++ " + FooBarAbstract::Foo();
+ }
+
+ virtual std::string Bar() {
+ return "C++ Bar";
+ }
+};
+
+
+#endif
diff --git a/Examples/go/director/example.i b/Examples/go/director/example.i
new file mode 100644
index 000000000..e832bd8c6
--- /dev/null
+++ b/Examples/go/director/example.i
@@ -0,0 +1,11 @@
+/* File : example.i */
+%module(directors="1") example
+
+%include "std_string.i"
+
+%header %{
+#include "director.h"
+%}
+
+%feature("director") FooBarAbstract;
+%include "director.h"
diff --git a/Examples/go/director/index.html b/Examples/go/director/index.html
new file mode 100644
index 000000000..b93e780e5
--- /dev/null
+++ b/Examples/go/director/index.html
@@ -0,0 +1,28 @@
+<html>
+<head>
+<title>SWIG:Examples:go:director</title>
+</head>
+
+<body bgcolor="#ffffff">
+
+<tt>SWIG/Examples/go/director/</tt>
+<hr>
+
+<H2>How to subclass a C++ class with a Go type</H2>
+
+<p>
+See the <a href="../../../Doc/Manual/Go.html#Go_director_classes">Go Director
+Classes</a> documentation subsection for an explanation of this example.
+</p>
+
+<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 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>
+
+<hr>
+</body>
+</html>
diff --git a/Examples/go/director/runme.go b/Examples/go/director/runme.go
new file mode 100644
index 000000000..0d839bc88
--- /dev/null
+++ b/Examples/go/director/runme.go
@@ -0,0 +1,39 @@
+package main
+
+import (
+ "./example"
+ "fmt"
+ "os"
+)
+
+func Compare(name string, got string, exp string) error {
+ fmt.Printf("%s; Got: '%s'; Expected: '%s'\n", name, got, exp)
+ if got != exp {
+ return fmt.Errorf("%s returned unexpected string! Got: '%s'; Expected: '%s'\n", name, got, exp)
+ }
+ return nil
+}
+
+func TestFooBarCpp() error {
+ fb := example.NewFooBarCpp()
+ defer example.DeleteFooBarCpp(fb)
+ return Compare("FooBarCpp.FooBar()", fb.FooBar(), "C++ Foo, C++ Bar")
+}
+
+func TestFooBarGo() error {
+ fb := example.NewFooBarGo()
+ defer example.DeleteFooBarGo(fb)
+ return Compare("FooBarGo.FooBar()", fb.FooBar(), "Go Foo, Go Bar")
+}
+
+func main() {
+ fmt.Println("Test output:")
+ fmt.Println("------------")
+ err := TestFooBarCpp()
+ err = TestFooBarGo()
+ fmt.Println("------------")
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Tests failed! Last error: %s\n", err.Error())
+ os.Exit(1)
+ }
+}
diff --git a/Examples/go/extend/Makefile b/Examples/go/extend/Makefile
index 290694210..a9f2d8d7d 100644
--- a/Examples/go/extend/Makefile
+++ b/Examples/go/extend/Makefile
@@ -1,6 +1,7 @@
TOP = ../..
SWIG = $(TOP)/../preinst-swig
CXXSRCS = extend.cxx
+GOSRCS = ceo.go
TARGET = example
INTERFACE = example.i
SWIGOPT =
@@ -9,8 +10,15 @@ check: build
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go_run
build:
- $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \
- SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' go_cpp
+ 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
index ca1aed28f..0c3b721bd 100644
--- a/Examples/go/extend/example.h
+++ b/Examples/go/extend/example.h
@@ -44,7 +44,7 @@ public:
const Employee *get_item(int i) {
return list[i];
}
- ~EmployeeList() {
+ ~EmployeeList() {
std::vector<Employee*>::iterator i;
std::cout << "~EmployeeList, deleting " << list.size() << " employees." << std::endl;
for (i=list.begin(); i!=list.end(); i++) {
diff --git a/Examples/go/extend/index.html b/Examples/go/extend/index.html
index 471fa9cdc..31788b2aa 100644
--- a/Examples/go/extend/index.html
+++ b/Examples/go/extend/index.html
@@ -12,13 +12,16 @@
<H2>Extending a simple C++ class in Go</H2>
<p>
-This example illustrates the extending of a C++ class with cross
-language polymorphism.
-
+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="example.h">example.h</a>. Header file containing some enums.
-<li><a href="example.i">example.i</a>. Interface file.
+<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>
diff --git a/Examples/go/extend/runme.go b/Examples/go/extend/runme.go
index 770e27802..a56968937 100644
--- a/Examples/go/extend/runme.go
+++ b/Examples/go/extend/runme.go
@@ -7,19 +7,12 @@ import (
"fmt"
)
-type CEO struct{}
-
-func (p *CEO) GetPosition() string {
- return "CEO"
-}
-
func main() {
// Create an instance of CEO, a class derived from the Go
// proxy of the underlying C++ class. The calls to getName()
// and getPosition() are standard, the call to getTitle() uses
// the director wrappers to call CEO.getPosition().
-
- e := NewDirectorManager(new(CEO), "Alice")
+ e := NewCEO("Alice")
fmt.Println(e.GetName(), " is a ", e.GetPosition())
fmt.Println("Just call her \"", e.GetTitle(), "\"")
fmt.Println("----------------------")
@@ -27,7 +20,6 @@ func main() {
// 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
@@ -49,15 +41,13 @@ func main() {
// CEO, but now Go thinks the object is an instance of class
// Employee. So the call passes through the Employee proxy
// class and on to the C wrappers and C++ director, eventually
- // ending up back at the Java CEO implementation of
+ // 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 Java implementation
+ // 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(), "\"")
@@ -66,11 +56,11 @@ func main() {
// 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.
+ // 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 21dda21b5..467f4ecb7 100644
--- a/Examples/go/index.html
+++ b/Examples/go/index.html
@@ -23,6 +23,7 @@ certain C declarations are turned into constants.
<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>
<h2>Compilation Issues</h2>
@@ -37,20 +38,23 @@ certain C declarations are turned into constants.
</blockquote>
<li>On Unix the compilation of examples is done using the
-file <tt>Example/Makefile</tt>. This makefile performs a manual
-module compilation which is platform specific. When using
-the <tt>6g</tt> or <tt>8g</tt> compiler, the steps look like this
+file <tt>Example/Makefile</tt>. Normally builds are done simply
+using <tt>go build</tt>. For testing purposes this makefile performs
+a manual module compilation that is platform specific. When using
+the <tt>gc</tt> compiler, the steps look approximately like this
(GNU/Linux):
<blockquote>
<pre>
-% swig -go interface.i
-% gcc -fpic -c interface_wrap.c
-% gcc -shared interface_wrap.o $(OBJS) -o interfacemodule.so
-% 6g interface.go
-% 6c interface_gc.c
-% gopack grc interface.a interface.6 interface_gc.6
-% 6l program.6
+% swig -go -cgo interface.i
+% mkdir -p gopath/src/interface
+% cp interface_wrap.c interface_wrap.h interface.go gopath/src/interface
+% GOPATH=`pwd`/gopath
+% export GOPATH
+% cd gopath/src/interface
+% go build
+% go tool compile $(SRCDIR)/runme.go
+% go tool link -o runme runme.o
</pre>
</blockquote>
@@ -58,10 +62,15 @@ the <tt>6g</tt> or <tt>8g</tt> compiler, the steps look like this
<blockquote>
<pre>
-% swig -go interface.i
-% gcc -c interface_wrap.c
-% gccgo -c interface.go
-% gccgo program.o interface.o interface_wrap.o
+% swig -go -cgo interface.i
+% mkdir -p gopath/src/interface
+% cp interface_wrap.c interface_wrap.h interface.go gopath/src/interface
+% GOPATH=`pwd`/gopath
+% export GOPATH
+% cd gopath/src/interface
+% go build
+% gccgo -c $(SRCDIR)/runme.go
+% gccgo -o runme runme.o interface.a
</pre>
</blockquote
@@ -76,14 +85,14 @@ The examples have been extensively tested on the following platforms:
</ul>
All of the examples were last tested with the following configuration
-(10 May 2010):
+(5 August 2015):
<ul>
-<li>Ubuntu Hardy
-<li>gcc-4.2.4
+<li>Ubuntu Trusty
+<li>gcc-4.8.4
</ul>
-Your mileage may vary. If you experience a problem, please let us know by
+Your mileage may vary. If you experience a problem, please let us know by
contacting us on the <a href="http://www.swig.org/mail.html">mailing lists</a>.
</body>
</html>
diff --git a/Examples/test-suite/array_typedef_memberin.i b/Examples/test-suite/array_typedef_memberin.i
index 7301057e9..ad2855eed 100644
--- a/Examples/test-suite/array_typedef_memberin.i
+++ b/Examples/test-suite/array_typedef_memberin.i
@@ -1,14 +1,14 @@
%module array_typedef_memberin
-#if defined(_MSC_VER)
- #pragma warning(disable: 4351) // new behavior: elements of array 'xyz' will be default initialized
-#endif
-
#if defined(SWIGSCILAB)
%rename(ExDetail) ExampleDetail;
#endif
%inline %{
+#if defined(_MSC_VER)
+ #pragma warning(disable: 4351) // new behavior: elements of array 'xyz' will be default initialized
+#endif
+
typedef short Eight[8];
typedef const short ConstEight[8];
namespace ArrayExample
diff --git a/Examples/test-suite/autodoc.i b/Examples/test-suite/autodoc.i
index 07afa5794..eda04d293 100644
--- a/Examples/test-suite/autodoc.i
+++ b/Examples/test-suite/autodoc.i
@@ -1,4 +1,4 @@
-%module(docstring="hello") autodoc
+%module(docstring="hello.") autodoc
%feature("autodoc");
@@ -27,7 +27,7 @@
%feature("autodoc","2") A::variable_c; // extended
%feature("autodoc","3") A::variable_d; // extended + types
-%feature("autodoc","just a string") A::funk; // names
+%feature("autodoc","just a string.") A::funk; // names
%inline {
diff --git a/Examples/test-suite/char_binary.i b/Examples/test-suite/char_binary.i
index 778792946..394565438 100644
--- a/Examples/test-suite/char_binary.i
+++ b/Examples/test-suite/char_binary.i
@@ -5,12 +5,16 @@ A test case for testing non null terminated char pointers.
%module char_binary
%apply (char *STRING, size_t LENGTH) { (const char *str, size_t len) }
+%apply (char *STRING, size_t LENGTH) { (const unsigned char *str, size_t len) }
%inline %{
struct Test {
size_t strlen(const char *str, size_t len) {
return len;
}
+ size_t ustrlen(const unsigned char *str, size_t len) {
+ return len;
+ }
};
typedef char namet[5];
diff --git a/Examples/test-suite/java/char_binary_runme.java b/Examples/test-suite/java/char_binary_runme.java
index 9227f8617..bc811ef5d 100644
--- a/Examples/test-suite/java/char_binary_runme.java
+++ b/Examples/test-suite/java/char_binary_runme.java
@@ -20,5 +20,11 @@ public class char_binary_runme {
if (t.strlen(hil0) != 4)
throw new RuntimeException("bad multi-arg typemap");
+
+ if (t.ustrlen(hile) != 4)
+ throw new RuntimeException("bad multi-arg typemap");
+
+ if (t.ustrlen(hil0) != 4)
+ throw new RuntimeException("bad multi-arg typemap");
}
}
diff --git a/Examples/test-suite/javascript/char_binary_runme.js b/Examples/test-suite/javascript/char_binary_runme.js
index b2aac920c..01b72ebe1 100644
--- a/Examples/test-suite/javascript/char_binary_runme.js
+++ b/Examples/test-suite/javascript/char_binary_runme.js
@@ -5,10 +5,17 @@ if (t.strlen('hile') != 4) {
print(t.strlen('hile'));
throw("bad multi-arg typemap 1");
}
+if (t.ustrlen('hile') != 4) {
+ print(t.ustrlen('hile'));
+ throw("bad multi-arg typemap 1");
+}
if (t.strlen('hil\0') != 4) {
throw("bad multi-arg typemap 2");
}
+if (t.ustrlen('hil\0') != 4) {
+ throw("bad multi-arg typemap 2");
+}
/*
* creating a raw char*
@@ -24,6 +31,9 @@ char_binary.pchar_setitem(pc, 4, 0);
if (t.strlen(pc) != 4) {
throw("bad multi-arg typemap (3)");
}
+if (t.ustrlen(pc) != 4) {
+ throw("bad multi-arg typemap (3)");
+}
char_binary.var_pchar = pc;
if (char_binary.var_pchar != "hola") {
diff --git a/Examples/test-suite/perl5/char_binary_runme.pl b/Examples/test-suite/perl5/char_binary_runme.pl
index 4c50ee700..f97d740a6 100644
--- a/Examples/test-suite/perl5/char_binary_runme.pl
+++ b/Examples/test-suite/perl5/char_binary_runme.pl
@@ -1,14 +1,16 @@
use strict;
use warnings;
-use Test::More tests => 7;
+use Test::More tests => 10;
BEGIN { use_ok('char_binary') }
require_ok('char_binary');
my $t = char_binary::Test->new();
is($t->strlen('hile'), 4, "string typemap");
+is($t->ustrlen('hile'), 4, "unsigned string typemap");
is($t->strlen("hil\0"), 4, "string typemap");
+is($t->ustrlen("hil\0"), 4, "unsigned string typemap");
#
# creating a raw char*
@@ -22,6 +24,7 @@ char_binary::pchar_setitem($pc, 4, 0);
is($t->strlen($pc), 4, "string typemap");
+is($t->ustrlen($pc), 4, "unsigned string typemap");
$char_binary::var_pchar = $pc;
is($char_binary::var_pchar, "hola", "pointer case");
diff --git a/Examples/test-suite/perl5/overload_simple_runme.pl b/Examples/test-suite/perl5/overload_simple_runme.pl
index 624d428c6..57a585a22 100644
--- a/Examples/test-suite/perl5/overload_simple_runme.pl
+++ b/Examples/test-suite/perl5/overload_simple_runme.pl
@@ -2,7 +2,7 @@
use overload_simple;
use vars qw/$DOWARN/;
use strict;
-use Test::More tests => 75;
+use Test::More tests => 97;
pass("loaded");
@@ -196,3 +196,40 @@ is(overload_simple::int_object(1), 1, "int_object(1)");
is(overload_simple::int_object(0), 0, "int_object(0)");
is(overload_simple::int_object(undef), 999, "int_object(Spam*)");
is(overload_simple::int_object($s), 999, "int_object(Spam*)");
+
+# some of this section is duplication of above tests, but I want to see
+# parity with the coverage in wrapmacro_runme.pl.
+
+sub check {
+ my($args, $want) = @_;
+ my($s, $rslt) = defined $want ? ($want, "bar:$want") : ('*boom*', undef);
+ is(eval("overload_simple::Spam::bar($args)"), $rslt, "bar($args) => $s");
+}
+
+# normal use patterns
+check("11", 'int');
+check("11.0", 'double');
+check("'11'", 'char *');
+check("'11.0'", 'char *');
+check("-13", 'int');
+check("-13.0", 'double');
+check("'-13'", 'char *');
+check("'-13.0'", 'char *');
+
+check("' '", 'char *');
+check("' 11 '", 'char *');
+# TypeError explosions
+check("\\*STDIN", undef);
+check("[]", undef);
+check("{}", undef);
+check("sub {}", undef);
+
+# regression cases
+check("''", 'char *');
+check("' 11'", 'char *');
+check("' 11.0'", 'char *');
+check("' -11.0'", 'char *');
+check("\"11\x{0}\"", 'char *');
+check("\"\x{0}\"", 'char *');
+check("\"\x{9}11\x{0}this is not eleven.\"", 'char *');
+check("\"\x{9}11.0\x{0}this is also not eleven.\"", 'char *');
diff --git a/Examples/test-suite/perl5/wrapmacro_runme.pl b/Examples/test-suite/perl5/wrapmacro_runme.pl
index 8e0154057..f2478b51b 100644
--- a/Examples/test-suite/perl5/wrapmacro_runme.pl
+++ b/Examples/test-suite/perl5/wrapmacro_runme.pl
@@ -1,7 +1,7 @@
#!/usr/bin/perl
use strict;
use warnings;
-use Test::More tests => 5;
+use Test::More tests => 27;
BEGIN { use_ok('wrapmacro') }
require_ok('wrapmacro');
@@ -12,3 +12,44 @@ my $b = -1;
is(wrapmacro::maximum($a,$b), 2);
is(wrapmacro::maximum($a/7.0, -$b*256), 256);
is(wrapmacro::GUINT16_SWAP_LE_BE_CONSTANT(1), 256);
+
+# some of this section is duplication of above tests, but I want to see
+# parity with the coverage in overload_simple_runme.pl.
+
+sub check {
+ my($args, $rslt) = @_;
+ my $s = defined $rslt ? $rslt : '*boom*';
+ is(eval("wrapmacro::maximum($args)"), $rslt, "max($args) => $s");
+}
+
+# normal use patterns
+check("0, 11", 11);
+check("0, 11.0", 11);
+check("0, '11'", 11);
+check("0, '11.0'", 11);
+check("11, -13", 11);
+check("11, -13.0", 11);
+{ local $TODO = 'strtoull() handles /^\s*-\d+$/ amusingly';
+check("11, '-13'", 11);
+}
+check("11, '-13.0'", 11);
+
+# TypeError explosions
+check("0, ' '", undef);
+check("0, ' 11 '", undef);
+check("0, \\*STDIN", undef);
+check("0, []", undef);
+check("0, {}", undef);
+check("0, sub {}", undef);
+
+# regression cases
+{ local $TODO = 'strtol() and friends have edge cases we should guard against';
+check("-11, ''", undef);
+check("0, ' 11'", undef);
+check("0, ' 11.0'", undef);
+check("-13, ' -11.0'", undef);
+check("0, \"11\x{0}\"", undef);
+check("0, \"\x{0}\"", undef);
+check("0, \"\x{9}11\x{0}this is not eleven.\"", undef);
+check("0, \"\x{9}11.0\x{0}this is also not eleven.\"", undef);
+}
diff --git a/Examples/test-suite/python/autodoc_runme.py b/Examples/test-suite/python/autodoc_runme.py
index f5b6b7ce6..7256669d9 100644
--- a/Examples/test-suite/python/autodoc_runme.py
+++ b/Examples/test-suite/python/autodoc_runme.py
@@ -23,8 +23,8 @@ if not is_new_style_class(A):
# skip builtin check - the autodoc is missing, but it probably should not be
skip = True
-check(A.__doc__, "Proxy of C++ A class", "::A")
-check(A.funk.__doc__, "just a string")
+check(A.__doc__, "Proxy of C++ A class.", "::A")
+check(A.funk.__doc__, "just a string.")
check(A.func0.__doc__,
"func0(self, arg2, hello) -> int",
"func0(arg2, hello) -> int")
@@ -35,17 +35,19 @@ check(A.func2.__doc__,
"\n"
" func2(self, arg2, hello) -> int\n"
"\n"
- " Parameters:\n"
- " arg2: short\n"
- " hello: int tuple[2]\n"
+ " Parameters\n"
+ " ----------\n"
+ " arg2: short\n"
+ " hello: int tuple[2]\n"
"\n"
" ",
"\n"
"func2(arg2, hello) -> int\n"
"\n"
- "Parameters:\n"
- " arg2: short\n"
- " hello: int tuple[2]\n"
+ "Parameters\n"
+ "----------\n"
+ "arg2: short\n"
+ "hello: int tuple[2]\n"
"\n"
""
)
@@ -53,17 +55,19 @@ check(A.func3.__doc__,
"\n"
" func3(A self, short arg2, Tuple hello) -> int\n"
"\n"
- " Parameters:\n"
- " arg2: short\n"
- " hello: int tuple[2]\n"
+ " Parameters\n"
+ " ----------\n"
+ " arg2: short\n"
+ " hello: int tuple[2]\n"
"\n"
" ",
"\n"
"func3(short arg2, Tuple hello) -> int\n"
"\n"
- "Parameters:\n"
- " arg2: short\n"
- " hello: int tuple[2]\n"
+ "Parameters\n"
+ "----------\n"
+ "arg2: short\n"
+ "hello: int tuple[2]\n"
"\n"
""
)
@@ -92,35 +96,39 @@ check(A.func2default.__doc__,
"\n"
" func2default(self, e, arg3, hello, f=2) -> int\n"
"\n"
- " Parameters:\n"
- " e: A *\n"
- " arg3: short\n"
- " hello: int tuple[2]\n"
- " f: double\n"
+ " Parameters\n"
+ " ----------\n"
+ " e: A *\n"
+ " arg3: short\n"
+ " hello: int tuple[2]\n"
+ " f: double\n"
"\n"
" func2default(self, e, arg3, hello) -> int\n"
"\n"
- " Parameters:\n"
- " e: A *\n"
- " arg3: short\n"
- " hello: int tuple[2]\n"
+ " Parameters\n"
+ " ----------\n"
+ " e: A *\n"
+ " arg3: short\n"
+ " hello: int tuple[2]\n"
"\n"
" ",
"\n"
"func2default(e, arg3, hello, f=2) -> int\n"
"\n"
- "Parameters:\n"
- " e: A *\n"
- " arg3: short\n"
- " hello: int tuple[2]\n"
- " f: double\n"
+ "Parameters\n"
+ "----------\n"
+ "e: A *\n"
+ "arg3: short\n"
+ "hello: int tuple[2]\n"
+ "f: double\n"
"\n"
"func2default(e, arg3, hello) -> int\n"
"\n"
- "Parameters:\n"
- " e: A *\n"
- " arg3: short\n"
- " hello: int tuple[2]\n"
+ "Parameters\n"
+ "----------\n"
+ "e: A *\n"
+ "arg3: short\n"
+ "hello: int tuple[2]\n"
"\n"
""
)
@@ -128,35 +136,39 @@ check(A.func3default.__doc__,
"\n"
" func3default(A self, A e, short arg3, Tuple hello, double f=2) -> int\n"
"\n"
- " Parameters:\n"
- " e: A *\n"
- " arg3: short\n"
- " hello: int tuple[2]\n"
- " f: double\n"
+ " Parameters\n"
+ " ----------\n"
+ " e: A *\n"
+ " arg3: short\n"
+ " hello: int tuple[2]\n"
+ " f: double\n"
"\n"
" func3default(A self, A e, short arg3, Tuple hello) -> int\n"
"\n"
- " Parameters:\n"
- " e: A *\n"
- " arg3: short\n"
- " hello: int tuple[2]\n"
+ " Parameters\n"
+ " ----------\n"
+ " e: A *\n"
+ " arg3: short\n"
+ " hello: int tuple[2]\n"
"\n"
" ",
"\n"
"func3default(A e, short arg3, Tuple hello, double f=2) -> int\n"
"\n"
- "Parameters:\n"
- " e: A *\n"
- " arg3: short\n"
- " hello: int tuple[2]\n"
- " f: double\n"
+ "Parameters\n"
+ "----------\n"
+ "e: A *\n"
+ "arg3: short\n"
+ "hello: int tuple[2]\n"
+ "f: double\n"
"\n"
"func3default(A e, short arg3, Tuple hello) -> int\n"
"\n"
- "Parameters:\n"
- " e: A *\n"
- " arg3: short\n"
- " hello: int tuple[2]\n"
+ "Parameters\n"
+ "----------\n"
+ "e: A *\n"
+ "arg3: short\n"
+ "hello: int tuple[2]\n"
"\n"
""
)
@@ -185,35 +197,39 @@ check(A.func2static.__doc__,
"\n"
" func2static(e, arg2, hello, f=2) -> int\n"
"\n"
- " Parameters:\n"
- " e: A *\n"
- " arg2: short\n"
- " hello: int tuple[2]\n"
- " f: double\n"
+ " Parameters\n"
+ " ----------\n"
+ " e: A *\n"
+ " arg2: short\n"
+ " hello: int tuple[2]\n"
+ " f: double\n"
"\n"
" func2static(e, arg2, hello) -> int\n"
"\n"
- " Parameters:\n"
- " e: A *\n"
- " arg2: short\n"
- " hello: int tuple[2]\n"
+ " Parameters\n"
+ " ----------\n"
+ " e: A *\n"
+ " arg2: short\n"
+ " hello: int tuple[2]\n"
"\n"
" ",
"\n"
"func2static(e, arg2, hello, f=2) -> int\n"
"\n"
- "Parameters:\n"
- " e: A *\n"
- " arg2: short\n"
- " hello: int tuple[2]\n"
- " f: double\n"
+ "Parameters\n"
+ "----------\n"
+ "e: A *\n"
+ "arg2: short\n"
+ "hello: int tuple[2]\n"
+ "f: double\n"
"\n"
"func2static(e, arg2, hello) -> int\n"
"\n"
- "Parameters:\n"
- " e: A *\n"
- " arg2: short\n"
- " hello: int tuple[2]\n"
+ "Parameters\n"
+ "----------\n"
+ "e: A *\n"
+ "arg2: short\n"
+ "hello: int tuple[2]\n"
"\n"
""
)
@@ -221,35 +237,39 @@ check(A.func3static.__doc__,
"\n"
" func3static(A e, short arg2, Tuple hello, double f=2) -> int\n"
"\n"
- " Parameters:\n"
- " e: A *\n"
- " arg2: short\n"
- " hello: int tuple[2]\n"
- " f: double\n"
+ " Parameters\n"
+ " ----------\n"
+ " e: A *\n"
+ " arg2: short\n"
+ " hello: int tuple[2]\n"
+ " f: double\n"
"\n"
" func3static(A e, short arg2, Tuple hello) -> int\n"
"\n"
- " Parameters:\n"
- " e: A *\n"
- " arg2: short\n"
- " hello: int tuple[2]\n"
+ " Parameters\n"
+ " ----------\n"
+ " e: A *\n"
+ " arg2: short\n"
+ " hello: int tuple[2]\n"
"\n"
" ",
"\n"
"func3static(A e, short arg2, Tuple hello, double f=2) -> int\n"
"\n"
- "Parameters:\n"
- " e: A *\n"
- " arg2: short\n"
- " hello: int tuple[2]\n"
- " f: double\n"
+ "Parameters\n"
+ "----------\n"
+ "e: A *\n"
+ "arg2: short\n"
+ "hello: int tuple[2]\n"
+ "f: double\n"
"\n"
"func3static(A e, short arg2, Tuple hello) -> int\n"
"\n"
- "Parameters:\n"
- " e: A *\n"
- " arg2: short\n"
- " hello: int tuple[2]\n"
+ "Parameters\n"
+ "----------\n"
+ "e: A *\n"
+ "arg2: short\n"
+ "hello: int tuple[2]\n"
"\n"
""
)
@@ -268,8 +288,9 @@ if sys.version_info[0:2] > (2, 4):
"\n"
"A_variable_c_get(self) -> int\n"
"\n"
- "Parameters:\n"
- " self: A *\n"
+ "Parameters\n"
+ "----------\n"
+ "self: A *\n"
"\n",
"A.variable_c"
)
@@ -277,14 +298,15 @@ if sys.version_info[0:2] > (2, 4):
"\n"
"A_variable_d_get(A self) -> int\n"
"\n"
- "Parameters:\n"
- " self: A *\n"
+ "Parameters\n"
+ "----------\n"
+ "self: A *\n"
"\n",
"A.variable_d"
)
check(B.__doc__,
- "Proxy of C++ B class",
+ "Proxy of C++ B class.",
"::B"
)
check(C.__init__.__doc__, "__init__(self, a, b, h) -> C", None, skip)
@@ -294,10 +316,11 @@ check(E.__init__.__doc__,
"\n"
" __init__(self, a, b, h) -> E\n"
"\n"
- " Parameters:\n"
- " a: special comment for parameter a\n"
- " b: another special comment for parameter b\n"
- " h: enum Hola\n"
+ " Parameters\n"
+ " ----------\n"
+ " a: special comment for parameter a\n"
+ " b: another special comment for parameter b\n"
+ " h: enum Hola\n"
"\n"
" ", None, skip
)
@@ -305,10 +328,11 @@ check(F.__init__.__doc__,
"\n"
" __init__(F self, int a, int b, Hola h) -> F\n"
"\n"
- " Parameters:\n"
- " a: special comment for parameter a\n"
- " b: another special comment for parameter b\n"
- " h: enum Hola\n"
+ " Parameters\n"
+ " ----------\n"
+ " a: special comment for parameter a\n"
+ " b: another special comment for parameter b\n"
+ " h: enum Hola\n"
"\n"
" ", None, skip
)
diff --git a/Examples/test-suite/python/char_binary_runme.py b/Examples/test-suite/python/char_binary_runme.py
index 13457253f..34caa3208 100644
--- a/Examples/test-suite/python/char_binary_runme.py
+++ b/Examples/test-suite/python/char_binary_runme.py
@@ -4,9 +4,14 @@ t = Test()
if t.strlen('hile') != 4:
print t.strlen('hile')
raise RuntimeError, "bad multi-arg typemap"
+if t.ustrlen('hile') != 4:
+ print t.ustrlen('hile')
+ raise RuntimeError, "bad multi-arg typemap"
if t.strlen('hil\0') != 4:
raise RuntimeError, "bad multi-arg typemap"
+if t.ustrlen('hil\0') != 4:
+ raise RuntimeError, "bad multi-arg typemap"
#
# creating a raw char*
@@ -21,6 +26,8 @@ pchar_setitem(pc, 4, 0)
if t.strlen(pc) != 4:
raise RuntimeError, "bad multi-arg typemap"
+if t.ustrlen(pc) != 4:
+ raise RuntimeError, "bad multi-arg typemap"
cvar.var_pchar = pc
if cvar.var_pchar != "hola":
diff --git a/Examples/test-suite/scilab/Makefile.in b/Examples/test-suite/scilab/Makefile.in
index 4a9a4f007..9ddd8f1aa 100644
--- a/Examples/test-suite/scilab/Makefile.in
+++ b/Examples/test-suite/scilab/Makefile.in
@@ -62,7 +62,7 @@ setup = \
mkdir $(TEST_DIR); \
fi; \
if [ -f $(SRC_RUNME_SCRIPT) ]; then \
- echo "$(ACTION)ing testcase $* (with run test) under $(LANGUAGE)" ; \
+ echo "$(ACTION)ing $(LANGUAGE) testcase $* (with run test)" ; \
if [ ! -f $(TEST_DIR) ]; then \
cp $(SRC_RUNME_SCRIPT) $(TEST_DIR); \
fi; \
@@ -73,7 +73,7 @@ setup = \
cp $(srcdir)/swigtest.quit $(TEST_DIR); \
fi; \
else \
- echo "$(ACTION)ing testcase $* under $(LANGUAGE)" ; \
+ echo "$(ACTION)ing $(LANGUAGE) testcase $*" ; \
fi; \
# Runs the testcase. A testcase is only run if
diff --git a/Lib/java/java.swg b/Lib/java/java.swg
index 2e106796c..0ff487d80 100644
--- a/Lib/java/java.swg
+++ b/Lib/java/java.swg
@@ -1330,8 +1330,8 @@ SWIG_PROXY_CONSTRUCTOR(true, true, SWIGTYPE)
%typemap(freearg) (char *STRING, size_t LENGTH) ""
%typemap(in) (char *STRING, size_t LENGTH) {
if ($input) {
- $1 = (char *) JCALL2(GetByteArrayElements, jenv, $input, 0);
- $2 = (size_t) JCALL1(GetArrayLength, jenv, $input);
+ $1 = ($1_ltype) JCALL2(GetByteArrayElements, jenv, $input, 0);
+ $2 = ($2_type) JCALL1(GetArrayLength, jenv, $input);
} else {
$1 = 0;
$2 = 0;
diff --git a/Lib/perl5/perlprimtypes.swg b/Lib/perl5/perlprimtypes.swg
index d7ac6f94e..6dd18b61f 100644
--- a/Lib/perl5/perlprimtypes.swg
+++ b/Lib/perl5/perlprimtypes.swg
@@ -37,7 +37,7 @@ SWIGINTERNINLINE SV *
SWIG_From_dec(long)(long value)
{
SV *sv;
- if (value >= IV_MIN && value <= IV_MAX)
+ if (IVSIZE >= sizeof(value) || (value >= IV_MIN && value <= IV_MAX))
sv = newSViv(value);
else
sv = newSVpvf("%ld", value);
@@ -46,20 +46,22 @@ SWIG_From_dec(long)(long value)
}
%fragment(SWIG_AsVal_frag(long),"header",
+ fragment="<limits.h>",
+ fragment="<stdlib.h>",
fragment="SWIG_CanCastAsInteger") {
SWIGINTERN int
SWIG_AsVal_dec(long)(SV *obj, long* val)
{
if (SvUOK(obj)) {
UV v = SvUV(obj);
- if (v <= LONG_MAX) {
+ if (UVSIZE < sizeof(*val) || v <= LONG_MAX) {
if (val) *val = v;
return SWIG_OK;
}
return SWIG_OverflowError;
} else if (SvIOK(obj)) {
IV v = SvIV(obj);
- if (v >= LONG_MIN && v <= LONG_MAX) {
+ if (IVSIZE <= sizeof(*val) || (v >= LONG_MIN && v <= LONG_MAX)) {
if(val) *val = v;
return SWIG_OK;
}
@@ -102,7 +104,7 @@ SWIGINTERNINLINE SV *
SWIG_From_dec(unsigned long)(unsigned long value)
{
SV *sv;
- if (value <= UV_MAX)
+ if (UVSIZE >= sizeof(value) || value <= UV_MAX)
sv = newSVuv(value);
else
sv = newSVpvf("%lu", value);
@@ -111,20 +113,22 @@ SWIG_From_dec(unsigned long)(unsigned long value)
}
%fragment(SWIG_AsVal_frag(unsigned long),"header",
+ fragment="<limits.h>",
+ fragment="<stdlib.h>",
fragment="SWIG_CanCastAsInteger") {
SWIGINTERN int
SWIG_AsVal_dec(unsigned long)(SV *obj, unsigned long *val)
{
if (SvUOK(obj)) {
UV v = SvUV(obj);
- if (v <= ULONG_MAX) {
+ if (UVSIZE <= sizeof(*val) || v <= ULONG_MAX) {
if (val) *val = v;
return SWIG_OK;
}
return SWIG_OverflowError;
} else if (SvIOK(obj)) {
IV v = SvIV(obj);
- if (v >= 0 && v <= ULONG_MAX) {
+ if (v >= 0 && (IVSIZE <= sizeof(*val) || v <= ULONG_MAX)) {
if (val) *val = v;
return SWIG_OK;
}
@@ -164,13 +168,12 @@ SWIG_AsVal_dec(unsigned long)(SV *obj, unsigned long *val)
%fragment(SWIG_From_frag(long long),"header",
fragment=SWIG_From_frag(long),
- fragment="<limits.h>",
fragment="<stdio.h>") {
SWIGINTERNINLINE SV *
SWIG_From_dec(long long)(long long value)
{
SV *sv;
- if (value >= IV_MIN && value <= IV_MAX)
+ if (IVSIZE >= sizeof(value) || (value >= IV_MIN && value <= IV_MAX))
sv = newSViv((IV)(value));
else {
//sv = newSVpvf("%lld", value); doesn't work in non 64bit Perl
@@ -192,14 +195,15 @@ SWIG_AsVal_dec(long long)(SV *obj, long long *val)
{
if (SvUOK(obj)) {
UV v = SvUV(obj);
- if (v < LLONG_MAX) {
+ /* pretty sure this could allow v == LLONG MAX */
+ if (UVSIZE < sizeof(*val) || v < LLONG_MAX) {
if (val) *val = v;
return SWIG_OK;
}
return SWIG_OverflowError;
} else if (SvIOK(obj)) {
IV v = SvIV(obj);
- if (v >= LLONG_MIN && v <= LLONG_MAX) {
+ if (IVSIZE <= sizeof(*val) || (v >= LLONG_MIN && v <= LLONG_MAX)) {
if (val) *val = v;
return SWIG_OK;
}
@@ -241,13 +245,12 @@ SWIG_AsVal_dec(long long)(SV *obj, long long *val)
%fragment(SWIG_From_frag(unsigned long long),"header",
fragment=SWIG_From_frag(long long),
- fragment="<limits.h>",
fragment="<stdio.h>") {
SWIGINTERNINLINE SV *
SWIG_From_dec(unsigned long long)(unsigned long long value)
{
SV *sv;
- if (value <= UV_MAX)
+ if (UVSIZE >= sizeof(value) || value <= UV_MAX)
sv = newSVuv((UV)(value));
else {
//sv = newSVpvf("%llu", value); doesn't work in non 64bit Perl
@@ -267,11 +270,13 @@ SWIGINTERN int
SWIG_AsVal_dec(unsigned long long)(SV *obj, unsigned long long *val)
{
if (SvUOK(obj)) {
+ /* pretty sure this should be conditional on
+ * (UVSIZE <= sizeof(*val) || v <= ULLONG_MAX) */
if (val) *val = SvUV(obj);
return SWIG_OK;
} else if (SvIOK(obj)) {
IV v = SvIV(obj);
- if (v >= 0 && v <= ULLONG_MAX) {
+ if (v >= 0 && (IVSIZE <= sizeof(*val) || v <= ULLONG_MAX)) {
if (val) *val = v;
return SWIG_OK;
} else {
diff --git a/README b/README
index a02c56ea9..e3f15e4da 100644
--- a/README
+++ b/README
@@ -1,6 +1,6 @@
SWIG (Simplified Wrapper and Interface Generator)
-Version: 3.0.7 (in progress)
+Version: 3.0.8 (in progress)
Tagline: SWIG is a compiler that integrates C and C++ with languages
including Perl, Python, Tcl, Ruby, PHP, Java, C#, D, Go, Lua,
diff --git a/RELEASENOTES b/RELEASENOTES
index bb1d82bb9..895caa2dd 100644
--- a/RELEASENOTES
+++ b/RELEASENOTES
@@ -4,6 +4,14 @@ and CHANGES files.
Release Notes
=============
+Detailed release notes are available with the release and are also
+published on the SWIG web site at http://swig.org/release.html.
+
+SWIG-3.0.7 summary:
+- Add support for Octave-4.0.0.
+- Remove potential Android security exploit in generated Java classes.
+- Minor new features and bug fixes.
+
SWIG-3.0.6 summary:
- Stability and regression fixes.
- Fixed parsing of C++ corner cases.
diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx
index 5670d9581..362a40929 100644
--- a/Source/Modules/python.cxx
+++ b/Source/Modules/python.cxx
@@ -799,7 +799,11 @@ public:
Swig_register_filebyname("python", f_shadow);
if (mod_docstring && Len(mod_docstring)) {
- Printv(f_shadow, "\"\"\"\n", mod_docstring, "\n\"\"\"\n\n", NIL);
+ const char *triple_double = "\"\"\"";
+ // follow PEP257 rules: https://www.python.org/dev/peps/pep-0257/
+ // reported by pep257: https://github.com/GreenSteam/pep257
+ const bool multi_line_ds = Strchr(mod_docstring, '\n');
+ Printv(f_shadow, triple_double, multi_line_ds?"\n":"", mod_docstring, multi_line_ds?"\n":"", triple_double, "\n\n", NIL);
Delete(mod_docstring);
mod_docstring = NULL;
}
@@ -1795,8 +1799,9 @@ public:
Append(doc, name);
if (pdoc) {
if (!pdocs)
- pdocs = NewString("\nParameters:\n");
- Printf(pdocs, " %s\n", pdoc);
+ // numpydoc style: https://github.com/numpy/numpy/blob/master/doc/HOWTO_DOCUMENT.rst.txt
+ pdocs = NewString("\nParameters\n----------\n");
+ Printf(pdocs, "%s\n", pdoc);
}
// Write the function annotation
if (func_annotation)
@@ -1892,9 +1897,9 @@ public:
Delete(rname);
} else {
if (CPlusPlus) {
- Printf(doc, "Proxy of C++ %s class", real_classname);
+ Printf(doc, "Proxy of C++ %s class.", real_classname);
} else {
- Printf(doc, "Proxy of C %s struct", real_classname);
+ Printf(doc, "Proxy of C %s struct.", real_classname);
}
}
}
@@ -4329,7 +4334,7 @@ public:
if (have_docstring(n)) {
String *str = docstring(n, AUTODOC_CLASS, tab4);
if (str && Len(str))
- Printv(f_shadow, tab4, str, "\n", NIL);
+ Printv(f_shadow, tab4, str, "\n\n", NIL);
}
if (!modern) {
diff --git a/Tools/nuget-install.cmd b/Tools/nuget-install.cmd
new file mode 100644
index 000000000..08caea7e0
--- /dev/null
+++ b/Tools/nuget-install.cmd
@@ -0,0 +1,28 @@
+rem Workaround 'nuget install' not being reliable by retrying a few times
+
+@echo off
+rem initiate the retry number
+set errorCode=1
+set retryNumber=0
+set maxRetries=5
+
+:RESTORE
+nuget install %*
+
+rem problem?
+IF ERRORLEVEL %errorCode% GOTO :RETRY
+
+rem everything is fine!
+GOTO :EXIT
+
+:RETRY
+@echo Oops, nuget restore exited with code %errorCode% - let us try again!
+set /a retryNumber=%retryNumber%+1
+IF %reTryNumber% LSS %maxRetries% (GOTO :RESTORE)
+IF %retryNumber% EQU %maxRetries% (GOTO :ERR)
+
+:ERR
+@echo Sorry, we tried restoring nuget packages for %maxRetries% times and all attempts were unsuccessful!
+EXIT /B 1
+
+:EXIT
diff --git a/appveyor.yml b/appveyor.yml
index dc96d0bca..1e60c37d4 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -46,7 +46,7 @@ install:
- ps: $env:VSCOMNTOOLS=(Get-Content ("env:VS" + "$env:VSVER" + "0COMNTOOLS"))
- echo "Using Visual Studio %VSVER%.0 at %VSCOMNTOOLS%"
- call "%VSCOMNTOOLS%\..\..\VC\vcvarsall.bat" %VCVARS_PLATFORM%
-- nuget install pcre -Verbosity detailed -Version 8.33.0.1 -OutputDirectory C:\pcre
+- Tools\nuget-install.cmd pcre -Verbosity detailed -Version 8.33.0.1 -OutputDirectory C:\pcre
- set PCRE_ROOT=C:/pcre/pcre.8.33.0.1/build/native
- set PATH=C:\Python%VER%%LANG_PLATFORM%;%PATH%
- python -V
diff --git a/configure.ac b/configure.ac
index 6d4505875..74235204e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2,7 +2,7 @@ dnl Process this file with autoconf to produce a configure script.
dnl The macros which aren't shipped with the autotools are stored in the
dnl Tools/config directory in .m4 files.
-AC_INIT([swig],[3.0.7],[http://www.swig.org])
+AC_INIT([swig],[3.0.8],[http://www.swig.org])
dnl NB: When this requirement is increased to 2.60 or later, AC_PROG_SED
dnl definition below can be removed