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:
William S Fulton 2013-12-14 15:12:07 +00:00
commit 314fae460b
61 changed files with 2435 additions and 1124 deletions

View file

@ -57,3 +57,4 @@ script:
branches:
only:
- master
- nested

View file

@ -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&amp; 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&amp; 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>

View file

@ -382,6 +382,7 @@ example.i(4) : Syntax error in input.
<li>119. Deprecated <tt>%typemap(ignore)</tt>.
<li>120. Deprecated command line option (-runtime, -noruntime).
<li>121. Deprecated <tt>%name</tt> directive.
<li>126. The 'nestedworkaround' feature is deprecated.
</ul>
<H3><a name="Warnings_nn11"></a>14.9.2 Preprocessor (200-299)</H3>

View file

@ -5,6 +5,7 @@ class
enum
extend
funcptr
nested
reference
simple
template

View file

@ -0,0 +1,19 @@
TOP = ../..
SWIG = $(TOP)/../preinst-swig
CXXSRCS = example.cxx
TARGET = example
INTERFACE = example.i
SWIGOPT =
CSHARPSRCS = *.cs
CSHARPFLAGS= -nologo -out:runme.exe
check: build
$(MAKE) -f $(TOP)/Makefile csharp_run
build:
$(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \
SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' csharp_cpp
$(MAKE) -f $(TOP)/Makefile CSHARPSRCS='$(CSHARPSRCS)' CSHARPFLAGS='$(CSHARPFLAGS)' csharp_compile
clean:
$(MAKE) -f $(TOP)/Makefile csharp_clean

View file

@ -0,0 +1,94 @@
<VisualStudioProject>
<CSHARP
ProjectType = "Local"
ProductVersion = "7.10.3077"
SchemaVersion = "2.0"
ProjectGuid = "{C17D27DF-4C57-4625-AEE0-A40C4F48FF1A}"
>
<Build>
<Settings
ApplicationIcon = ""
AssemblyKeyContainerName = ""
AssemblyName = "runme"
AssemblyOriginatorKeyFile = ""
DefaultClientScript = "JScript"
DefaultHTMLPageLayout = "Grid"
DefaultTargetSchema = "IE50"
DelaySign = "false"
OutputType = "Exe"
PreBuildEvent = ""
PostBuildEvent = ""
RootNamespace = "runme"
RunPostBuildEvent = "OnBuildSuccess"
StartupObject = ""
>
<Config
Name = "Debug"
AllowUnsafeBlocks = "false"
BaseAddress = "285212672"
CheckForOverflowUnderflow = "false"
ConfigurationOverrideFile = ""
DefineConstants = "DEBUG;TRACE"
DocumentationFile = ""
DebugSymbols = "true"
FileAlignment = "4096"
IncrementalBuild = "false"
NoStdLib = "false"
NoWarn = ""
Optimize = "false"
OutputPath = ".\"
RegisterForComInterop = "false"
RemoveIntegerChecks = "false"
TreatWarningsAsErrors = "false"
WarningLevel = "4"
/>
<Config
Name = "Release"
AllowUnsafeBlocks = "false"
BaseAddress = "285212672"
CheckForOverflowUnderflow = "false"
ConfigurationOverrideFile = ""
DefineConstants = "TRACE"
DocumentationFile = ""
DebugSymbols = "false"
FileAlignment = "4096"
IncrementalBuild = "false"
NoStdLib = "false"
NoWarn = ""
Optimize = "true"
OutputPath = ".\"
RegisterForComInterop = "false"
RemoveIntegerChecks = "false"
TreatWarningsAsErrors = "false"
WarningLevel = "4"
/>
</Settings>
<References/>
</Build>
<Files>
<Include>
<File
RelPath = "example.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "examplePINVOKE.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "MotorCar.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "runme.cs"
SubType = "Code"
BuildAction = "Compile"
/>
</Include>
</Files>
</CSHARP>
</VisualStudioProject>

View file

@ -0,0 +1,158 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="example"
ProjectGUID="{C2302635-D489-4678-96B4-70F5309DCBE6}"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="Debug"
IntermediateDirectory="Debug"
ConfigurationType="2"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;EXAMPLEVC_EXPORTS"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
OutputFile="example.dll"
LinkIncremental="2"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/example.pdb"
SubSystem="2"
ImportLibrary="$(OutDir)/example.lib"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="Release"
IntermediateDirectory="Release"
ConfigurationType="2"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;EXAMPLEVC_EXPORTS"
RuntimeLibrary="0"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
OutputFile="example.dll"
LinkIncremental="1"
GenerateDebugInformation="TRUE"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
ImportLibrary="$(OutDir)/example.lib"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
<File
RelativePath="example.cxx">
</File>
<File
RelativePath="example_wrap.cxx">
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
<File
RelativePath="example.h">
</File>
</Filter>
<File
RelativePath=".\example.i">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCustomBuildTool"
CommandLine="echo Invoking SWIG...
echo on
..\..\..\swig.exe -c++ -csharp &quot;$(InputPath)&quot;
@echo off"
Outputs="$(InputName)_wrap.cxx"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCustomBuildTool"
CommandLine="echo Invoking SWIG...
echo on
..\..\..\swig.exe -c++ -csharp &quot;$(InputPath)&quot;
@echo off"
Outputs="$(InputName)_wrap.cxx"/>
</FileConfiguration>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View file

@ -0,0 +1,62 @@
#include "example.h"
int MotorCar::DesignOpinion::AceDesignCount = 0;
int MotorCar::DesignOpinion::TotalDesignCount = 0;
int MotorCar::DesignOpinion::PercentScore() {
return AceDesignCount*100/TotalDesignCount;
}
MotorCar::Wheels::Wheels(Shape shape, size_t count) : shape(shape), count(count) {}
MotorCar::WindScreen::WindScreen(bool opaque) : opaque(opaque) {}
MotorCar::MotorCar(const std::string &name, const Wheels &wheels, const WindScreen &windscreen) : name(name), wheels(wheels), windscreen(windscreen) {}
MotorCar MotorCar::DesignFromComponents(const std::string &name, const Wheels &wheels, const WindScreen &windscreen) {
MotorCar car = MotorCar(name, wheels, windscreen);
DesignOpinion::TotalDesignCount++;
if (car.wheels.Opinion().itrocks && car.windscreen.Opinion().itrocks)
DesignOpinion::AceDesignCount++;
return car;
}
MotorCar::DesignOpinion MotorCar::Wheels::Opinion() {
DesignOpinion opinion;
opinion.itrocks = true;
if (shape == Square) {
opinion.itrocks = false;
opinion.reason = "you'll have a few issues with wheel rotation";
}
if (count <= 2) {
opinion.reason += opinion.itrocks ? "" : " and ";
opinion.itrocks = false;
opinion.reason += "a few more wheels are needed for stability";
}
if (opinion.itrocks)
opinion.reason = "your choice of wheels was top notch";
return opinion;
}
MotorCar::DesignOpinion MotorCar::WindScreen::Opinion() {
DesignOpinion opinion;
opinion.itrocks = !opaque;
opinion.reason = opinion.itrocks ? "the driver will have a commanding view out the window" : "you can't see out the windscreen";
return opinion;
}
std::string MotorCar::WillItWork() {
DesignOpinion wh = wheels.Opinion();
DesignOpinion ws = windscreen.Opinion();
std::string willit;
if (wh.itrocks && ws.itrocks) {
willit = "Great car design because " + wh.reason + " and " + ws.reason;
} else {
willit = "You need a rethink because ";
willit += wh.itrocks ? "" : wh.reason;
willit += (!wh.itrocks && !ws.itrocks) ? " and " : "";
willit += ws.itrocks ? "" : ws.reason;
}
return willit;
}

View file

@ -0,0 +1,48 @@
#include <string>
/** Design a motor car from various components */
struct MotorCar {
/** Information about an opinion of the design of a car component */
struct DesignOpinion {
bool itrocks;
std::string reason;
static int AceDesignCount;
static int TotalDesignCount;
static int PercentScore();
};
/** Wheels component */
struct Wheels {
enum Shape { Round, Square };
Wheels(Shape shape, size_t count);
DesignOpinion Opinion();
private:
Shape shape;
size_t count;
};
/** Windscreen component */
struct WindScreen {
WindScreen(bool opaque);
DesignOpinion Opinion();
private:
bool opaque;
};
/** Factory method for creating a car */
static MotorCar DesignFromComponents(const std::string &name, const Wheels &wheels, const WindScreen &windscreen);
std::string Name() {
return name;
}
/** Get an overall opinion on the car design */
std::string WillItWork();
private:
MotorCar(const std::string &name, const Wheels &wheels, const WindScreen &windscreen);
std::string name;
Wheels wheels;
WindScreen windscreen;
};

View file

@ -0,0 +1,13 @@
%module example
// This example shows how wrappers for numerous aspects of C++ nested classes work:
// Nested static and instance variables and methods and nested enums
%include <std_string.i>
%{
#include "example.h"
%}
%include "example.h"

View file

@ -0,0 +1,30 @@
Microsoft Visual Studio Solution File, Format Version 8.00
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "example-cs", "example-cs.csproj", "{C17D27DF-4C57-4625-AEE0-A40C4F48FF1A}"
ProjectSection(ProjectDependencies) = postProject
{C2302635-D489-4678-96B4-70F5309DCBE6} = {C2302635-D489-4678-96B4-70F5309DCBE6}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example-vc", "example-vc.vcproj", "{C2302635-D489-4678-96B4-70F5309DCBE6}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfiguration) = preSolution
Debug = Debug
Release = Release
EndGlobalSection
GlobalSection(ProjectConfiguration) = postSolution
{C17D27DF-4C57-4625-AEE0-A40C4F48FF1A}.Debug.ActiveCfg = Debug|.NET
{C17D27DF-4C57-4625-AEE0-A40C4F48FF1A}.Debug.Build.0 = Debug|.NET
{C17D27DF-4C57-4625-AEE0-A40C4F48FF1A}.Release.ActiveCfg = Release|.NET
{C17D27DF-4C57-4625-AEE0-A40C4F48FF1A}.Release.Build.0 = Release|.NET
{C2302635-D489-4678-96B4-70F5309DCBE6}.Debug.ActiveCfg = Debug|Win32
{C2302635-D489-4678-96B4-70F5309DCBE6}.Debug.Build.0 = Debug|Win32
{C2302635-D489-4678-96B4-70F5309DCBE6}.Release.ActiveCfg = Release|Win32
{C2302635-D489-4678-96B4-70F5309DCBE6}.Release.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
EndGlobalSection
GlobalSection(ExtensibilityAddIns) = postSolution
EndGlobalSection
EndGlobal

View file

@ -0,0 +1,27 @@
// This example illustrates how C++ classes can be used from C# using SWIG.
// The C# class gets mapped onto the C++ class and behaves as if it is a C# class.
using System;
public class runme
{
static void Main()
{
MotorCar car1 = MotorCar.DesignFromComponents("Bumpy", new MotorCar.Wheels(MotorCar.Wheels.Shape.Square, 4), new MotorCar.WindScreen(false));
MotorCar car2 = MotorCar.DesignFromComponents("Wobbly", new MotorCar.Wheels(MotorCar.Wheels.Shape.Round, 2), new MotorCar.WindScreen(false));
MotorCar car3 = MotorCar.DesignFromComponents("Batty", new MotorCar.Wheels(MotorCar.Wheels.Shape.Round, 4), new MotorCar.WindScreen(true));
MotorCar car4 = MotorCar.DesignFromComponents("Spiffing", new MotorCar.Wheels(MotorCar.Wheels.Shape.Round, 4), new MotorCar.WindScreen(false));
Console.WriteLine("Expert opinion on " + car1.Name() + " : \n " + car1.WillItWork());
Console.WriteLine("Expert opinion on " + car2.Name() + " : \n " + car2.WillItWork());
Console.WriteLine("Expert opinion on " + car3.Name() + " : \n " + car3.WillItWork());
Console.WriteLine("Expert opinion on " + car4.Name() + " : \n " + car4.WillItWork());
int count = MotorCar.DesignOpinion.AceDesignCount;
int total = MotorCar.DesignOpinion.TotalDesignCount;
int percent = MotorCar.DesignOpinion.PercentScore();
Console.WriteLine("Overall opinion rating on car design is " + count + "/" + total + " = " + percent + "%");
Console.WriteLine("Single square wheel thoughts: " + new MotorCar.Wheels(MotorCar.Wheels.Shape.Square, 1).Opinion().reason);
}
}

View file

@ -7,6 +7,7 @@ extend
funcptr
multimap
native
nested
pointer
reference
simple

View file

@ -0,0 +1,18 @@
TOP = ../..
SWIG = $(TOP)/../preinst-swig
CXXSRCS = example.cxx
TARGET = example
INTERFACE = example.i
SWIGOPT =
JAVASRCS = *.java
check: build
$(MAKE) -f $(TOP)/Makefile java_run
build:
$(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \
SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' java_cpp
$(MAKE) -f $(TOP)/Makefile JAVASRCS='$(JAVASRCS)' JAVAFLAGS='$(JAVAFLAGS)' java_compile
clean:
$(MAKE) -f $(TOP)/Makefile java_clean

View file

@ -0,0 +1,62 @@
#include "example.h"
int MotorCar::DesignOpinion::AceDesignCount = 0;
int MotorCar::DesignOpinion::TotalDesignCount = 0;
int MotorCar::DesignOpinion::PercentScore() {
return AceDesignCount*100/TotalDesignCount;
}
MotorCar::Wheels::Wheels(Shape shape, size_t count) : shape(shape), count(count) {}
MotorCar::WindScreen::WindScreen(bool opaque) : opaque(opaque) {}
MotorCar::MotorCar(const std::string &name, const Wheels &wheels, const WindScreen &windscreen) : name(name), wheels(wheels), windscreen(windscreen) {}
MotorCar MotorCar::DesignFromComponents(const std::string &name, const Wheels &wheels, const WindScreen &windscreen) {
MotorCar car = MotorCar(name, wheels, windscreen);
DesignOpinion::TotalDesignCount++;
if (car.wheels.Opinion().itrocks && car.windscreen.Opinion().itrocks)
DesignOpinion::AceDesignCount++;
return car;
}
MotorCar::DesignOpinion MotorCar::Wheels::Opinion() {
DesignOpinion opinion;
opinion.itrocks = true;
if (shape == Square) {
opinion.itrocks = false;
opinion.reason = "you'll have a few issues with wheel rotation";
}
if (count <= 2) {
opinion.reason += opinion.itrocks ? "" : " and ";
opinion.itrocks = false;
opinion.reason += "a few more wheels are needed for stability";
}
if (opinion.itrocks)
opinion.reason = "your choice of wheels was top notch";
return opinion;
}
MotorCar::DesignOpinion MotorCar::WindScreen::Opinion() {
DesignOpinion opinion;
opinion.itrocks = !opaque;
opinion.reason = opinion.itrocks ? "the driver will have a commanding view out the window" : "you can't see out the windscreen";
return opinion;
}
std::string MotorCar::WillItWork() {
DesignOpinion wh = wheels.Opinion();
DesignOpinion ws = windscreen.Opinion();
std::string willit;
if (wh.itrocks && ws.itrocks) {
willit = "Great car design because " + wh.reason + " and " + ws.reason;
} else {
willit = "You need a rethink because ";
willit += wh.itrocks ? "" : wh.reason;
willit += (!wh.itrocks && !ws.itrocks) ? " and " : "";
willit += ws.itrocks ? "" : ws.reason;
}
return willit;
}

View file

@ -0,0 +1,162 @@
# Microsoft Developer Studio Project File - Name="example" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
CFG=example - Win32 Release
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "example.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "example.mak" CFG="example - Win32 Release"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "example - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "example - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
!IF "$(CFG)" == "example - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE_EXPORTS" /YX /FD /GZ /c
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "$(JAVA_INCLUDE)" /I "$(JAVA_INCLUDE)\win32" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE_EXPORTS" /YX /FD /GZ /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x809 /d "_DEBUG"
# ADD RSC /l 0x809 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /dll /debug /machine:I386 /out:"example.dll" /pdbtype:sept
# Begin Special Build Tool
SOURCE="$(InputPath)"
PostBuild_Desc=Java compile post-build step
PostBuild_Cmds=echo on "%JAVA_BIN%\javac" *.java
# End Special Build Tool
!ELSEIF "$(CFG)" == "example - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE_EXPORTS" /YX /FD /c
# ADD CPP /nologo /MT /W3 /GX /O2 /I "$(JAVA_INCLUDE)" /I "$(JAVA_INCLUDE)\win32" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE_EXPORTS" /YX /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x809 /d "NDEBUG"
# ADD RSC /l 0x809 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /dll /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /dll /machine:I386 /out:"example.dll"
# Begin Special Build Tool
SOURCE="$(InputPath)"
PostBuild_Desc=Java compile post-build step
PostBuild_Cmds=echo on "%JAVA_BIN%\javac" *.java
# End Special Build Tool
!ENDIF
# Begin Target
# Name "example - Win32 Debug"
# Name "example - Win32 Release"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=.\example.cxx
# End Source File
# Begin Source File
SOURCE=.\example_wrap.cxx
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=.\example.h
# End Source File
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# End Group
# Begin Source File
SOURCE=.\example.i
!IF "$(CFG)" == "example - Win32 Debug"
# Begin Custom Build
InputPath=.\example.i
InputName=example
"$(InputName)_wrap.cxx" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
echo In order to function correctly, please ensure the following environment variables are correctly set:
echo JAVA_INCLUDE: %JAVA_INCLUDE%
echo JAVA_BIN: %JAVA_BIN%
echo on
..\..\..\swig.exe -c++ -java "$(InputPath)"
# End Custom Build
!ELSEIF "$(CFG)" == "example - Win32 Release"
# Begin Custom Build
InputPath=.\example.i
InputName=example
"$(InputName)_wrap.cxx" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
echo In order to function correctly, please ensure the following environment variables are correctly set:
echo JAVA_INCLUDE: %JAVA_INCLUDE%
echo JAVA_BIN: %JAVA_BIN%
echo on
..\..\..\swig.exe -c++ -java "$(InputPath)"
# End Custom Build
!ENDIF
# End Source File
# End Target
# End Project

View file

@ -0,0 +1,48 @@
#include <string>
/** Design a motor car from various components */
struct MotorCar {
/** Information about an opinion of the design of a car component */
struct DesignOpinion {
bool itrocks;
std::string reason;
static int AceDesignCount;
static int TotalDesignCount;
static int PercentScore();
};
/** Wheels component */
struct Wheels {
enum Shape { Round, Square };
Wheels(Shape shape, size_t count);
DesignOpinion Opinion();
private:
Shape shape;
size_t count;
};
/** Windscreen component */
struct WindScreen {
WindScreen(bool opaque);
DesignOpinion Opinion();
private:
bool opaque;
};
/** Factory method for creating a car */
static MotorCar DesignFromComponents(const std::string &name, const Wheels &wheels, const WindScreen &windscreen);
std::string Name() {
return name;
}
/** Get an overall opinion on the car design */
std::string WillItWork();
private:
MotorCar(const std::string &name, const Wheels &wheels, const WindScreen &windscreen);
std::string name;
Wheels wheels;
WindScreen windscreen;
};

View file

@ -0,0 +1,13 @@
%module example
// This example shows how wrappers for numerous aspects of C++ nested classes work:
// Nested static and instance variables and methods and nested enums
%include <std_string.i>
%{
#include "example.h"
%}
%include "example.h"

View file

@ -0,0 +1,32 @@
// This example illustrates wrapping of nested C++ classes
public class runme {
static {
try {
System.loadLibrary("example");
} catch (UnsatisfiedLinkError e) {
System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e);
System.exit(1);
}
}
public static void main(String argv[])
{
MotorCar car1 = MotorCar.DesignFromComponents("Bumpy", new MotorCar.Wheels(MotorCar.Wheels.Shape.Square, 4), new MotorCar.WindScreen(false));
MotorCar car2 = MotorCar.DesignFromComponents("Wobbly", new MotorCar.Wheels(MotorCar.Wheels.Shape.Round, 2), new MotorCar.WindScreen(false));
MotorCar car3 = MotorCar.DesignFromComponents("Batty", new MotorCar.Wheels(MotorCar.Wheels.Shape.Round, 4), new MotorCar.WindScreen(true));
MotorCar car4 = MotorCar.DesignFromComponents("Spiffing", new MotorCar.Wheels(MotorCar.Wheels.Shape.Round, 4), new MotorCar.WindScreen(false));
System.out.println("Expert opinion on " + car1.Name() + " : \n " + car1.WillItWork());
System.out.println("Expert opinion on " + car2.Name() + " : \n " + car2.WillItWork());
System.out.println("Expert opinion on " + car3.Name() + " : \n " + car3.WillItWork());
System.out.println("Expert opinion on " + car4.Name() + " : \n " + car4.WillItWork());
int count = MotorCar.DesignOpinion.getAceDesignCount();
int total = MotorCar.DesignOpinion.getTotalDesignCount();
int percent = MotorCar.DesignOpinion.PercentScore();
System.out.println("Overall opinion rating on car design is " + count + "/" + total + " = " + percent + "%");
System.out.println("Single square wheel thoughts: " + new MotorCar.Wheels(MotorCar.Wheels.Shape.Square, 1).Opinion().getReason());
}
}

View file

@ -84,6 +84,7 @@ CPP_TEST_BROKEN += \
extend_variable \
li_std_vector_ptr \
li_boost_shared_ptr_template \
nested_private \
overload_complicated \
template_default_pointer \
template_expr \
@ -279,6 +280,7 @@ CPP_TEST_CASES += \
naturalvar_more \
nested_class \
nested_comment \
nested_scope \
nested_workaround \
newobject1 \
null_pointer \

Some files were not shown because too many files have changed in this diff Show more