From 5ea73416b53264ab3c8906699344751202f8bae4 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 13 May 2006 23:27:58 +0000 Subject: [PATCH] C# director support added git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@9102 626c5289-ae23-0410-ae9c-e8d60b6d4f22 --- SWIG/Examples/csharp/callback/.cvsignore | 14 ++ SWIG/Examples/csharp/callback/Makefile | 20 +++ .../csharp/callback/example-cs.csproj | 99 +++++++++++ .../csharp/callback/example-vc.vcproj | 158 ++++++++++++++++++ SWIG/Examples/csharp/callback/example.cxx | 4 + SWIG/Examples/csharp/callback/example.h | 24 +++ SWIG/Examples/csharp/callback/example.i | 13 ++ SWIG/Examples/csharp/callback/example.sln | 30 ++++ SWIG/Examples/csharp/callback/runme.cs | 46 +++++ SWIG/Examples/csharp/extend/.cvsignore | 19 +++ SWIG/Examples/csharp/extend/Makefile | 20 +++ SWIG/Examples/csharp/extend/example-cs.csproj | 104 ++++++++++++ SWIG/Examples/csharp/extend/example-vc.vcproj | 158 ++++++++++++++++++ SWIG/Examples/csharp/extend/example.cxx | 4 + SWIG/Examples/csharp/extend/example.h | 56 +++++++ SWIG/Examples/csharp/extend/example.i | 15 ++ SWIG/Examples/csharp/extend/example.sln | 30 ++++ SWIG/Examples/csharp/extend/main.java | 88 ++++++++++ SWIG/Examples/csharp/extend/runme.cs | 77 +++++++++ 19 files changed, 979 insertions(+) create mode 100644 SWIG/Examples/csharp/callback/.cvsignore create mode 100644 SWIG/Examples/csharp/callback/Makefile create mode 100644 SWIG/Examples/csharp/callback/example-cs.csproj create mode 100644 SWIG/Examples/csharp/callback/example-vc.vcproj create mode 100644 SWIG/Examples/csharp/callback/example.cxx create mode 100644 SWIG/Examples/csharp/callback/example.h create mode 100644 SWIG/Examples/csharp/callback/example.i create mode 100644 SWIG/Examples/csharp/callback/example.sln create mode 100644 SWIG/Examples/csharp/callback/runme.cs create mode 100644 SWIG/Examples/csharp/extend/.cvsignore create mode 100644 SWIG/Examples/csharp/extend/Makefile create mode 100644 SWIG/Examples/csharp/extend/example-cs.csproj create mode 100644 SWIG/Examples/csharp/extend/example-vc.vcproj create mode 100644 SWIG/Examples/csharp/extend/example.cxx create mode 100644 SWIG/Examples/csharp/extend/example.h create mode 100644 SWIG/Examples/csharp/extend/example.i create mode 100644 SWIG/Examples/csharp/extend/example.sln create mode 100644 SWIG/Examples/csharp/extend/main.java create mode 100644 SWIG/Examples/csharp/extend/runme.cs diff --git a/SWIG/Examples/csharp/callback/.cvsignore b/SWIG/Examples/csharp/callback/.cvsignore new file mode 100644 index 000000000..5357e1b11 --- /dev/null +++ b/SWIG/Examples/csharp/callback/.cvsignore @@ -0,0 +1,14 @@ +*.class +*.java +*_wrap.c +*_wrap.cxx +*_wrap.h +*.dll +*.dsw +*.exp +*.lib +*.ncb +*.opt +*.plg +Release +Debug diff --git a/SWIG/Examples/csharp/callback/Makefile b/SWIG/Examples/csharp/callback/Makefile new file mode 100644 index 000000000..51b163b85 --- /dev/null +++ b/SWIG/Examples/csharp/callback/Makefile @@ -0,0 +1,20 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +CXXSRCS = example.cxx +TARGET = example +INTERFACE = example.i +SWIGOPT = +CSHARPSRCS = *.cs +CSHARPFLAGS= -debug -nologo -out:runme.exe + +all:: csharp + +csharp:: + $(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 + +check: all diff --git a/SWIG/Examples/csharp/callback/example-cs.csproj b/SWIG/Examples/csharp/callback/example-cs.csproj new file mode 100644 index 000000000..5fc34527f --- /dev/null +++ b/SWIG/Examples/csharp/callback/example-cs.csproj @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/SWIG/Examples/csharp/callback/example-vc.vcproj b/SWIG/Examples/csharp/callback/example-vc.vcproj new file mode 100644 index 000000000..7c0b8ef13 --- /dev/null +++ b/SWIG/Examples/csharp/callback/example-vc.vcproj @@ -0,0 +1,158 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/SWIG/Examples/csharp/callback/example.cxx b/SWIG/Examples/csharp/callback/example.cxx new file mode 100644 index 000000000..450d75608 --- /dev/null +++ b/SWIG/Examples/csharp/callback/example.cxx @@ -0,0 +1,4 @@ +/* File : example.cxx */ + +#include "example.h" + diff --git a/SWIG/Examples/csharp/callback/example.h b/SWIG/Examples/csharp/callback/example.h new file mode 100644 index 000000000..38d25a043 --- /dev/null +++ b/SWIG/Examples/csharp/callback/example.h @@ -0,0 +1,24 @@ +/* File : example.h */ + +#include +#include + +class Callback { +public: + virtual ~Callback() { std::cout << "Callback::~Callback()" << std:: endl; } + virtual void run() { std::cout << "Callback::run()" << std::endl; } +}; + + +class Caller { +private: + Callback *_callback; +public: + Caller(): _callback(0) {} + ~Caller() { delCallback(); } + void delCallback() { delete _callback; _callback = 0; } + void setCallback(Callback *cb) { delCallback(); _callback = cb; } + void resetCallback() { _callback = 0; } + void call() { if (_callback) _callback->run(); } +}; + diff --git a/SWIG/Examples/csharp/callback/example.i b/SWIG/Examples/csharp/callback/example.i new file mode 100644 index 000000000..90beda01a --- /dev/null +++ b/SWIG/Examples/csharp/callback/example.i @@ -0,0 +1,13 @@ +/* File : example.i */ +%module(directors="1") example +%{ +#include "example.h" +%} + +%include "std_string.i" + +/* turn on director wrapping Callback */ +%feature("director") Callback; + +%include "example.h" + diff --git a/SWIG/Examples/csharp/callback/example.sln b/SWIG/Examples/csharp/callback/example.sln new file mode 100644 index 000000000..28b9851b0 --- /dev/null +++ b/SWIG/Examples/csharp/callback/example.sln @@ -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 diff --git a/SWIG/Examples/csharp/callback/runme.cs b/SWIG/Examples/csharp/callback/runme.cs new file mode 100644 index 000000000..a104b1a3e --- /dev/null +++ b/SWIG/Examples/csharp/callback/runme.cs @@ -0,0 +1,46 @@ +using System; + +public class runme +{ + static void Main() + { + Console.WriteLine("Adding and calling a normal C++ callback"); + Console.WriteLine("----------------------------------------"); + + Caller caller = new Caller(); + using (Callback callback = new Callback()) + { + caller.setCallback(callback); + caller.call(); + caller.resetCallback(); + } + + Console.WriteLine(); + Console.WriteLine("Adding and calling a C# callback"); + Console.WriteLine("------------------------------------"); + + using (Callback callback = new CSharpCallback()) + { + caller.setCallback(callback); + caller.call(); + caller.resetCallback(); + } + + Console.WriteLine(); + Console.WriteLine("C# exit"); + } +} + +public class CSharpCallback : Callback +{ + public CSharpCallback() + : base() + { + } + + public override void run() + { + Console.WriteLine("CSharpCallback.run()"); + } +} + diff --git a/SWIG/Examples/csharp/extend/.cvsignore b/SWIG/Examples/csharp/extend/.cvsignore new file mode 100644 index 000000000..4fa8caf32 --- /dev/null +++ b/SWIG/Examples/csharp/extend/.cvsignore @@ -0,0 +1,19 @@ +runme +*_wrap.c +*_wrap.cxx +*.iltmp +*.cs +*.dll +*.dsw +*.exp +*.ilk +*.lib +*.ncb +*.opt +*.plg +*.suo +*.pdb +example-cs.csproj.user +obj +Release +Debug diff --git a/SWIG/Examples/csharp/extend/Makefile b/SWIG/Examples/csharp/extend/Makefile new file mode 100644 index 000000000..20f0dd5bb --- /dev/null +++ b/SWIG/Examples/csharp/extend/Makefile @@ -0,0 +1,20 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +CXXSRCS = example.cxx +TARGET = example +INTERFACE = example.i +SWIGOPT = +CSHARPSRCS = *.cs +CSHARPFLAGS= -nologo -out:runme.exe + +all:: csharp + +csharp:: + $(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 + +check: all diff --git a/SWIG/Examples/csharp/extend/example-cs.csproj b/SWIG/Examples/csharp/extend/example-cs.csproj new file mode 100644 index 000000000..4e8874669 --- /dev/null +++ b/SWIG/Examples/csharp/extend/example-cs.csproj @@ -0,0 +1,104 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/SWIG/Examples/csharp/extend/example-vc.vcproj b/SWIG/Examples/csharp/extend/example-vc.vcproj new file mode 100644 index 000000000..7c0b8ef13 --- /dev/null +++ b/SWIG/Examples/csharp/extend/example-vc.vcproj @@ -0,0 +1,158 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/SWIG/Examples/csharp/extend/example.cxx b/SWIG/Examples/csharp/extend/example.cxx new file mode 100644 index 000000000..450d75608 --- /dev/null +++ b/SWIG/Examples/csharp/extend/example.cxx @@ -0,0 +1,4 @@ +/* File : example.cxx */ + +#include "example.h" + diff --git a/SWIG/Examples/csharp/extend/example.h b/SWIG/Examples/csharp/extend/example.h new file mode 100644 index 000000000..b27ab9711 --- /dev/null +++ b/SWIG/Examples/csharp/extend/example.h @@ -0,0 +1,56 @@ +/* File : example.h */ + +#include +#include +#include +#include +#include + +class Employee { +private: + std::string name; +public: + Employee(const char* n): name(n) {} + virtual std::string getTitle() { return getPosition() + " " + getName(); } + virtual std::string getName() { return name; } + virtual std::string getPosition() const { return "Employee"; } + virtual ~Employee() { printf("~Employee() @ %p\n", this); } +}; + + +class Manager: public Employee { +public: + Manager(const char* n): Employee(n) {} + virtual std::string getPosition() const { return "Manager"; } +}; + + +class EmployeeList { + std::vector list; +public: + EmployeeList() { + list.push_back(new Employee("Bob")); + list.push_back(new Employee("Jane")); + list.push_back(new Manager("Ted")); + } + void addEmployee(Employee *p) { + list.push_back(p); + std::cout << "New employee added. Current employees are:" << std::endl; + std::vector::iterator i; + for (i=list.begin(); i!=list.end(); i++) { + std::cout << " " << (*i)->getTitle() << std::endl; + } + } + const Employee *get_item(int i) { + return list[i]; + } + ~EmployeeList() { + std::vector::iterator i; + std::cout << "~EmployeeList, deleting " << list.size() << " employees." << std::endl; + for (i=list.begin(); i!=list.end(); i++) { + delete *i; + } + std::cout << "~EmployeeList empty." << std::endl; + } +}; + diff --git a/SWIG/Examples/csharp/extend/example.i b/SWIG/Examples/csharp/extend/example.i new file mode 100644 index 000000000..c8ec32e09 --- /dev/null +++ b/SWIG/Examples/csharp/extend/example.i @@ -0,0 +1,15 @@ +/* File : example.i */ +%module(directors="1") example +%{ +#include "example.h" +%} + +%include "std_vector.i" +%include "std_string.i" + +/* turn on director wrapping for Manager */ +%feature("director") Employee; +%feature("director") Manager; + +%include "example.h" + diff --git a/SWIG/Examples/csharp/extend/example.sln b/SWIG/Examples/csharp/extend/example.sln new file mode 100644 index 000000000..28b9851b0 --- /dev/null +++ b/SWIG/Examples/csharp/extend/example.sln @@ -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 diff --git a/SWIG/Examples/csharp/extend/main.java b/SWIG/Examples/csharp/extend/main.java new file mode 100644 index 000000000..ee3a94ed0 --- /dev/null +++ b/SWIG/Examples/csharp/extend/main.java @@ -0,0 +1,88 @@ +// This file illustrates the cross language polymorphism using directors. + + +// CEO class, which overrides Employee::getPosition(). + +class CEO extends Manager { + public CEO(String name) { + super(name); + } + public String getPosition() { + return "CEO"; + } + // Public method to stop the SWIG proxy base class from thinking it owns the underlying C++ memory. + public void disownMemory() { + swigCMemOwn = false; + } +} + + +public class main { + 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[]) + { + + // Create an instance of CEO, a class derived from the Java 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(). + + CEO e = new CEO("Alice"); + System.out.println( e.getName() + " is a " + e.getPosition() ); + System.out.println( "Just call her \"" + e.getTitle() + "\"" ); + System.out.println( "----------------------" ); + + + // Create a new EmployeeList instance. This class does not have a C++ + // director wrapper, but can be used freely with other classes that do. + + EmployeeList list = new EmployeeList(); + + // EmployeeList owns its items, so we must surrender ownership of objects we add. + e.disownMemory(); + list.addEmployee(e); + System.out.println( "----------------------" ); + + // Now we access the first four items in list (three are C++ objects that + // EmployeeList's constructor adds, the last is our CEO). The virtual + // methods of all these instances are treated the same. For items 0, 1, and + // 2, all methods resolve in C++. For item 3, our CEO, getTitle calls + // getPosition which resolves in Java. The call to getPosition is + // slightly different, however, because of the overidden getPosition() call, since + // now the object reference has been "laundered" by passing through + // EmployeeList as an Employee*. Previously, Java resolved the call + // immediately in CEO, but now Java 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 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 + // in CEO. All this routing takes place transparently. + + System.out.println( "(position, title) for items 0-3:" ); + + System.out.println( " " + list.get_item(0).getPosition() + ", \"" + list.get_item(0).getTitle() + "\"" ); + System.out.println( " " + list.get_item(1).getPosition() + ", \"" + list.get_item(1).getTitle() + "\"" ); + System.out.println( " " + list.get_item(2).getPosition() + ", \"" + list.get_item(2).getTitle() + "\"" ); + System.out.println( " " + list.get_item(3).getPosition() + ", \"" + list.get_item(3).getTitle() + "\"" ); + System.out.println( "----------------------" ); + + // Time to delete the EmployeeList, which will delete all the Employee* + // items it contains. The last item is our CEO, which gets destroyed as well. + list.delete(); + System.out.println( "----------------------" ); + + // All done. + + System.out.println( "java exit" ); + + } +} diff --git a/SWIG/Examples/csharp/extend/runme.cs b/SWIG/Examples/csharp/extend/runme.cs new file mode 100644 index 000000000..825dcdbca --- /dev/null +++ b/SWIG/Examples/csharp/extend/runme.cs @@ -0,0 +1,77 @@ +// This file illustrates the cross language polymorphism using directors. + +using System; + +// CEO class, which overrides Employee::getPosition(). + +class CEO : Manager { + public CEO(String name) : base(name) { + } + public override String getPosition() { + return "CEO"; + } + // Public method to stop the SWIG proxy base class from thinking it owns the underlying C++ memory. + public void disownMemory() { + swigCMemOwn = false; + } +} + + +public class runme +{ + static void Main() + { + // Create an instance of CEO, a class derived from the C# 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(). + + CEO e = new CEO("Alice"); + Console.WriteLine( e.getName() + " is a " + e.getPosition() ); + Console.WriteLine( "Just call her \"" + e.getTitle() + "\"" ); + Console.WriteLine( "----------------------" ); + + // Create a new EmployeeList instance. This class does not have a C++ + // director wrapper, but can be used freely with other classes that do. + + using (EmployeeList list = new EmployeeList()) { + + // EmployeeList owns its items, so we must surrender ownership of objects we add. + e.disownMemory(); + list.addEmployee(e); + Console.WriteLine( "----------------------" ); + + // Now we access the first four items in list (three are C++ objects that + // EmployeeList's constructor adds, the last is our CEO). The virtual + // methods of all these instances are treated the same. For items 0, 1, and + // 2, all methods resolve in C++. For item 3, our CEO, getTitle calls + // getPosition which resolves in C#. The call to getPosition is + // slightly different, however, because of the overidden getPosition() call, since + // now the object reference has been "laundered" by passing through + // EmployeeList as an Employee*. Previously, C# resolved the call + // immediately in CEO, but now C# 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 C# 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 C# implementation + // in CEO. All this routing takes place transparently. + + Console.WriteLine( "(position, title) for items 0-3:" ); + + Console.WriteLine( " " + list.get_item(0).getPosition() + ", \"" + list.get_item(0).getTitle() + "\"" ); + Console.WriteLine( " " + list.get_item(1).getPosition() + ", \"" + list.get_item(1).getTitle() + "\"" ); + Console.WriteLine( " " + list.get_item(2).getPosition() + ", \"" + list.get_item(2).getTitle() + "\"" ); + Console.WriteLine( " " + list.get_item(3).getPosition() + ", \"" + list.get_item(3).getTitle() + "\"" ); + Console.WriteLine( "----------------------" ); + + // The using statement ensures the EmployeeList.Dispose() will be called, which will delete all the Employee* + // items it contains. The last item is our CEO, which gets destroyed as well. + } + Console.WriteLine( "----------------------" ); + + // All done. + + Console.WriteLine( "C# exit" ); + } +}