Merge branch 'nested' - nested structs/classes support
* nested: Deprecation of the 'nestedworkaround' feature Ensure -c++out is not used with -c++ Add missing header to new source file Nested C class setters restored in c++out mode for Octave Classprefix fixed after private nested classes some comments and spaces added Fix template partial specialization detection Minor tweaks in Swig_feature_set Swig_offset_string moved to misc.c nested private classes are discarded while parsing nested relate functions are moved to nested.cxx and renamed accordingly out-of-scope template definitions fixed nested_private test disabled again fixed out-of-scope nested class definitions, added a test enabled nested C structs assignment (still disabled for Octave), added Java runtime test fixed nested_private test case for Java & C# Testcase of private nested class usage causing segfault C nested struct passed by value example Add in Travis testing for nested branch Add C++ nested class example Minor code improvements Cosmetics/code beautification of nested class support Nested classes support
This commit is contained in:
commit
314fae460b
61 changed files with 2438 additions and 1127 deletions
|
|
@ -185,7 +185,6 @@ The following C++ features are not currently supported:</p>
|
|||
|
||||
<ul>
|
||||
<li>Overloaded versions of certain operators (new, delete, etc.)
|
||||
<li>Nested classes, see <a href="#SWIGPlus_nested_classes">Nested classes</a> for workarounds.
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
|
|
@ -4965,143 +4964,56 @@ public:
|
|||
|
||||
<H2><a name="SWIGPlus_nested_classes"></a>6.27 Nested classes</H2>
|
||||
|
||||
|
||||
<p>
|
||||
There is some support for nested structs and unions when wrapping C code,
|
||||
see <a href="SWIG.html#SWIG_nested_structs">Nested structures</a> for further details.
|
||||
The added complexity of C++ compared to C means this approach does not work well for
|
||||
C++ code (when using the -c++ command line option).
|
||||
For C++, a nested class is treated much like an opaque pointer, so anything useful within the nested class, such as its
|
||||
methods and variables, are not accessible from the target language.
|
||||
True nested class support may be added to SWIG in the future, however,
|
||||
until then some of the following workarounds can be applied to improve the situation.
|
||||
If the target language supports the nested classes concept (like Java), the nested C++ classes
|
||||
are wrapped as nested target language proxy classes. (In case of Java - "static" nested classes.)
|
||||
Only public nested classes are wrapped. Otherwise there is little difference between nested and
|
||||
normal classes.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
It might be possible to use partial class information as often you can accept that the nested class is not needed,
|
||||
especially if it is not actually used in any methods you need from the target language.
|
||||
Imagine you are wrapping the following <tt>Outer</tt> class which contains a nested class <tt>Inner</tt>.
|
||||
The easiest thing to do is turn a blind eye to the warning that SWIG generates, or simply suppress it:
|
||||
If the target language doesn't support nested classes directly, or the support is not implemented in the
|
||||
language module (like for python currently), then the visible nested classes are moved to the same name
|
||||
space as the containing class (nesting hierarchy is "flattened"). The same behaviour may be turned on for
|
||||
C# and Java by the %feature ("flatnested"); If there is a class with the same name in the outer namespace
|
||||
the inner class (or the global one) may be renamed or ignored:
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
<pre>
|
||||
%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Outer::Inner;
|
||||
|
||||
class Outer {
|
||||
public:
|
||||
class Inner {
|
||||
public:
|
||||
...
|
||||
};
|
||||
Inner getInner();
|
||||
void useInner(const Inner& inner);
|
||||
...
|
||||
};
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
Note that if <tt>Inner</tt> can be used as an opaque type, the default wrapping approach suffices.
|
||||
For example, if the nested class does not need to be created from the target language, but can be obtained via a method
|
||||
call, such as the <tt>getInner()</tt> method above, the returned value can then be passed around, such as passed into the
|
||||
<tt>useInner()</tt> method.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
With some more effort the above situation can be improved somewhat and a nested class can be constructed and used
|
||||
from the target language much like any other non-nested class. Assuming we have the <tt>Outer</tt> class in a header file:
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
<pre>
|
||||
// File outer.h
|
||||
class Outer {
|
||||
public:
|
||||
class Inner {
|
||||
public:
|
||||
int var;
|
||||
Inner(int v = 0) : var(v) {}
|
||||
};
|
||||
Inner getInner();
|
||||
void useInner(const Inner& inner);
|
||||
};
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
The following interface file works around the nested class limitations by redefining the nested class as a global class.
|
||||
A typedef for the compiler and the <tt>nestedworkaround</tt>
|
||||
<a href="Customization.html#Customization_feature_flags">feature flag</a> is also required in
|
||||
order for the generated wrappers to compile. This flag simply removes all the type information from SWIG, so SWIG treats
|
||||
the nested class as if it had not been parsed at all.
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
<pre>
|
||||
// File : example.i
|
||||
%module example
|
||||
|
||||
// Redefine nested class in global scope in order for SWIG to generate
|
||||
// a proxy class. Only SWIG parses this definition.
|
||||
class Inner {
|
||||
%rename (Bar_Foo) Bar::Foo;
|
||||
class Foo {};
|
||||
class Bar {
|
||||
public:
|
||||
int var;
|
||||
Inner(int v = 0) : var(v) {}
|
||||
class Foo {};
|
||||
};
|
||||
|
||||
%nestedworkaround Outer::Inner;
|
||||
|
||||
%{
|
||||
#include "outer.h"
|
||||
%}
|
||||
%include "outer.h"
|
||||
|
||||
// We've fooled SWIG into thinking that Inner is a global class, so now we need
|
||||
// to trick the C++ compiler into understanding this apparent global type.
|
||||
%{
|
||||
typedef Outer::Inner Inner;
|
||||
%}
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
The downside to this approach is a more complex interface file and having to maintain two definitions of <tt>Inner</tt>,
|
||||
the real one and the one in the interface file that SWIG parses.
|
||||
However, the upside is that all the methods/variables in the nested class are available from the target language
|
||||
as a proxy class is generated instead of treating the nested class as an opaque type.
|
||||
The proxy class can be constructed from the target language and passed into any methods accepting the nested class.
|
||||
Also note that the original header file is parsed unmodified.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Finally, conditional compilation can be used as a workaround to comment out nested class definitions in the actual headers,
|
||||
assuming you are able to modify them.
|
||||
<b>Compatibility Note:</b>
|
||||
Prior to SWIG-3.0.0, there was limited nested class support. Nested classes were treated as opaque pointers.
|
||||
However, there was a workaround for nested class support in these older versions requiring the user to replicate
|
||||
the nested class in the global scope, adding in a typedef for the nested class in the global scope and
|
||||
using the "nestedworkaround" feature on the nested class. This resulted in approximately the
|
||||
same behaviour as the "flatnested" feature. With proper nested class support now available in SWIG-3.0.0, this
|
||||
feature has been deprecated and no longer works requiring code changes. If you see the following warning:
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
<div class="shell">
|
||||
<pre>
|
||||
// File outer.h
|
||||
class Outer {
|
||||
public:
|
||||
#ifndef SWIG
|
||||
class Inner {
|
||||
public:
|
||||
...
|
||||
};
|
||||
#endif
|
||||
...
|
||||
};
|
||||
example.i:8: Warning 126: The nestedworkaround feature is deprecated
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
This workaround used to be common when SWIG could not deal with nested classes particulary well.
|
||||
This should just be a last resort for unusual corner cases now as SWIG can parse nested classes and even handle nested template classes fairly well.
|
||||
consider using the "flatnested" feature discussed above which generates a non-nested proxy class, like the
|
||||
"nestedworkaround" feature did. Alternatively, use the default nested class code generation, which may generate an
|
||||
equivalent to a nested proxy class in the target language, depending on the target language support.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b>Compatibility Note:</b> SWIG-1.3.40 and earlier versions did not have the <tt>nestedworkaround</tt> feature
|
||||
SWIG-1.3.40 and earlier versions did not have the <tt>nestedworkaround</tt> feature
|
||||
and the generated code resulting from parsing nested classes did not always compile.
|
||||
Nested class warnings could also not be suppressed using %warnfilter.
|
||||
</p>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue