diff options
Diffstat (limited to 'Examples/tcl')
93 files changed, 4469 insertions, 0 deletions
diff --git a/Examples/tcl/check.list b/Examples/tcl/check.list new file mode 100644 index 0000000..8e7a8a9 --- /dev/null +++ b/Examples/tcl/check.list @@ -0,0 +1,16 @@ +# see top-level Makefile.in +class +constants +contract +enum +funcptr +import +java +multimap +operator +pointer +reference +simple +std_vector +value +variables diff --git a/Examples/tcl/class/Makefile b/Examples/tcl/class/Makefile new file mode 100644 index 0000000..c01283c --- /dev/null +++ b/Examples/tcl/class/Makefile @@ -0,0 +1,19 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +CXXSRCS = example.cxx +TARGET = example +INTERFACE = example.i +LIBS = -lm + +all:: + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' tcl_cpp + +static:: + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + TARGET='mytclsh' INTERFACE='$(INTERFACE)' tclsh_cpp_static + +clean:: + $(MAKE) -f $(TOP)/Makefile tcl_clean + +check: all diff --git a/Examples/tcl/class/example.cxx b/Examples/tcl/class/example.cxx new file mode 100644 index 0000000..1e8e203 --- /dev/null +++ b/Examples/tcl/class/example.cxx @@ -0,0 +1,28 @@ +/* File : example.c */ + +#include "example.h" +#define M_PI 3.14159265358979323846 + +/* Move the shape to a new location */ +void Shape::move(double dx, double dy) { + x += dx; + y += dy; +} + +int Shape::nshapes = 0; + +double Circle::area(void) { + return M_PI*radius*radius; +} + +double Circle::perimeter(void) { + return 2*M_PI*radius; +} + +double Square::area(void) { + return width*width; +} + +double Square::perimeter(void) { + return 4*width; +} diff --git a/Examples/tcl/class/example.dsp b/Examples/tcl/class/example.dsp new file mode 100644 index 0000000..0ff5482 --- /dev/null +++ b/Examples/tcl/class/example.dsp @@ -0,0 +1,152 @@ +# 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 "$(TCL_INCLUDE)" /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 "$(TCL_LIB)" /nologo /dll /debug /machine:I386 /out:"example.dll" /pdbtype:sept
+
+!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 "$(TCL_INCLUDE)" /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 "$(TCL_LIB)" /nologo /dll /machine:I386 /out:"example.dll"
+
+!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 TCL_INCLUDE: %TCL_INCLUDE%
+ echo TCL_LIB: %TCL_LIB%
+ echo on
+ ..\..\..\swig.exe -c++ -tcl8 $(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 TCL_INCLUDE: %TCL_INCLUDE%
+ echo TCL_LIB: %TCL_LIB%
+ echo on
+ ..\..\..\swig.exe -c++ -tcl8 $(InputPath)
+
+# End Custom Build
+
+!ENDIF
+
+# End Source File
+# End Target
+# End Project
diff --git a/Examples/tcl/class/example.h b/Examples/tcl/class/example.h new file mode 100644 index 0000000..46d9013 --- /dev/null +++ b/Examples/tcl/class/example.h @@ -0,0 +1,39 @@ +/* File : example.h */ + +class Shape { +public: + Shape() { + nshapes++; + } + virtual ~Shape() { + nshapes--; + }; + double x, y; + void move(double dx, double dy); + virtual double area(void) = 0; + virtual double perimeter(void) = 0; + static int nshapes; +}; + +class Circle : public Shape { +private: + double radius; +public: + Circle(double r) : radius(r) { }; + virtual double area(void); + virtual double perimeter(void); +}; + +class Square : public Shape { +private: + double width; +public: + Square(double w) : width(w) { }; + virtual double area(void); + virtual double perimeter(void); +}; + + + + + diff --git a/Examples/tcl/class/example.i b/Examples/tcl/class/example.i new file mode 100644 index 0000000..23ee8a8 --- /dev/null +++ b/Examples/tcl/class/example.i @@ -0,0 +1,11 @@ +/* File : example.i */ +%module example + +%{ +#include "example.h" +%} + +/* Let's just grab the original header file here */ + +%include "example.h" + diff --git a/Examples/tcl/class/index.html b/Examples/tcl/class/index.html new file mode 100644 index 0000000..fd8cfe5 --- /dev/null +++ b/Examples/tcl/class/index.html @@ -0,0 +1,274 @@ +<html> +<head> +<title>SWIG:Examples:tcl:class</title> +</head> + +<body bgcolor="#ffffff"> + + +<tt>SWIG/Examples/tcl/class/</tt> +<hr> + +<H2>Wrapping a simple C++ class</H2> + +<p> +This example illustrates the most primitive form of C++ class wrapping performed +by SWIG. In this case, C++ classes are simply transformed into a collection of +C-style functions that provide access to class members. + +<h2>The C++ Code</h2> + +Suppose you have some C++ classes described by the following (and admittedly lame) +header file: + +<blockquote> +<pre> +/* File : example.h */ + +class Shape { +public: + Shape() { + nshapes++; + } + virtual ~Shape() { + nshapes--; + }; + double x, y; + void move(double dx, double dy); + virtual double area() = 0; + virtual double perimeter() = 0; + static int nshapes; +}; + +class Circle : public Shape { +private: + double radius; +public: + Circle(double r) : radius(r) { }; + virtual double area(); + virtual double perimeter(); +}; + +class Square : public Shape { +private: + double width; +public: + Square(double w) : width(w) { }; + virtual double area(); + virtual double perimeter(); +}; +</pre> +</blockquote> + +<h2>The SWIG interface</h2> + +A simple SWIG interface for this can be built by simply grabbing the header file +like this: + +<blockquote> +<pre> +/* File : example.i */ +%module example + +%{ +#include "example.h" +%} + +/* Let's just grab the original header file here */ +%include "example.h" +</pre> +</blockquote> + +Note: when creating a C++ extension, you must run SWIG with the <tt>-c++</tt> option like this: +<blockquote> +<pre> +% swig -c++ -tcl example.i +</pre> +</blockquote> + +<h2>Some sample Tcl scripts</h2> + +SWIG performs two forms of C++ wrapping-- a low level interface and a high level widget-like interface. +<ul> +<li> +Click <a href="example1.tcl">here</a> to see a script that calls the C++ functions using the +low-level interface. +<li> +Click <a href="example2.tcl">here</a> to see a the same script written with the high-level +interface. +</ul> + +<h2>Key points</h2> + +<ul> +<li>The low-level C++ interface works like this: +<p> +<ul> +<li>To create a new object, you call a constructor like this: + +<blockquote> +<pre> +set c [new_Circle 10.0] +</pre> +</blockquote> + +<p> +<li>To access member data, a pair of accessor functions are used. +For example: + +<blockquote> +<pre> +Shape_x_set $c 15 ;# Set member data +set x [Shape_x_get $c] ;# Get member data +</pre> +</blockquote> + +Note: when accessing member data, the name of the base class must +be used such as <tt>Shape_x_get</tt> + +<p> +<li>To invoke a member function, you simply do this + +<blockquote> +<pre> +puts "The area is [Shape_area $c]" +</pre> +</blockquote> + +<p> +<li>Type checking knows about the inheritance structure of C++. For example: + +<blockquote> +<pre> +Shape_area $c # Works (c is a Shape) +Circle_area $c # Works (c is a Circle) +Square_area $c # Fails (c is definitely not a Square) +</pre> +</blockquote> + +<p> +<li>To invoke a destructor, simply do this + +<blockquote> +<pre> +delete_Shape $c # Deletes a shape +</pre> +</blockquote> + +<p> +<li>Static member variables are wrapped as C global variables. For example: + +<blockquote> +<pre> +set n $Shape_nshapes # Get a static data member +set Shapes_nshapes 13 # Set a static data member +</pre> +</blockquote> + +</ul> + +<p> +<li>The high-level interface works like a Tk widget + +<p> +<ul> +<li>To create a new object, you call a constructor like this: + +<blockquote> +<pre> +Circle c 10 # c becomes a name for the Circle object +</pre> +</blockquote> + +<p> +<li>To access member data, use cget and configure methods. +For example: + +<blockquote> +<pre> +c configure -x 15 ;# Set member data +set x [c cget -x] ;# Get member data +</pre> +</blockquote> + +<p> +<li>To invoke a member function, you simply do this + +<blockquote> +<pre> +puts "The area is [c area]" +</pre> +</blockquote> + +<p> +<li>To invoke a destructor, simply destroy the object name like this: + +<blockquote> +<pre> +rename c "" # c goes away +</pre> +</blockquote> + +<p> +<li>Static member variables are wrapped as C global variables. For example: + +<blockquote> +<pre> +set n $Shape_nshapes # Get a static data member +set Shapes_nshapes 13 # Set a static data member +</pre> +</blockquote> + +</ul> +</ul> + +<h2>General Comments</h2> + +<ul> +<li>The low-level function interface is much faster than the high-level interface. +In fact, all the higher level interface does is call functions in the low-level interface. + +<p> +<li>SWIG *does* know how to properly perform upcasting of objects in an inheritance +hierarchy (including multiple inheritance). Therefore it is perfectly safe to pass +an object of a derived class to any function involving a base class. + +<p> +<li>A wide variety of C++ features are not currently supported by SWIG. Here is the +short and incomplete list: + +<p> +<ul> +<li>Overloaded methods and functions. SWIG wrappers don't know how to resolve name +conflicts so you must give an alternative name to any overloaded method name using the +%name directive like this: + +<blockquote> +<pre> +void foo(int a); +%name(foo2) void foo(double a, double b); +</pre> +</blockquote> + +<p> +<li>Overloaded operators. Not supported at all. The only workaround for this is +to write a helper function. For example: + +<blockquote> +<pre> +%inline %{ + Vector *vector_add(Vector *a, Vector *b) { + ... whatever ... + } +%} +</pre> +</blockquote> + +<p> +<li>Namespaces. Not supported at all. Won't be supported until SWIG2.0 (if at all). + +</ul> + +<hr> +</body> +</html> diff --git a/Examples/tcl/class/runme.tcl b/Examples/tcl/class/runme.tcl new file mode 100644 index 0000000..c7f4725 --- /dev/null +++ b/Examples/tcl/class/runme.tcl @@ -0,0 +1,50 @@ +# file: runme.tcl + +# This file illustrates the high level C++ interface. +# In this case C++ classes work kind of like Tk widgets + +catch { load ./example[info sharedlibextension] example} + +# ----- Object creation ----- + +puts "Creating some objects:" +Circle c 10 +puts " Created circle [c cget -this]" +Square s 10 +puts " Created square [s cget -this]" + +# ----- Access a static member ----- + +puts "\nA total of $Shape_nshapes shapes were created" + +# ----- Member data access ----- + +# Set the location of the object + +c configure -x 20 -y 30 +s configure -x -10 -y 5 + +puts "\nHere is their current position:" +puts " Circle = ([c cget -x], [c cget -y])" +puts " Square = ([s cget -x], [s cget -y])" + +# ----- Call some methods ----- + +puts "\nHere are some properties of the shapes:" +foreach o "c s" { + puts " [$o cget -this]" + puts " area = [$o area]" + puts " perimeter = [$o perimeter]" +} + +# ----- Delete everything ----- + +puts "\nGuess I'll clean up now" + +# Note: this invokes the virtual destructor +rename c "" +rename s "" + +puts "$Shape_nshapes shapes remain" +puts "Goodbye" + diff --git a/Examples/tcl/class/runme2.tcl b/Examples/tcl/class/runme2.tcl new file mode 100644 index 0000000..88ec2f6 --- /dev/null +++ b/Examples/tcl/class/runme2.tcl @@ -0,0 +1,70 @@ +# file: runme2.tcl + +# This file illustrates the low-level C++ interface +# created by SWIG. In this case, all of our C++ classes +# get converted into function calls. + +catch { load ./example[info sharedlibextension] example} + +# ----- Object creation ----- + +puts "Creating some objects:" +set c [new_Circle 10] +puts " Created circle $c" +set s [new_Square 10] +puts " Created square $s" + +# ----- Access a static member ----- + +puts "\nA total of $Shape_nshapes shapes were created" + +# ----- Member data access ----- + +# Set the location of the object +# Note: the base class must be used since that's where x and y +# were declared. + +Shape_x_set $c 20 +Shape_y_set $c 30 +Shape_x_set $s -10 +Shape_y_set $s 5 + +puts "\nHere is their current position:" +puts " Circle = ([Shape_x_get $c], [Shape_y_get $c])" +puts " Square = ([Shape_x_get $s], [Shape_y_get $s])" + +# ----- Call some methods ----- + +puts "\nHere are some properties of the shapes:" +foreach o "$c $s" { + puts " $o" + puts " area = [Shape_area $o]" + puts " perimeter = [Shape_perimeter $o]" +} +# Notice how the Shape_area() and Shape_perimeter() functions really +# invoke the appropriate virtual method on each object. + +# ----- Try to cause a type error ----- + +puts "\nI'm going to try and break the type system" + +if { [catch { + # Bad script! + Square_area $c # Try to invoke Square method on a Circle + puts " Bad bad SWIG!" + +}]} { + puts " Well, it didn't work. Good SWIG." +} + +# ----- Delete everything ----- + +puts "\nGuess I'll clean up now" + +# Note: this invokes the virtual destructor +delete_Shape $c +delete_Shape $s + +puts "$Shape_nshapes shapes remain" +puts "Goodbye" + diff --git a/Examples/tcl/constants/Makefile b/Examples/tcl/constants/Makefile new file mode 100644 index 0000000..ba28f47 --- /dev/null +++ b/Examples/tcl/constants/Makefile @@ -0,0 +1,19 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +SRCS = +TARGET = my_tclsh +DLTARGET = example +INTERFACE = example.i + +all:: + $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \ + TARGET='$(DLTARGET)' INTERFACE='$(INTERFACE)' tcl + +static:: + $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \ + TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' tclsh + +clean:: + $(MAKE) -f $(TOP)/Makefile tcl_clean + +check: all diff --git a/Examples/tcl/constants/example.i b/Examples/tcl/constants/example.i new file mode 100644 index 0000000..4f7b1a4 --- /dev/null +++ b/Examples/tcl/constants/example.i @@ -0,0 +1,27 @@ +/* File : example.i */ +%module example + +/* A few preprocessor macros */ + +#define ICONST 42 +#define FCONST 2.1828 +#define CCONST 'x' +#define CCONST2 '\n' +#define SCONST "Hello World" +#define SCONST2 "\"Hello World\"" + +/* This should work just fine */ +#define EXPR ICONST + 3*(FCONST) + +/* This shouldn't do anything */ +#define EXTERN extern + +/* Neither should this (BAR isn't defined) */ +#define FOO (ICONST + BAR) + +/* The following directives also produce constants */ + +%constant int iconst = 37; +%constant double fconst = 3.14; + + diff --git a/Examples/tcl/constants/index.html b/Examples/tcl/constants/index.html new file mode 100644 index 0000000..fa332c6 --- /dev/null +++ b/Examples/tcl/constants/index.html @@ -0,0 +1,61 @@ +<html> +<head> +<title>SWIG:Examples:tcl:constants</title> +</head> + +<body bgcolor="#ffffff"> + +<tt>SWIG/Examples/tcl/constants/</tt> +<hr> + +<H2>Wrapping C Constants</H2> + +<p> +When SWIG encounters C preprocessor macros and C declarations that look like constants, +it creates Tcl variables with an identical value. Click <a href="example.i">here</a> +to see a SWIG interface with some constant declarations in it. + +<h2>Accessing Constants from Tcl</h2> + +Click <a href="runme.tcl">here</a> to see a script that prints out the values +of the constants contained in the above file. + +<h2>Key points</h2> + +<ul> +<li>The values of preprocessor macros are converted into Tcl read-only variables. +<li>Types are inferred by syntax (e.g., "3" is an integer and "3.5" is a float). +<li>Character constants such as 'x' are converted into strings. +<li>C string literals such as "Hello World" are converted into strings. +<li>Macros that are not fully defined are simply ignored. For example: +<blockquote> +<pre> +#define EXTERN extern +</pre> +</blockquote> +is ignored because SWIG has no idea what type of variable this would be. + +<p> +<li>Expressions are allowed provided that all of their components are defined. Otherwise, the constant is ignored. + +<li>Certain C declarations involving 'const' are also turned into Tcl constants. +<li>The constants that appear in a SWIG interface file do not have to appear in any sort +of matching C source file since the creation of a constant does not require linkage +to a stored value (i.e., a value held in a C global variable or memory location). +<li>Since constants are turned into Tcl variables, you have to use the global +statement when accessing from a procedure. For example: + +<blockquote> +<pre> +proc foo {} { + global ICONST # Some C constant + puts $ICONST +} +</pre> +</blockquote> +</ul> + +<hr> + +</body> +</html> diff --git a/Examples/tcl/constants/runme.tcl b/Examples/tcl/constants/runme.tcl new file mode 100644 index 0000000..b504ba8 --- /dev/null +++ b/Examples/tcl/constants/runme.tcl @@ -0,0 +1,26 @@ +# file: runme.tcl + +catch { load ./example[info sharedlibextension] example} + +puts "ICONST = $ICONST (should be 42)" +puts "FCONST = $FCONST (should be 2.1828)" +puts "CCONS T = $CCONST (should be 'x')" +puts "CCONST2 = $CCONST2 (this should be on a separate line)" +puts "SCONST = $SCONST (should be 'Hello World')" +puts "SCONST2 = $SCONST2 (should be '\"Hello World\"')" +puts "EXPR = $EXPR (should be 48.5484)" +puts "iconst = $iconst (should be 37)" +puts "fconst = $fconst (should be 3.14)" + +if { [catch { + puts "EXTERN = $EXTERN (Arg! This shouldn't print anything)" +}]} { + puts "EXTERN isn't defined (good)" +} + +if { [catch { + puts "FOO = $FOO (Arg! This shouldn't print anything)" +}]} { + puts "FOO isn't defined (good)" +} + diff --git a/Examples/tcl/contract/Makefile b/Examples/tcl/contract/Makefile new file mode 100644 index 0000000..91a139a --- /dev/null +++ b/Examples/tcl/contract/Makefile @@ -0,0 +1,20 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +SRCS = example.c +TARGET = my_tclsh +DLTARGET = example +INTERFACE = example.i +SWIGOPT = + +all:: + $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' SWIGOPT='$(SWIGOPT)' \ + TARGET='$(DLTARGET)' INTERFACE='$(INTERFACE)' tcl + +static:: + $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' SWIGOPT='$(SWIGOPT)' \ + TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' tclsh + +clean:: + $(MAKE) -f $(TOP)/Makefile tcl_clean + +check: all diff --git a/Examples/tcl/contract/example.c b/Examples/tcl/contract/example.c new file mode 100644 index 0000000..1a64454 --- /dev/null +++ b/Examples/tcl/contract/example.c @@ -0,0 +1,23 @@ +/* File : example.c */ + +/* A global variable */ +double Foo = 3.0; + +/* Compute the greatest common divisor of positive integers */ +int gcd(int x, int y) { + int g; + g = y; + while (x > 0) { + g = x; + x = y % x; + y = g; + } + return g; +} + +int fact(int n) { + if (n <= 0) return 1; + return n*fact(n-1); +} + + diff --git a/Examples/tcl/contract/example.dsp b/Examples/tcl/contract/example.dsp new file mode 100644 index 0000000..c1568f2 --- /dev/null +++ b/Examples/tcl/contract/example.dsp @@ -0,0 +1,148 @@ +# 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 "$(TCL_INCLUDE)" /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 "$(TCL_LIB)" /nologo /dll /debug /machine:I386 /out:"example.dll" /pdbtype:sept
+
+!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 "$(TCL_INCLUDE)" /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 "$(TCL_LIB)" /nologo /dll /machine:I386 /out:"example.dll"
+
+!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.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\example_wrap.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# 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.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ echo In order to function correctly, please ensure the following environment variables are correctly set:
+ echo TCL_INCLUDE: %TCL_INCLUDE%
+ echo TCL_LIB: %TCL_LIB%
+ echo on
+ ..\..\..\swig.exe -tcl8 $(InputPath)
+
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "example - Win32 Release"
+
+# Begin Custom Build
+InputPath=.\example.i
+InputName=example
+
+"$(InputName)_wrap.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ echo In order to function correctly, please ensure the following environment variables are correctly set:
+ echo TCL_INCLUDE: %TCL_INCLUDE%
+ echo TCL_LIB: %TCL_LIB%
+ echo on
+ ..\..\..\swig.exe -tcl8 $(InputPath)
+
+# End Custom Build
+
+!ENDIF
+
+# End Source File
+# End Target
+# End Project
diff --git a/Examples/tcl/contract/example.i b/Examples/tcl/contract/example.i new file mode 100644 index 0000000..8fd1a80 --- /dev/null +++ b/Examples/tcl/contract/example.i @@ -0,0 +1,21 @@ +/* File : example.i */ +%module example + +%contract gcd(int x, int y) { +require: + x >= 0; + y >= 0; +} + +%contract fact(int n) { +require: + n >= 0; +ensure: + fact >= 1; +} + +%inline %{ +extern int gcd(int x, int y); +extern int fact(int n); +extern double Foo; +%} diff --git a/Examples/tcl/contract/runme.tcl b/Examples/tcl/contract/runme.tcl new file mode 100644 index 0000000..3a6ce10 --- /dev/null +++ b/Examples/tcl/contract/runme.tcl @@ -0,0 +1,22 @@ +# file: runme.tcl +# Try to load as a dynamic module. + +catch { load ./example[info sharedlibextension] example} + +# Call our gcd() function +set x 42 +set y 105 +set g [gcd $x $y] +puts "The gcd of $x and $y is $g" + +# Manipulate the Foo global variable + +# Output its current value +puts "Foo = $Foo" + +# Change its value +set Foo 3.1415926 + +# See if the change took effect +puts "Foo = $Foo" + diff --git a/Examples/tcl/enum/Makefile b/Examples/tcl/enum/Makefile new file mode 100644 index 0000000..c01283c --- /dev/null +++ b/Examples/tcl/enum/Makefile @@ -0,0 +1,19 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +CXXSRCS = example.cxx +TARGET = example +INTERFACE = example.i +LIBS = -lm + +all:: + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' tcl_cpp + +static:: + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + TARGET='mytclsh' INTERFACE='$(INTERFACE)' tclsh_cpp_static + +clean:: + $(MAKE) -f $(TOP)/Makefile tcl_clean + +check: all diff --git a/Examples/tcl/enum/example.cxx b/Examples/tcl/enum/example.cxx new file mode 100644 index 0000000..6785e57 --- /dev/null +++ b/Examples/tcl/enum/example.cxx @@ -0,0 +1,37 @@ +/* File : example.c */ + +#include "example.h" +#include <stdio.h> + +void Foo::enum_test(speed s) { + if (s == IMPULSE) { + printf("IMPULSE speed\n"); + } else if (s == WARP) { + printf("WARP speed\n"); + } else if (s == LUDICROUS) { + printf("LUDICROUS speed\n"); + } else { + printf("Unknown speed\n"); + } +} + +void enum_test(color c, Foo::speed s) { + if (c == RED) { + printf("color = RED, "); + } else if (c == BLUE) { + printf("color = BLUE, "); + } else if (c == GREEN) { + printf("color = GREEN, "); + } else { + printf("color = Unknown color!, "); + } + if (s == Foo::IMPULSE) { + printf("speed = IMPULSE speed\n"); + } else if (s == Foo::WARP) { + printf("speed = WARP speed\n"); + } else if (s == Foo::LUDICROUS) { + printf("speed = LUDICROUS speed\n"); + } else { + printf("speed = Unknown speed!\n"); + } +} diff --git a/Examples/tcl/enum/example.h b/Examples/tcl/enum/example.h new file mode 100644 index 0000000..525d62a --- /dev/null +++ b/Examples/tcl/enum/example.h @@ -0,0 +1,13 @@ +/* File : example.h */ + +enum color { RED, BLUE, GREEN }; + +class Foo { + public: + Foo() { } + enum speed { IMPULSE, WARP, LUDICROUS }; + void enum_test(speed s); +}; + +void enum_test(color c, Foo::speed s); + diff --git a/Examples/tcl/enum/example.i b/Examples/tcl/enum/example.i new file mode 100644 index 0000000..23ee8a8 --- /dev/null +++ b/Examples/tcl/enum/example.i @@ -0,0 +1,11 @@ +/* File : example.i */ +%module example + +%{ +#include "example.h" +%} + +/* Let's just grab the original header file here */ + +%include "example.h" + diff --git a/Examples/tcl/enum/index.html b/Examples/tcl/enum/index.html new file mode 100644 index 0000000..559f6a8 --- /dev/null +++ b/Examples/tcl/enum/index.html @@ -0,0 +1,35 @@ +<html> +<head> +<title>SWIG:Examples:tcl:enum</title> +</head> + +<body bgcolor="#ffffff"> + + +<tt>SWIG/Examples/tcl/enum/</tt> +<hr> + +<H2>Wrapping enumerations</H2> + +<p> +This example tests SWIG's ability to wrap enumerations. By default, SWIG +converts enumeration specifications into integer constants. Further use +of enumerated types are handled as integers. + +<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="runme.tcl">runme.tcl</a>. Sample Tcl script. +</ul> + +<h2>Notes</h2> + +<ul> +<li>SWIG allows arbitrary integers to be passed as enum values. However, +the result of passing an integer not corresponding to any of the values +specified in the <tt>enum</tt> specification is undefined. +</ul> + +<hr> +</body> +</html> diff --git a/Examples/tcl/enum/runme.tcl b/Examples/tcl/enum/runme.tcl new file mode 100644 index 0000000..3d4e52a --- /dev/null +++ b/Examples/tcl/enum/runme.tcl @@ -0,0 +1,32 @@ +# file: runme.tcl + +catch { load ./example[info sharedlibextension] example} + +# ----- Object creation ----- + +# Print out the value of some enums +puts "*** color ***" +puts " RED = $RED" +puts " BLUE = $BLUE" +puts " GREEN = $GREEN" + +puts "\n*** Foo::speed ***" +puts " Foo_IMPULSE = $Foo_IMPULSE" +puts " Foo_WARP = $Foo_WARP" +puts " Foo_LUDICROUS = $Foo_LUDICROUS" + + +puts "\nTesting use of enums with functions\n" + +enum_test $RED $Foo_IMPULSE +enum_test $BLUE $Foo_WARP +enum_test $GREEN $Foo_LUDICROUS +enum_test 1234 5678 + +puts "\nTesting use of enum with class method" +Foo f + +f enum_test $Foo_IMPULSE +f enum_test $Foo_WARP +f enum_test $Foo_LUDICROUS + diff --git a/Examples/tcl/funcptr/Makefile b/Examples/tcl/funcptr/Makefile new file mode 100644 index 0000000..bed049a --- /dev/null +++ b/Examples/tcl/funcptr/Makefile @@ -0,0 +1,19 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +SRCS = example.c +TARGET = my_tclsh +DLTARGET = example +INTERFACE = example.i + +all:: + $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \ + TARGET='$(DLTARGET)' INTERFACE='$(INTERFACE)' tcl + +static:: + $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \ + TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' tclsh + +clean:: + $(MAKE) -f $(TOP)/Makefile tcl_clean + +check: all diff --git a/Examples/tcl/funcptr/example.c b/Examples/tcl/funcptr/example.c new file mode 100644 index 0000000..5c4a3da --- /dev/null +++ b/Examples/tcl/funcptr/example.c @@ -0,0 +1,19 @@ +/* File : example.c */ + +int do_op(int a, int b, int (*op)(int,int)) { + return (*op)(a,b); +} + +int add(int a, int b) { + return a+b; +} + +int sub(int a, int b) { + return a-b; +} + +int mul(int a, int b) { + return a*b; +} + +int (*funcvar)(int,int) = add; diff --git a/Examples/tcl/funcptr/example.h b/Examples/tcl/funcptr/example.h new file mode 100644 index 0000000..9936e24 --- /dev/null +++ b/Examples/tcl/funcptr/example.h @@ -0,0 +1,9 @@ +/* file: example.h */ + +extern int do_op(int,int, int (*op)(int,int)); +extern int add(int,int); +extern int sub(int,int); +extern int mul(int,int); + +extern int (*funcvar)(int,int); + diff --git a/Examples/tcl/funcptr/example.i b/Examples/tcl/funcptr/example.i new file mode 100644 index 0000000..8b3bef6 --- /dev/null +++ b/Examples/tcl/funcptr/example.i @@ -0,0 +1,16 @@ +/* File : example.i */ +%module example +%{ +#include "example.h" +%} + +/* Wrap a function taking a pointer to a function */ +extern int do_op(int a, int b, int (*op)(int, int)); + +/* Now install a bunch of "ops" as constants */ +%constant int (*ADD)(int,int) = add; +%constant int (*SUB)(int,int) = sub; +%constant int (*MUL)(int,int) = mul; + +extern int (*funcvar)(int,int); + diff --git a/Examples/tcl/funcptr/index.html b/Examples/tcl/funcptr/index.html new file mode 100644 index 0000000..b822962 --- /dev/null +++ b/Examples/tcl/funcptr/index.html @@ -0,0 +1,90 @@ +<html> +<head> +<title>SWIG:Examples:tcl:funcptr</title> +</head> + +<body bgcolor="#ffffff"> + + +<tt>SWIG/Examples/tcl/funcptr/</tt> +<hr> + +<H2>Pointers to Functions</H2> + +<p> +Okay, just what in the heck does SWIG do with a declaration like this? + +<blockquote> +<pre> +int do_op(int a, int b, int (*op)(int, int)); +</pre> +</blockquote> + +Well, it creates a wrapper as usual. Of course, that does raise some +questions about the third argument (the pointer to a function). + +<p> +In this case, SWIG will wrap the function pointer as it does for all other +pointers. However, in order to actually call this function from a script, +you will need to pass some kind of C function pointer object. In C, +this is easy, you just supply a function name as an argument like this: + +<blockquote> +<pre> +/* Some callback function */ +int add(int a, int b) { + return a+b; +} +... +int r = do_op(x,y,add); +</pre> +</blockquote> + +To make this work with SWIG, you will need to do a little extra work. Specifically, +you need to create some function pointer objects using the %constant directive like this: + +<blockquote> +<pre> +%constant(int (*)(int,int)) ADD = add; +</pre> +</blockquote> + +Now, in a script, you would do this: + +<blockquote> +<pre> +set r [do_op $x $y $ADD] +</pre> +</blockquote> + +<h2>An Example</h2> + +Here are some files that illustrate this with a simple example: + +<ul> +<li><a href="example.c">example.c</a> +<li><a href="example.h">example.h</a> +<li><a href="example.i">example.i</a> (SWIG interface) +<li><a href="runme.tcl">runme.tcl</a> (Sample script) +</ul> + +<h2>Notes</h2> + +<ul> +<li>The value of a function pointer must correspond to a function written in C or C++. +It is not possible to pass an arbitrary Tcl function object in as a substitute for a C +function pointer. + +<p> +<li>A Tcl function can be used as a C/C++ callback if you write some +clever typemaps and are very careful about how you create your extension. +This is an advanced topic not covered here. +</ul> + +<hr> +</body> +</html> + + + + diff --git a/Examples/tcl/funcptr/runme.tcl b/Examples/tcl/funcptr/runme.tcl new file mode 100644 index 0000000..7e676c2 --- /dev/null +++ b/Examples/tcl/funcptr/runme.tcl @@ -0,0 +1,21 @@ +# file: runme.tcl + +catch { load ./example[info sharedlibextension] example} + +set a 37 +set b 42 + +# Now call our C function with a bunch of callbacks + +puts "Trying some C callback functions" +puts " a = $a" +puts " b = $b" +puts " ADD(a,b) = [do_op $a $b $ADD]" +puts " SUB(a,b) = [do_op $a $b $SUB]" +puts " MUL(a,b) = [do_op $a $b $MUL]" + +puts "Here is what the C callback function objects look like in Tcl" +puts " ADD = $ADD" +puts " SUB = $SUB" +puts " MUL = $MUL" + diff --git a/Examples/tcl/import/Makefile b/Examples/tcl/import/Makefile new file mode 100644 index 0000000..6b257aa --- /dev/null +++ b/Examples/tcl/import/Makefile @@ -0,0 +1,20 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +SWIGOPT = +LIBS = + +all:: + $(MAKE) -f $(TOP)/Makefile SWIG='$(SWIG)' SWIGOPT='$(SWIGOPT)' \ + LIBS='$(LIBS)' TARGET='base' INTERFACE='base.i' tcl_cpp + $(MAKE) -f $(TOP)/Makefile SWIG='$(SWIG)' SWIGOPT='$(SWIGOPT)' \ + LIBS='$(LIBS)' TARGET='foo' INTERFACE='foo.i' tcl_cpp + $(MAKE) -f $(TOP)/Makefile SWIG='$(SWIG)' SWIGOPT='$(SWIGOPT)' \ + LIBS='$(LIBS)' TARGET='bar' INTERFACE='bar.i' tcl_cpp + $(MAKE) -f $(TOP)/Makefile SWIG='$(SWIG)' SWIGOPT='$(SWIGOPT)' \ + LIBS='$(LIBS)' TARGET='spam' INTERFACE='spam.i' tcl_cpp + + +clean:: + $(MAKE) -f $(TOP)/Makefile tcl_clean + +check: all diff --git a/Examples/tcl/import/README b/Examples/tcl/import/README new file mode 100644 index 0000000..b2a65f5 --- /dev/null +++ b/Examples/tcl/import/README @@ -0,0 +1,37 @@ +This example tests the %import directive and working with multiple modules. + +Use 'tclsh runme.tcl' to run a test. + +Overview: +--------- + +The example defines 4 different extension modules--each wrapping +a separate C++ class. + + base.i - Base class + foo.i - Foo class derived from Base + bar.i - Bar class derived from Base + spam.i - Spam class derived from Bar + +Each module used %import to refer to another module. For +example, the 'foo.i' module uses '%import base.i' to get +definitions for its base class. + +If everything is okay, all of the modules will load properly and +type checking will work correctly. Caveat: Some compilers, for example +gcc-3.2.x, generate broken vtables with the inline methods in this test. +This is not a SWIG problem and can usually be solved with non-inlined +destructors compiled into separate shared objects/DLLs. + +Unix: +----- +- Run make +- Run the test as described above + +Windows: +-------- +- Use the Visual C++ 6 workspace file (example.dsw). The Batch build option + in the Build menu is usually the easiest way to do this. Only use the Release + builds not the Debug builds. +- Run the test as described above + diff --git a/Examples/tcl/import/bar.dsp b/Examples/tcl/import/bar.dsp new file mode 100644 index 0000000..d22b6a6 --- /dev/null +++ b/Examples/tcl/import/bar.dsp @@ -0,0 +1,144 @@ +# Microsoft Developer Studio Project File - Name="bar" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=bar - 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 "bar.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 "bar.mak" CFG="bar - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "bar - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "bar - 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)" == "bar - 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 "BAR_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GR /GX /ZI /Od /I "$(TCL_INCLUDE)" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "BAR_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 "$(TCL_LIB)" /nologo /dll /debug /machine:I386 /out:"bar.dll" /pdbtype:sept
+
+!ELSEIF "$(CFG)" == "bar - 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 "BAR_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GR /GX /O2 /I "$(TCL_INCLUDE)" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "BAR_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 "$(TCL_LIB)" /nologo /dll /machine:I386 /out:"bar.dll"
+
+!ENDIF
+
+# Begin Target
+
+# Name "bar - Win32 Debug"
+# Name "bar - Win32 Release"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\bar_wrap.cxx
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\bar.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=.\bar.i
+
+!IF "$(CFG)" == "bar - Win32 Debug"
+
+# Begin Custom Build
+InputPath=.\bar.i
+InputName=bar
+
+"$(InputName)_wrap.cxx" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ echo In order to function correctly, please ensure the following environment variables are correctly set:
+ echo TCL_INCLUDE: %TCL_INCLUDE%
+ echo TCL_LIB: %TCL_LIB%
+ echo on
+ ..\..\..\swig.exe -c++ -tcl8 $(InputPath)
+
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "bar - Win32 Release"
+
+# Begin Custom Build
+InputPath=.\bar.i
+InputName=bar
+
+"$(InputName)_wrap.cxx" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ echo In order to function correctly, please ensure the following environment variables are correctly set:
+ echo TCL_INCLUDE: %TCL_INCLUDE%
+ echo TCL_LIB: %TCL_LIB%
+ echo on
+ ..\..\..\swig.exe -c++ -tcl8 $(InputPath)
+
+# End Custom Build
+
+!ENDIF
+
+# End Source File
+# End Target
+# End Project
diff --git a/Examples/tcl/import/bar.h b/Examples/tcl/import/bar.h new file mode 100644 index 0000000..fa4185f --- /dev/null +++ b/Examples/tcl/import/bar.h @@ -0,0 +1,22 @@ +#include "base.h" + +class Bar : public Base { + public: + Bar() { } + ~Bar() { } + virtual void A() { + printf("I'm Bar::A\n"); + } + void B() { + printf("I'm Bar::B\n"); + } + virtual Base *toBase() { + return static_cast<Base *>(this); + } + static Bar *fromBase(Base *b) { + return dynamic_cast<Bar *>(b); + } + +}; + + diff --git a/Examples/tcl/import/bar.i b/Examples/tcl/import/bar.i new file mode 100644 index 0000000..5816cbe --- /dev/null +++ b/Examples/tcl/import/bar.i @@ -0,0 +1,9 @@ +%module bar +%{ +#include "bar.h" +%} + +%import base.i +%include "bar.h" + + diff --git a/Examples/tcl/import/base.dsp b/Examples/tcl/import/base.dsp new file mode 100644 index 0000000..b27bbfd --- /dev/null +++ b/Examples/tcl/import/base.dsp @@ -0,0 +1,144 @@ +# Microsoft Developer Studio Project File - Name="base" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=base - 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 "base.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 "base.mak" CFG="base - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "base - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "base - 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)" == "base - 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 "BASE_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GR /GX /ZI /Od /I "$(TCL_INCLUDE)" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "BASE_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 "$(TCL_LIB)" /nologo /dll /debug /machine:I386 /out:"base.dll" /pdbtype:sept
+
+!ELSEIF "$(CFG)" == "base - 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 "BASE_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GR /GX /O2 /I "$(TCL_INCLUDE)" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "BASE_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 "$(TCL_LIB)" /nologo /dll /machine:I386 /out:"base.dll"
+
+!ENDIF
+
+# Begin Target
+
+# Name "base - Win32 Debug"
+# Name "base - Win32 Release"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\base_wrap.cxx
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\base.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=.\base.i
+
+!IF "$(CFG)" == "base - Win32 Debug"
+
+# Begin Custom Build
+InputPath=.\base.i
+InputName=base
+
+"$(InputName)_wrap.cxx" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ echo In order to function correctly, please ensure the following environment variables are correctly set:
+ echo TCL_INCLUDE: %TCL_INCLUDE%
+ echo TCL_LIB: %TCL_LIB%
+ echo on
+ ..\..\..\swig.exe -c++ -tcl8 $(InputPath)
+
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "base - Win32 Release"
+
+# Begin Custom Build
+InputPath=.\base.i
+InputName=base
+
+"$(InputName)_wrap.cxx" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ echo In order to function correctly, please ensure the following environment variables are correctly set:
+ echo TCL_INCLUDE: %TCL_INCLUDE%
+ echo TCL_LIB: %TCL_LIB%
+ echo on
+ ..\..\..\swig.exe -c++ -tcl8 $(InputPath)
+
+# End Custom Build
+
+!ENDIF
+
+# End Source File
+# End Target
+# End Project
diff --git a/Examples/tcl/import/base.h b/Examples/tcl/import/base.h new file mode 100644 index 0000000..5a266f6 --- /dev/null +++ b/Examples/tcl/import/base.h @@ -0,0 +1,18 @@ +#include <stdio.h> + +class Base { + public: + Base() { }; + virtual ~Base() { }; + virtual void A() { + printf("I'm Base::A\n"); + } + void B() { + printf("I'm Base::B\n"); + } + virtual Base *toBase() { + return static_cast<Base *>(this); + } +}; + + diff --git a/Examples/tcl/import/base.i b/Examples/tcl/import/base.i new file mode 100644 index 0000000..f6e19ef --- /dev/null +++ b/Examples/tcl/import/base.i @@ -0,0 +1,6 @@ +%module base +%{ +#include "base.h" +%} + +%include base.h diff --git a/Examples/tcl/import/example.dsw b/Examples/tcl/import/example.dsw new file mode 100644 index 0000000..d395d46 --- /dev/null +++ b/Examples/tcl/import/example.dsw @@ -0,0 +1,65 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "bar"=.\bar.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "base"=.\base.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "foo"=.\foo.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "spam"=.\spam.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/Examples/tcl/import/foo.dsp b/Examples/tcl/import/foo.dsp new file mode 100644 index 0000000..4d3765b --- /dev/null +++ b/Examples/tcl/import/foo.dsp @@ -0,0 +1,144 @@ +# Microsoft Developer Studio Project File - Name="foo" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=foo - 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 "foo.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 "foo.mak" CFG="foo - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "foo - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "foo - 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)" == "foo - 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 "FOO_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GR /GX /ZI /Od /I "$(TCL_INCLUDE)" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FOO_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 "$(TCL_LIB)" /nologo /dll /debug /machine:I386 /out:"foo.dll" /pdbtype:sept
+
+!ELSEIF "$(CFG)" == "foo - 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 "FOO_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GR /GX /O2 /I "$(TCL_INCLUDE)" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FOO_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 "$(TCL_LIB)" /nologo /dll /machine:I386 /out:"foo.dll"
+
+!ENDIF
+
+# Begin Target
+
+# Name "foo - Win32 Debug"
+# Name "foo - Win32 Release"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\foo_wrap.cxx
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\foo.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=.\foo.i
+
+!IF "$(CFG)" == "foo - Win32 Debug"
+
+# Begin Custom Build
+InputPath=.\foo.i
+InputName=foo
+
+"$(InputName)_wrap.cxx" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ echo In order to function correctly, please ensure the following environment variables are correctly set:
+ echo TCL_INCLUDE: %TCL_INCLUDE%
+ echo TCL_LIB: %TCL_LIB%
+ echo on
+ ..\..\..\swig.exe -c++ -tcl8 $(InputPath)
+
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "foo - Win32 Release"
+
+# Begin Custom Build
+InputPath=.\foo.i
+InputName=foo
+
+"$(InputName)_wrap.cxx" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ echo In order to function correctly, please ensure the following environment variables are correctly set:
+ echo TCL_INCLUDE: %TCL_INCLUDE%
+ echo TCL_LIB: %TCL_LIB%
+ echo on
+ ..\..\..\swig.exe -c++ -tcl8 $(InputPath)
+
+# End Custom Build
+
+!ENDIF
+
+# End Source File
+# End Target
+# End Project
diff --git a/Examples/tcl/import/foo.h b/Examples/tcl/import/foo.h new file mode 100644 index 0000000..dd51840 --- /dev/null +++ b/Examples/tcl/import/foo.h @@ -0,0 +1,21 @@ +#include "base.h" + +class Foo : public Base { + public: + Foo() { } + ~Foo() { } + virtual void A() { + printf("I'm Foo::A\n"); + } + void B() { + printf("I'm Foo::B\n"); + } + virtual Base *toBase() { + return static_cast<Base *>(this); + } + static Foo *fromBase(Base *b) { + return dynamic_cast<Foo *>(b); + } +}; + + diff --git a/Examples/tcl/import/foo.i b/Examples/tcl/import/foo.i new file mode 100644 index 0000000..27feb2e --- /dev/null +++ b/Examples/tcl/import/foo.i @@ -0,0 +1,8 @@ +%module foo +%{ +#include "foo.h" +%} + +%import base.i +%include "foo.h" + diff --git a/Examples/tcl/import/runme.tcl b/Examples/tcl/import/runme.tcl new file mode 100644 index 0000000..1227d7b --- /dev/null +++ b/Examples/tcl/import/runme.tcl @@ -0,0 +1,114 @@ +# file: runme.tcl +# Test various properties of classes defined in separate modules + +puts "Testing the %import directive" +catch { load ./base[info sharedlibextension] base} +catch { load ./foo[info sharedlibextension] foo} +catch { load ./bar[info sharedlibextension] bar} +catch { load ./spam[info sharedlibextension] spam} + +# Create some objects + +puts "Creating some objects" + +set a [Base] +set b [Foo] +set c [Bar] +set d [Spam] + +# Try calling some methods +puts "Testing some methods" +puts "Should see 'Base::A' ---> " +$a A +puts "Should see 'Base::B' ---> " +$a B + +puts "Should see 'Foo::A' ---> " +$b A +puts "Should see 'Foo::B' ---> " +$b B + +puts "Should see 'Bar::A' ---> " +$c A +puts "Should see 'Bar::B' ---> " +$c B + +puts "Should see 'Spam::A' ---> " +$d A +puts "Should see 'Spam::B' ---> " +$d B + +# Try some casts + +puts "\nTesting some casts\n" + +Base x -this [$a toBase] +puts "Should see 'Base::A' ---> " +x A +puts "Should see 'Base::B' ---> " +x B +rename x "" + +Base x -this [$b toBase] +puts "Should see 'Foo::A' ---> " +x A +puts "Should see 'Base::B' ---> " +x B +rename x "" + +Base x -this [$c toBase] +puts "Should see 'Bar::A' ---> " +x A +puts "Should see 'Base::B' ---> " +x B +rename x "" + +Base x -this [$d toBase] +puts "Should see 'Spam::A' ---> " +x A +puts "Should see 'Base::B' ---> " +x B +rename x "" + +Bar x -this [$d toBar] +puts "Should see 'Bar::B' ---> " +x B +rename x "" + +puts "\nTesting some dynamic casts\n" +Base x -this [$d toBase] + +puts "Spam -> Base -> Foo : " +set y [Foo_fromBase [x cget -this]] +if {$y != "NULL"} { + puts "bad swig" +} { + puts "good swig" +} + +puts "Spam -> Base -> Bar : " +set y [Bar_fromBase [x cget -this]] +if {$y != "NULL"} { + puts "good swig" +} { + puts "bad swig" +} + +puts "Spam -> Base -> Spam : " +set y [Spam_fromBase [x cget -this]] +if {$y != "NULL"} { + puts "good swig" +} { + puts "bad swig" +} + +puts "Foo -> Spam : " +set y [Spam_fromBase $b] +if {$y != "NULL"} { + puts "bad swig" +} { + puts "good swig" +} + + + diff --git a/Examples/tcl/import/spam.dsp b/Examples/tcl/import/spam.dsp new file mode 100644 index 0000000..5674c43 --- /dev/null +++ b/Examples/tcl/import/spam.dsp @@ -0,0 +1,144 @@ +# Microsoft Developer Studio Project File - Name="spam" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=spam - 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 "spam.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For spam:
+!MESSAGE
+!MESSAGE NMAKE /f "spam.mak" CFG="spam - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "spam - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "spam - 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)" == "spam - 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 "SPAM_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GR /GX /ZI /Od /I "$(TCL_INCLUDE)" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SPAM_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 "$(TCL_LIB)" /nologo /dll /debug /machine:I386 /out:"spam.dll" /pdbtype:sept
+
+!ELSEIF "$(CFG)" == "spam - 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 "SPAM_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GR /GX /O2 /I "$(TCL_INCLUDE)" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SPAM_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 "$(TCL_LIB)" /nologo /dll /machine:I386 /out:"spam.dll"
+
+!ENDIF
+
+# Begin Target
+
+# Name "spam - Win32 Debug"
+# Name "spam - Win32 Release"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\spam_wrap.cxx
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\spam.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=.\spam.i
+
+!IF "$(CFG)" == "spam - Win32 Debug"
+
+# Begin Custom Build
+InputPath=.\spam.i
+InputName=spam
+
+"$(InputName)_wrap.cxx" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ echo In order to function correctly, please ensure the following environment variables are correctly set:
+ echo TCL_INCLUDE: %TCL_INCLUDE%
+ echo TCL_LIB: %TCL_LIB%
+ echo on
+ ..\..\..\swig.exe -c++ -tcl8 $(InputPath)
+
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "spam - Win32 Release"
+
+# Begin Custom Build
+InputPath=.\spam.i
+InputName=spam
+
+"$(InputName)_wrap.cxx" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ echo In order to function correctly, please ensure the following environment variables are correctly set:
+ echo TCL_INCLUDE: %TCL_INCLUDE%
+ echo TCL_LIB: %TCL_LIB%
+ echo on
+ ..\..\..\swig.exe -c++ -tcl8 $(InputPath)
+
+# End Custom Build
+
+!ENDIF
+
+# End Source File
+# End Target
+# End Project
diff --git a/Examples/tcl/import/spam.h b/Examples/tcl/import/spam.h new file mode 100644 index 0000000..b4e7a26 --- /dev/null +++ b/Examples/tcl/import/spam.h @@ -0,0 +1,24 @@ +#include "bar.h" + +class Spam : public Bar { + public: + Spam() { } + ~Spam() { } + virtual void A() { + printf("I'm Spam::A\n"); + } + void B() { + printf("I'm Spam::B\n"); + } + virtual Base *toBase() { + return static_cast<Base *>(this); + } + virtual Bar *toBar() { + return static_cast<Bar *>(this); + } + static Spam *fromBase(Base *b) { + return dynamic_cast<Spam *>(b); + } +}; + + diff --git a/Examples/tcl/import/spam.i b/Examples/tcl/import/spam.i new file mode 100644 index 0000000..d3d9121 --- /dev/null +++ b/Examples/tcl/import/spam.i @@ -0,0 +1,9 @@ +%module spam +%{ +#include "spam.h" +%} + +%import bar.i +%include "spam.h" + + diff --git a/Examples/tcl/index.html b/Examples/tcl/index.html new file mode 100644 index 0000000..b327260 --- /dev/null +++ b/Examples/tcl/index.html @@ -0,0 +1,70 @@ +<html> +<head> +<title>SWIG:Examples:tcl</title> +</head> + +<body bgcolor="#ffffff"> +<H1>SWIG Tcl Examples</H1> + +<p> +The following examples illustrate the use of SWIG with Tcl. + +<ul> +<li><a href="simple/index.html">simple</a>. A minimal example showing how SWIG can +be used to wrap a C function and a global variable. +<li><a href="constants/index.html">constants</a>. This shows how preprocessor macros and +certain C declarations are turned into constants. +<li><a href="variables/index.html">variables</a>. How SWIG can be used to wrap C global variables. +<li><a href="value/index.html">value</a>. How to pass and return structures by value. +<li><a href="class/index.html">class</a>. How wrap a simple C++ class. +<li><a href="reference/index.html">reference</a>. C++ references. +<li><a href="pointer/index.html">pointer</a>. Simple pointer handling. +<li><a href="funcptr/index.html">funcptr</a>. Pointers to functions. +</ul> + +<h2>Compilation Issues</h2> + +<ul> +<li>To create a Tcl extension, SWIG is run with the following options: + +<blockquote> +<pre> +% swig -tcl interface.i +</pre> +</blockquote> + +<li> +Please see the <a href="../../Doc/Manual/Windows.html">Windows</a> page in the main manual for information on using the examples on Windows. <p> +</li> + +<li>The compilation of examples is done using the file <tt>Example/Makefile</tt>. This +makefile performs a manual module compilation which is platform specific. Typically, +the steps look like this (Linux): + +<blockquote> +<pre> +unix % swig -tcl interface.i +unix % gcc -fpic -c interface_wrap.c -I/usr/local/include +unix % gcc -shared interface_wrap.o $(OBJS) -o interface.so +unix % tclsh8.3 +% load ./interface.so +% blah ... +</pre> +</blockquote> +</ul> + +<h2>Compatibility</h2> + +The examples have been extensively tested on the following platforms: + +<ul> +<li>Linux +<li>Solaris +</ul> + +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/tcl/java/Example.java b/Examples/tcl/java/Example.java new file mode 100644 index 0000000..91ddb1a --- /dev/null +++ b/Examples/tcl/java/Example.java @@ -0,0 +1,29 @@ +public class Example { + public int mPublicInt; + + public Example() { + mPublicInt = 0; + } + + public Example(int IntVal) { + mPublicInt = IntVal; + } + + + public int Add(int a, int b) { + return (a+b); + } + + public float Add(float a, float b) { + return (a+b); + } + + public String Add(String a, String b) { + return (a+b); + } + + public Example Add(Example a, Example b) { + return new Example(a.mPublicInt + b.mPublicInt); + } +} + diff --git a/Examples/tcl/java/Makefile b/Examples/tcl/java/Makefile new file mode 100644 index 0000000..1c6d4d0 --- /dev/null +++ b/Examples/tcl/java/Makefile @@ -0,0 +1,26 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +CXXSRCS = +TARGET = example +INTERFACE = example.i +LIBS = -lm + +all:: Example.class + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' CXX="gcj" \ + TCL_CXXSHARED="gcj -fpic -shared Example.class " LIBS="-lstdc++" DEFS='' tcl_cpp + + +clean:: + $(MAKE) -f $(TOP)/Makefile tcl_clean + rm -f *.class Example.h + +check: all + +run: + tclsh runme.tcl + +Example.class: Example.java + gcj -fPIC -C -c -g Example.java + gcjh Example + diff --git a/Examples/tcl/java/example.i b/Examples/tcl/java/example.i new file mode 100644 index 0000000..b69d83f --- /dev/null +++ b/Examples/tcl/java/example.i @@ -0,0 +1,8 @@ +%module example +%include <cni.i> + +%{ +#include "Example.h" +%} + +%include Example.h diff --git a/Examples/tcl/java/runme.tcl b/Examples/tcl/java/runme.tcl new file mode 100644 index 0000000..6caf007 --- /dev/null +++ b/Examples/tcl/java/runme.tcl @@ -0,0 +1,15 @@ +catch { load ./example[info sharedlibextension] example} + +JvCreateJavaVM NULL +JvAttachCurrentThread NULL NULL +Example e1 1 +Example e2 2 + +puts "[e1 cget -mPublicInt]" +puts "[e2 cget -mPublicInt]" + +puts "[e2 Add 1 2]" +puts "[e2 Add 1.0 2.0]" +puts "[e2 Add '1' '2']" + +JvDetachCurrentThread diff --git a/Examples/tcl/multimap/Makefile b/Examples/tcl/multimap/Makefile new file mode 100644 index 0000000..bed049a --- /dev/null +++ b/Examples/tcl/multimap/Makefile @@ -0,0 +1,19 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +SRCS = example.c +TARGET = my_tclsh +DLTARGET = example +INTERFACE = example.i + +all:: + $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \ + TARGET='$(DLTARGET)' INTERFACE='$(INTERFACE)' tcl + +static:: + $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \ + TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' tclsh + +clean:: + $(MAKE) -f $(TOP)/Makefile tcl_clean + +check: all diff --git a/Examples/tcl/multimap/example.c b/Examples/tcl/multimap/example.c new file mode 100644 index 0000000..b8360fa --- /dev/null +++ b/Examples/tcl/multimap/example.c @@ -0,0 +1,53 @@ +/* File : example.c */ +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> + +/* Compute the greatest common divisor of positive integers */ +int gcd(int x, int y) { + int g; + g = y; + while (x > 0) { + g = x; + x = y % x; + y = g; + } + return g; +} + +int gcdmain(int argc, char *argv[]) { + int x,y; + if (argc != 3) { + printf("usage: gcd x y\n"); + return -1; + } + x = atoi(argv[1]); + y = atoi(argv[2]); + printf("gcd(%d,%d) = %d\n", x,y,gcd(x,y)); + return 0; +} + +int count(char *bytes, int len, char c) { + int i; + int count = 0; + for (i = 0; i < len; i++) { + if (bytes[i] == c) count++; + } + return count; +} + +void capitalize(char *str, int len) { + int i; + for (i = 0; i < len; i++) { + str[i] = (char)toupper(str[i]); + } +} + +void circle(double x, double y) { + double a = x*x + y*y; + if (a > 1.0) { + printf("Bad points %g, %g\n", x,y); + } else { + printf("Good points %g, %g\n", x,y); + } +} diff --git a/Examples/tcl/multimap/example.dsp b/Examples/tcl/multimap/example.dsp new file mode 100644 index 0000000..c1568f2 --- /dev/null +++ b/Examples/tcl/multimap/example.dsp @@ -0,0 +1,148 @@ +# 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 "$(TCL_INCLUDE)" /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 "$(TCL_LIB)" /nologo /dll /debug /machine:I386 /out:"example.dll" /pdbtype:sept
+
+!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 "$(TCL_INCLUDE)" /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 "$(TCL_LIB)" /nologo /dll /machine:I386 /out:"example.dll"
+
+!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.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\example_wrap.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# 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.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ echo In order to function correctly, please ensure the following environment variables are correctly set:
+ echo TCL_INCLUDE: %TCL_INCLUDE%
+ echo TCL_LIB: %TCL_LIB%
+ echo on
+ ..\..\..\swig.exe -tcl8 $(InputPath)
+
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "example - Win32 Release"
+
+# Begin Custom Build
+InputPath=.\example.i
+InputName=example
+
+"$(InputName)_wrap.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ echo In order to function correctly, please ensure the following environment variables are correctly set:
+ echo TCL_INCLUDE: %TCL_INCLUDE%
+ echo TCL_LIB: %TCL_LIB%
+ echo on
+ ..\..\..\swig.exe -tcl8 $(InputPath)
+
+# End Custom Build
+
+!ENDIF
+
+# End Source File
+# End Target
+# End Project
diff --git a/Examples/tcl/multimap/example.i b/Examples/tcl/multimap/example.i new file mode 100644 index 0000000..9a141b6 --- /dev/null +++ b/Examples/tcl/multimap/example.i @@ -0,0 +1,80 @@ +/* File : example.i */ +%module example + +%{ +extern int gcd(int x, int y); +extern int gcdmain(int argc, char *argv[]); +extern int count(char *bytes, int len, char c); +extern void capitalize (char *str, int len); +extern void circle (double cx, double cy); +extern int squareCubed (int n, int *OUTPUT); +%} + +%include exception.i + +extern int gcd(int x, int y); + +%typemap(arginit) (int argc, char *argv[]) "$2 = 0;"; + +%typemap(in) (int argc, char *argv[]) { + Tcl_Obj **listobjv = 0; + int i; + if (Tcl_ListObjGetElements(interp,$input, &$1, &listobjv) == TCL_ERROR) { + SWIG_exception(SWIG_ValueError,"Expected a list"); + return TCL_ERROR; + } + $2 = (char **) malloc(($1+1)*sizeof(char *)); + for (i = 0; i < $1; i++) { + $2[i] = Tcl_GetStringFromObj(listobjv[i],0); + } + $2[i] = 0; +} + +%typemap(freearg) char *argv[] { + if ($1) { + free($1); + } +} + +extern int gcdmain(int argc, char *argv[]); + +%typemap(in) (char *bytes, int len) { + $1 = Tcl_GetStringFromObj($input,&$2); +} + +extern int count(char *bytes, int len, char c); + + +/* This example shows how to wrap a function that mutates a string */ + +%typemap(in) (char *str, int len) { + char *temp; + temp = Tcl_GetStringFromObj($input,&$2); + $1 = (char *) malloc($2+1); + memmove($1,temp,$2); +} + +/* Return the mutated string as a new object. */ + +%typemap(argout) (char *str, int len) { + Tcl_Obj *o; + o = Tcl_NewStringObj($1,$2); + Tcl_ListObjAppendElement(interp,$result,o); + free($1); +} + +extern void capitalize(char *str, int len); + + +/* A multi-valued constraint. Force two arguments to lie + inside the unit circle */ + +%typemap(check) (double cx, double cy) { + double a = $1*$1 + $2*$2; + if (a > 1.0) { + SWIG_exception(SWIG_ValueError,"$1_name and $2_name must be in unit circle"); + return TCL_ERROR; + } +} + +extern void circle(double cx, double cy); diff --git a/Examples/tcl/multimap/runme.tcl b/Examples/tcl/multimap/runme.tcl new file mode 100644 index 0000000..bafa281 --- /dev/null +++ b/Examples/tcl/multimap/runme.tcl @@ -0,0 +1,24 @@ +# file: runme.tcl +# Try to load as a dynamic module. + +catch { load ./example[info sharedlibextension] example} + +# Call our gcd() function +set x 42 +set y 105 +set g [gcd $x $y] +puts "The gcd of $x and $y is $g" + +# call the gcdmain +gcdmain "gcdmain 42 105" + + +# call count +set c [count "Hello World" l] +puts $c + +# call capitalize + +set c [capitalize "helloworld"] +puts $c + diff --git a/Examples/tcl/operator/Makefile b/Examples/tcl/operator/Makefile new file mode 100644 index 0000000..caf2f79 --- /dev/null +++ b/Examples/tcl/operator/Makefile @@ -0,0 +1,19 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +CXXSRCS = +TARGET = example +INTERFACE = example.i +LIBS = -lm + +all:: + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' tcl_cpp + +static:: + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + TARGET='mytclsh' INTERFACE='$(INTERFACE)' tclsh_cpp_static + +clean:: + $(MAKE) -f $(TOP)/Makefile tcl_clean + +check: all diff --git a/Examples/tcl/operator/example.h b/Examples/tcl/operator/example.h new file mode 100644 index 0000000..4da6a23 --- /dev/null +++ b/Examples/tcl/operator/example.h @@ -0,0 +1,36 @@ +/* File : example.h */ +#include <math.h> + +class Complex { +private: + double rpart, ipart; +public: + Complex(double r = 0, double i = 0) : rpart(r), ipart(i) { } + Complex(const Complex &c) : rpart(c.rpart), ipart(c.ipart) { } + Complex &operator=(const Complex &c) { + rpart = c.rpart; + ipart = c.ipart; + return *this; + } + Complex operator+(const Complex &c) const { + return Complex(rpart+c.rpart, ipart+c.ipart); + } + Complex operator-(const Complex &c) const { + return Complex(rpart-c.rpart, ipart-c.ipart); + } + Complex operator*(const Complex &c) const { + return Complex(rpart*c.rpart - ipart*c.ipart, + rpart*c.ipart + c.rpart*ipart); + } + Complex operator-() const { + return Complex(-rpart, -ipart); + } + + double re() const { return rpart; } + double im() const { return ipart; } +}; + + + + + diff --git a/Examples/tcl/operator/example.i b/Examples/tcl/operator/example.i new file mode 100644 index 0000000..fa5bccd --- /dev/null +++ b/Examples/tcl/operator/example.i @@ -0,0 +1,28 @@ +/* File : example.i */ +%module example + +%{ +#include "example.h" +%} + +/* This header file is a little tough to handle because it has overloaded + operators and constructors. We're going to try and deal with that here */ + +/* This turns the copy constructor in a function ComplexCopy() that can + be called */ + +%rename(ComplexCopy) Complex::Complex(Complex const &); + +/* Now grab the original header file */ +%include "example.h" + +/* An output method that turns a complex into a short string */ +%extend Complex { + char *str() { + static char temp[512]; + sprintf(temp,"(%g,%g)", $self->re(), $self->im()); + return temp; + } +}; + + diff --git a/Examples/tcl/operator/runme.tcl b/Examples/tcl/operator/runme.tcl new file mode 100644 index 0000000..3b7c068 --- /dev/null +++ b/Examples/tcl/operator/runme.tcl @@ -0,0 +1,30 @@ +# Operator overloading example + +catch { load ./example[info sharedlibextension] example} + +set a [Complex -args 2 3] +set b [Complex -args -5 10] + +puts "a = $a [$a str]" +puts "b = $b [$b str]" + +set c [$a + $b] +Complex -this $c +puts "c = $c [$c str]" + +set d [$a * $b] +Complex -this $d +puts "a*b = [$d str]" + +# Alternative calling convention +set e [Complex_- $a $c] +puts "a-c = [Complex_str $e]" + +set f [new_ComplexCopy $e] +Complex -this $f +puts "f = [$f str]" + +# Call assignment operator +$c = $f +puts "c = [$c str]" + diff --git a/Examples/tcl/pointer/Makefile b/Examples/tcl/pointer/Makefile new file mode 100644 index 0000000..bed049a --- /dev/null +++ b/Examples/tcl/pointer/Makefile @@ -0,0 +1,19 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +SRCS = example.c +TARGET = my_tclsh +DLTARGET = example +INTERFACE = example.i + +all:: + $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \ + TARGET='$(DLTARGET)' INTERFACE='$(INTERFACE)' tcl + +static:: + $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \ + TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' tclsh + +clean:: + $(MAKE) -f $(TOP)/Makefile tcl_clean + +check: all diff --git a/Examples/tcl/pointer/example.c b/Examples/tcl/pointer/example.c new file mode 100644 index 0000000..b877d9a --- /dev/null +++ b/Examples/tcl/pointer/example.c @@ -0,0 +1,16 @@ +/* File : example.c */ + +void add(int *x, int *y, int *result) { + *result = *x + *y; +} + +void sub(int *x, int *y, int *result) { + *result = *x - *y; +} + +int divide(int n, int d, int *r) { + int q; + q = n/d; + *r = n - q*d; + return q; +} diff --git a/Examples/tcl/pointer/example.i b/Examples/tcl/pointer/example.i new file mode 100644 index 0000000..4d5b523 --- /dev/null +++ b/Examples/tcl/pointer/example.i @@ -0,0 +1,31 @@ +/* File : example.i */ +%module example + +%{ +extern void add(int *, int *, int *); +extern void sub(int *, int *, int *); +extern int divide(int, int, int *); +%} + +/* This example illustrates a couple of different techniques + for manipulating C pointers */ + +/* First we'll use the pointer library */ +extern void add(int *x, int *y, int *result); + +%include cpointer.i +%pointer_functions(int, intp); + +/* Next we'll use some typemaps */ + +%include typemaps.i +extern void sub(int *INPUT, int *INPUT, int *OUTPUT); + +/* Next we'll use typemaps and the %apply directive */ + +%apply int *OUTPUT { int *r }; +extern int divide(int n, int d, int *r); + + + + diff --git a/Examples/tcl/pointer/index.html b/Examples/tcl/pointer/index.html new file mode 100644 index 0000000..874088a --- /dev/null +++ b/Examples/tcl/pointer/index.html @@ -0,0 +1,171 @@ +<html> +<head> +<title>SWIG:Examples:tcl:pointer</title> +</head> + +<body bgcolor="#ffffff"> + +<tt>SWIG/Examples/tcl/pointer/</tt> +<hr> + +<H2>Simple Pointer Handling</H2> + +<p> +This example illustrates a couple of techniques for handling +simple pointers in SWIG. The prototypical example is a C function +that operates on pointers such as this: + +<blockquote> +<pre> +void add(int *x, int *y, int *r) { + *r = *x + *y; +} +</pre> +</blockquote> + +By default, SWIG wraps this function exactly as specified and creates +an interface that expects pointer objects for arguments. The only +problem is how does one go about creating these objects from a script? + +<h2>Possible Solutions</h2> + +<ul> +<li>Write some helper functions to explicitly create objects. For +example: + +<blockquote> +<pre> +int *new_int(int ivalue) { + int *i = (int *) malloc(sizeof(ivalue)); + *i = ivalue; + return i; +} +int get_int(int *i) { + return *i; +} + +void delete_int(int *i) { + free(i); +} +</pre> +</blockquote> + +Now, in a script you would do this: + +<blockquote> +<pre> +set a [new_int 37] +set b [new_int 42] +set c [new_int 0] +add $a $b $c +set r [get_int $c] +puts "Result = $r" +delete_int $a +delete_int $b +delete_int $c +</pre> +</blockquote> + +<p> +<li>Use the SWIG pointer library. For example, in the interface file +you would do this: + +<blockquote> +<pre> +%include "pointer.i" +</pre> +</blockquote? + +and in a script you would do this: + +<blockquote> +<pre> +set a [ptrcreate int 37] +set b [ptrcreate int 42] +set c [ptrcreate int] +add $a $b $c +set r [ptrvalue $c] +puts "Result = $r" +ptrfree $a +ptrfree $b +ptrfree $c +</pre> +</blockquote> + +The advantage to using the pointer library is that it unifies some of the helper +functions behind a common set of names. For example, the same set of functions work +with int, double, float, and other fundamental types. + +<p> +<li>Use the SWIG typemap library. This library allows you to completely +change the way arguments are processed by SWIG. For example: + +<blockquote> +<pre> +%include "typemaps.i" +void add(int *INPUT, int *INPUT, int *OUTPUT); +</pre> +</blockquote> + +And in a script: + +<blockquote> +<pre> +set r [add 37 42] +puts "Result = $r" +</pre> +</blockquote> +Needless to say, this is substantially easier. + +<p> +<li>A final alternative is to use the typemaps library in combination +with the %apply directive. This allows you to change the names of parameters +that behave as input or output parameters. For example: + +<blockquote> +<pre> +%include "typemaps.i" +%apply int *INPUT {int *x, int *y}; +%apply int *OUTPUT {int *r}; + +void add(int *x, int *y, int *r); +void sub(int *x, int *y, int *r); +void mul(int *x, int *y, int *r); +... etc ... +</pre> +</blockquote> + +</ul> + +<h2>Example</h2> + +The following example illustrates the use of these features for pointer +extraction. + +<ul> +<li> <a href="example.c">example.c</a> (C Source) +<li> <a href="example.i">example.i</a> (Swig interface) +<li> <a href="runme.tcl">runme.tcl</a> (Tcl Script) +</ul> + +<h2>Notes</h2> + +<ul> +<li>Since pointers are used for so many different things (arrays, output values, +etc...) the complexity of pointer handling can be as complicated as you want to +make it. + +<p> +<li>More documentation on the typemaps.i and pointer.i library files can be +found in the SWIG user manual. The files also contain documentation. + +<p> +<li>The pointer.i library is designed primarily for convenience. If you +are concerned about performance, you probably want to use a different +approach. + +</ul> + +<hr> +</body> +</html> diff --git a/Examples/tcl/pointer/runme.tcl b/Examples/tcl/pointer/runme.tcl new file mode 100644 index 0000000..efe9bb4 --- /dev/null +++ b/Examples/tcl/pointer/runme.tcl @@ -0,0 +1,47 @@ +# file: runme.tcl + +catch { load ./example[info sharedlibextension] example} + +# First create some objects using the pointer library. +puts "Testing the pointer library" +set a [new_intp] +set b [new_intp] +set c [new_intp] ;# Memory for result + +intp_assign $a 37 +intp_assign $b 42 + +puts " a = $a" +puts " b = $b" +puts " c = $c" + +# Call the add() function with some pointers +add $a $b $c + +# Now get the result +set r [intp_value $c] +puts " 37 + 42 = $r" + +# Clean up the pointers +delete_intp $a +delete_intp $b +delete_intp $c + +# Now try the typemap library +# This should be much easier. Now how it is no longer +# necessary to manufacture pointers. + +puts "Trying the typemap library" +set r [sub 37 42] +puts " 37 - 42 = $r" + +# Now try the version with multiple return values + +puts "Testing multiple return values" +set qr [divide 42 37] +set q [lindex $qr 0] +set r [lindex $qr 1] +puts " 42/37 = $q remainder $r" + + + diff --git a/Examples/tcl/reference/Makefile b/Examples/tcl/reference/Makefile new file mode 100644 index 0000000..c01283c --- /dev/null +++ b/Examples/tcl/reference/Makefile @@ -0,0 +1,19 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +CXXSRCS = example.cxx +TARGET = example +INTERFACE = example.i +LIBS = -lm + +all:: + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' tcl_cpp + +static:: + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + TARGET='mytclsh' INTERFACE='$(INTERFACE)' tclsh_cpp_static + +clean:: + $(MAKE) -f $(TOP)/Makefile tcl_clean + +check: all diff --git a/Examples/tcl/reference/example.cxx b/Examples/tcl/reference/example.cxx new file mode 100644 index 0000000..8a513bf --- /dev/null +++ b/Examples/tcl/reference/example.cxx @@ -0,0 +1,46 @@ +/* File : example.cxx */ + +/* Deal with Microsoft's attempt at deprecating C standard runtime functions */ +#if !defined(SWIG_NO_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) +# define _CRT_SECURE_NO_DEPRECATE +#endif + +#include "example.h" +#include <stdio.h> +#include <stdlib.h> + +Vector operator+(const Vector &a, const Vector &b) { + Vector r; + r.x = a.x + b.x; + r.y = a.y + b.y; + r.z = a.z + b.z; + return r; +} + +char *Vector::print() { + static char temp[512]; + sprintf(temp,"Vector %p (%g,%g,%g)", this, x,y,z); + return temp; +} + +VectorArray::VectorArray(int size) { + items = new Vector[size]; + maxsize = size; +} + +VectorArray::~VectorArray() { + delete [] items; +} + +Vector &VectorArray::operator[](int index) { + if ((index < 0) || (index >= maxsize)) { + printf("Panic! Array index out of bounds.\n"); + exit(1); + } + return items[index]; +} + +int VectorArray::size() { + return maxsize; +} + diff --git a/Examples/tcl/reference/example.h b/Examples/tcl/reference/example.h new file mode 100644 index 0000000..4915adb --- /dev/null +++ b/Examples/tcl/reference/example.h @@ -0,0 +1,26 @@ +/* File : example.h */ + +class Vector { +private: + double x,y,z; +public: + Vector() : x(0), y(0), z(0) { }; + Vector(double x, double y, double z) : x(x), y(y), z(z) { }; + friend Vector operator+(const Vector &a, const Vector &b); + char *print(); +}; + +class VectorArray { +private: + Vector *items; + int maxsize; +public: + VectorArray(int maxsize); + ~VectorArray(); + Vector &operator[](int); + int size(); +}; + + + + diff --git a/Examples/tcl/reference/example.i b/Examples/tcl/reference/example.i new file mode 100644 index 0000000..6daa3b1 --- /dev/null +++ b/Examples/tcl/reference/example.i @@ -0,0 +1,46 @@ +/* File : example.i */ + +/* This file has a few "typical" uses of C++ references. */ + +%module example + +%{ +#include "example.h" +%} + +class Vector { +public: + Vector(double x, double y, double z); + ~Vector(); + char *print(); +}; + +/* This helper function calls an overloaded operator */ +%inline %{ +Vector addv(Vector &a, Vector &b) { + return a+b; +} +%} + +/* Wrapper around an array of vectors class */ + +class VectorArray { +public: + VectorArray(int maxsize); + ~VectorArray(); + int size(); + + /* This wrapper provides an alternative to the [] operator */ + %extend { + Vector &get(int index) { + return (*$self)[index]; + } + void set(int index, Vector &a) { + (*$self)[index] = a; + } + } +}; + + + + diff --git a/Examples/tcl/reference/index.html b/Examples/tcl/reference/index.html new file mode 100644 index 0000000..ef799fa --- /dev/null +++ b/Examples/tcl/reference/index.html @@ -0,0 +1,147 @@ +<html> +<head> +<title>SWIG:Examples:tcl:reference</title> +</head> + +<body bgcolor="#ffffff"> + + +<tt>SWIG/Examples/tcl/reference/</tt> +<hr> + +<H2>C++ Reference Handling</H2> + +<p> +This example tests SWIG's handling of C++ references. Since C++ +references are closely related to pointers (as both refer to a +location in memory), SWIG simply collapses all references into +pointers when creating wrappers. + +<h2>Some examples</h2> + +References are most commonly used as function parameter. For example, +you might have an operator like this: + +<blockquote> +<pre> +Vector operator+(const Vector &a, const Vector &b) { + Vector result; + result.x = a.x + b.x; + result.y = a.y + b.y; + result.z = a.z + b.z; + return result; +} +</pre> +</blockquote> + +or a function: + +<blockquote> +<pre> +Vector addv(const Vector &a, const Vector &b) { + Vector result; + result.x = a.x + b.x; + result.y = a.y + b.y; + result.z = a.z + b.z; + return result; +} +</pre> +</blockquote> + +In these cases, SWIG transforms everything into a pointer and creates a wrapper +that looks like this: + +<blockquote> +<pre> +Vector wrap_addv(Vector *a, Vector *b) { + return addv(*a,*b); +} +</pre> +</blockquote> + +Occasionally, a reference is used as a return value of a function +when the return result is to be used as an lvalue in an expression. +The prototypical example is an operator like this: + +<blockquote> +<pre> +Vector &operator[](int index); +</pre> +</blockquote> + +or a method: + +<blockquote> +<pre> +Vector &get(int index); +</pre> +</blockquote> + +For functions returning references, a wrapper like this is created: + +<blockquote> +<pre> +Vector *wrap_Object_get(Object *self, int index) { + Vector &result = self->get(index); + return &result; +} +</pre> +</blockquote> + +The following <a href="example.h">header file</a> contains some class +definitions with some operators and use of references. + +<h2>SWIG Interface</h2> + +SWIG does NOT support overloaded operators so it can not directly build +an interface to the classes in the above file. However, a number of workarounds +can be made. For example, an overloaded operator can be stuck behind a function +call such as the <tt>addv()</tt> function above. Array access can be handled +with a pair of set/get functions like this: + +<blockquote> +<pre> +class VectorArray { +public: + ... + %addmethods { + Vector &get(int index) { + return (*self)[index]; + } + void set(int index, Vector &a) { + (*self)[index] = a; + } + } + ... +} +</pre> +</blockquote> + +Click <a href="example.i">here</a> to see a SWIG interface file with these additions. + +<h2>Sample Tcl scripts</h2> + +Click <a href="runme.tcl">here</a> to see a script that manipulates some C++ references. + +<h2>Notes:</h2> + +<ul> +<li>C++ references primarily provide notational convenience for C++ +source code. However, Tcl has neither the 'x.a' or 'x->a' +notation so it doesn't much matter. + +<p> +<li>When a program returns a reference, a pointer is returned. +Unlike return by value, memory is not allocated to hold the +return result. + +<p> +<li>SWIG has particular trouble handling various combinations of references +and pointers. This is side effect of an old parsing scheme and +type representation that will be replaced in future versions. + +</ul> + +<hr> +</body> +</html> diff --git a/Examples/tcl/reference/runme.tcl b/Examples/tcl/reference/runme.tcl new file mode 100644 index 0000000..6560cf4 --- /dev/null +++ b/Examples/tcl/reference/runme.tcl @@ -0,0 +1,76 @@ +# file: runme.tcl + +# This file illustrates the manipulation of C++ references in Tcl + +catch { load ./example[info sharedlibextension] example} + +# ----- Object creation ----- + +puts "Creating some objects:" +set a [new_Vector 3 4 5] +set b [new_Vector 10 11 12] + +puts " Created [Vector_print $a]" +puts " Created [Vector_print $b]" + +# ----- Call an overloaded operator ----- + +# This calls the wrapper we placed around +# +# operator+(const Vector &a, const Vector &) +# +# It returns a new allocated object. + +puts "Adding a+b" +set c [addv $a $b] +puts " a+b = [Vector_print $c]" + +# Note: Unless we free the result, a memory leak will occur +delete_Vector $c + +# ----- Create a vector array ----- + +# Note: Using the high-level interface here +puts "Creating an array of vectors" +VectorArray va 10 +puts " va = [va cget -this]" + + +# ----- Set some values in the array ----- + +# These operators copy the value of $a and $b to the vector array +va set 0 $a +va set 1 $b + +# This will work, but it will cause a memory leak! + +va set 2 [addv $a $b] + +# The non-leaky way to do it + +set c [addv $a $b] +va set 3 $c +delete_Vector $c + +# Get some values from the array + +puts "Getting some array values" +for {set i 0} {$i < 5} {incr i 1} { + puts " va($i) = [Vector_print [va get $i]]" +} + +# Watch under resource meter to check on this +puts "Making sure we don't leak memory." +for {set i 0} {$i < 1000000} {incr i 1} { + set c [va get [expr {$i % 10}]] +} + +# ----- Clean up ----- +puts "Cleaning up" + +rename va "" + +delete_Vector $a +delete_Vector $b + + diff --git a/Examples/tcl/simple/Makefile b/Examples/tcl/simple/Makefile new file mode 100644 index 0000000..bed049a --- /dev/null +++ b/Examples/tcl/simple/Makefile @@ -0,0 +1,19 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +SRCS = example.c +TARGET = my_tclsh +DLTARGET = example +INTERFACE = example.i + +all:: + $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \ + TARGET='$(DLTARGET)' INTERFACE='$(INTERFACE)' tcl + +static:: + $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \ + TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' tclsh + +clean:: + $(MAKE) -f $(TOP)/Makefile tcl_clean + +check: all diff --git a/Examples/tcl/simple/example.c b/Examples/tcl/simple/example.c new file mode 100644 index 0000000..1c2af78 --- /dev/null +++ b/Examples/tcl/simple/example.c @@ -0,0 +1,18 @@ +/* File : example.c */ + +/* A global variable */ +double Foo = 3.0; + +/* Compute the greatest common divisor of positive integers */ +int gcd(int x, int y) { + int g; + g = y; + while (x > 0) { + g = x; + x = y % x; + y = g; + } + return g; +} + + diff --git a/Examples/tcl/simple/example.dsp b/Examples/tcl/simple/example.dsp new file mode 100644 index 0000000..c1568f2 --- /dev/null +++ b/Examples/tcl/simple/example.dsp @@ -0,0 +1,148 @@ +# 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 "$(TCL_INCLUDE)" /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 "$(TCL_LIB)" /nologo /dll /debug /machine:I386 /out:"example.dll" /pdbtype:sept
+
+!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 "$(TCL_INCLUDE)" /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 "$(TCL_LIB)" /nologo /dll /machine:I386 /out:"example.dll"
+
+!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.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\example_wrap.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# 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.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ echo In order to function correctly, please ensure the following environment variables are correctly set:
+ echo TCL_INCLUDE: %TCL_INCLUDE%
+ echo TCL_LIB: %TCL_LIB%
+ echo on
+ ..\..\..\swig.exe -tcl8 $(InputPath)
+
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "example - Win32 Release"
+
+# Begin Custom Build
+InputPath=.\example.i
+InputName=example
+
+"$(InputName)_wrap.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ echo In order to function correctly, please ensure the following environment variables are correctly set:
+ echo TCL_INCLUDE: %TCL_INCLUDE%
+ echo TCL_LIB: %TCL_LIB%
+ echo on
+ ..\..\..\swig.exe -tcl8 $(InputPath)
+
+# End Custom Build
+
+!ENDIF
+
+# End Source File
+# End Target
+# End Project
diff --git a/Examples/tcl/simple/example.i b/Examples/tcl/simple/example.i new file mode 100644 index 0000000..24093b9 --- /dev/null +++ b/Examples/tcl/simple/example.i @@ -0,0 +1,7 @@ +/* File : example.i */ +%module example + +%inline %{ +extern int gcd(int x, int y); +extern double Foo; +%} diff --git a/Examples/tcl/simple/index.html b/Examples/tcl/simple/index.html new file mode 100644 index 0000000..333d905 --- /dev/null +++ b/Examples/tcl/simple/index.html @@ -0,0 +1,97 @@ +<html> +<head> +<title>SWIG:Examples:tcl:simple</title> +</head> + +<body bgcolor="#ffffff"> + +<tt>SWIG/Examples/tcl/simple/</tt> +<hr> + +<H2>Simple Tcl Example</H2> + +<p> +This example illustrates how you can hook Tcl to a very simple C program containing +a function and a global variable. + +<h2>The C Code</h2> + +Suppose you have the following C code: + +<blockquote> +<pre> +/* File : example.c */ + +/* A global variable */ +double Foo = 3.0; + +/* Compute the greatest common divisor of positive integers */ +int gcd(int x, int y) { + int g; + g = y; + while (x > 0) { + g = x; + x = y % x; + y = g; + } + return g; +} +</pre> +</blockquote> + +<h2>The SWIG interface</h2> + +Here is a simple SWIG interface file: + +<blockquote> +<pre> +/* File: example.i */ +%module example + +extern int gcd(int x, int y); +extern double Foo; +</pre> +</blockquote> + +<h2>Compilation</h2> + +<ol> +<li><tt>swig -tcl <a href="example.i">example.i</a></tt> +<p> +<li>Compile <tt><a href="example_wrap.c">example_wrap.c</a></tt> and <tt><a href="example.c">example.c</a></tt> +to create the extension <tt>example.so</tt>. +</ol> + +<h2>Using the extension</h2> + +Click <a href="runme.tcl">here</a> to see a script that calls our C functions from Tcl. + +<h2>Key points</h2> + +<ul> +<li>Use the <tt>load</tt> statement to load your extension module into Tcl. For example: +<blockquote> +<pre> +load ./example.so +</pre> +</blockquote> + +<li>C functions work just like Tcl functions. For example: +<blockquote> +<pre> +set g [gcd 42 105] +</pre> +</blockquote> + +<li>C global variables are accessed as Tcl variables. For example: +<blockquote> +<pre> +set a $Foo +set Foo $newvalue +</pre> +</blockquote> +</ul> + +<hr> +</body> +</html> diff --git a/Examples/tcl/simple/runme.tcl b/Examples/tcl/simple/runme.tcl new file mode 100644 index 0000000..3a6ce10 --- /dev/null +++ b/Examples/tcl/simple/runme.tcl @@ -0,0 +1,22 @@ +# file: runme.tcl +# Try to load as a dynamic module. + +catch { load ./example[info sharedlibextension] example} + +# Call our gcd() function +set x 42 +set y 105 +set g [gcd $x $y] +puts "The gcd of $x and $y is $g" + +# Manipulate the Foo global variable + +# Output its current value +puts "Foo = $Foo" + +# Change its value +set Foo 3.1415926 + +# See if the change took effect +puts "Foo = $Foo" + diff --git a/Examples/tcl/std_vector/Makefile b/Examples/tcl/std_vector/Makefile new file mode 100644 index 0000000..ce6a3c7 --- /dev/null +++ b/Examples/tcl/std_vector/Makefile @@ -0,0 +1,20 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +CXXSRCS = +TARGET = my_tclsh +DLTARGET = example +INTERFACE = example.i +LIBS = -lm + +all:: + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + TARGET='$(DLTARGET)' INTERFACE='$(INTERFACE)' tcl_cpp + +static:: + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' tclsh_cpp_static + +clean:: + $(MAKE) -f $(TOP)/Makefile tcl_clean + +check: all diff --git a/Examples/tcl/std_vector/example.h b/Examples/tcl/std_vector/example.h new file mode 100644 index 0000000..4f0dac7 --- /dev/null +++ b/Examples/tcl/std_vector/example.h @@ -0,0 +1,25 @@ +/* File : example.h */ + +#include <vector> +#include <algorithm> +#include <functional> +#include <numeric> + +double average(std::vector<int> v) { + return std::accumulate(v.begin(),v.end(),0.0)/v.size(); +} + +std::vector<double> half(const std::vector<double>& v) { + std::vector<double> w(v); + for (unsigned int i=0; i<w.size(); i++) + w[i] /= 2.0; + return w; +} + +void halve_in_place(std::vector<double>& v) { + // would you believe this is the same as the above? + std::transform(v.begin(),v.end(),v.begin(), + std::bind2nd(std::divides<double>(),2.0)); +} + + diff --git a/Examples/tcl/std_vector/example.i b/Examples/tcl/std_vector/example.i new file mode 100644 index 0000000..aa58b66 --- /dev/null +++ b/Examples/tcl/std_vector/example.i @@ -0,0 +1,17 @@ +/* File : example.i */ +%module example + +%{ +#include "example.h" +%} + +%include stl.i +/* instantiate the required template specializations */ +namespace std { + %template(IntVector) vector<int>; + %template(DoubleVector) vector<double>; +} + +/* Let's just grab the original header file here */ +%include "example.h" + diff --git a/Examples/tcl/std_vector/runme.tcl b/Examples/tcl/std_vector/runme.tcl new file mode 100644 index 0000000..2cece96 --- /dev/null +++ b/Examples/tcl/std_vector/runme.tcl @@ -0,0 +1,40 @@ +# file: runme.tcl + +catch { load ./example[info sharedlibextension] example} + +# Exercise IntVector + +set iv [IntVector] +$iv push 1 +$iv push 3 +$iv push 5 + +puts "IntVector size: [$iv size] (should be 3)" +puts "IntVector average: [average $iv] (should be 3.0)" +puts "IntVector pop: [$iv pop] (should be 5)" +puts "IntVector pop: [$iv pop] (should be 3)" +puts "IntVector get 0: [$iv get 0] (should be 1)" +puts "" + +# Exercise DoubleVector + +set dv [DoubleVector] +$dv push 2 +$dv push 4 +$dv push 6 + +puts "DoubleVector size: [$dv size] (should be 3)" +puts "DoubleVector data: [$dv get 0] [$dv get 1] [$dv get 2] (should be 2.0 4.0 6.0)" +halve_in_place $dv +puts "DoubleVector halved: [$dv get 0] [$dv get 1] [$dv get 2] (should be 1.0 2.0 3.0)" +puts "" + +# Complain if unknown is called +rename unknown unknown_orig +proc unknown {args} { + puts "ERROR: unknown called with: $args" + uplevel 1 unknown_orig $args +} + +puts "average \"1 2 3\": [average [list 1 2 3]]" + diff --git a/Examples/tcl/value/Makefile b/Examples/tcl/value/Makefile new file mode 100644 index 0000000..bed049a --- /dev/null +++ b/Examples/tcl/value/Makefile @@ -0,0 +1,19 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +SRCS = example.c +TARGET = my_tclsh +DLTARGET = example +INTERFACE = example.i + +all:: + $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \ + TARGET='$(DLTARGET)' INTERFACE='$(INTERFACE)' tcl + +static:: + $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \ + TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' tclsh + +clean:: + $(MAKE) -f $(TOP)/Makefile tcl_clean + +check: all diff --git a/Examples/tcl/value/example.c b/Examples/tcl/value/example.c new file mode 100644 index 0000000..4ed2fe1 --- /dev/null +++ b/Examples/tcl/value/example.c @@ -0,0 +1,15 @@ +/* File : example.c */ + +#include "example.h" + +double dot_product(Vector a, Vector b) { + return (a.x*b.x + a.y*b.y + a.z*b.z); +} + +Vector vector_add(Vector a, Vector b) { + Vector r; + r.x = a.x + b.x; + r.y = a.y + b.y; + r.z = a.z + b.z; + return r; +} diff --git a/Examples/tcl/value/example.h b/Examples/tcl/value/example.h new file mode 100644 index 0000000..212cf4b --- /dev/null +++ b/Examples/tcl/value/example.h @@ -0,0 +1,5 @@ +/* File : example.h */ + +typedef struct { + double x, y, z; +} Vector; diff --git a/Examples/tcl/value/example.i b/Examples/tcl/value/example.i new file mode 100644 index 0000000..98fd60e --- /dev/null +++ b/Examples/tcl/value/example.i @@ -0,0 +1,32 @@ +// Tests SWIG's handling of pass-by-value for complex datatypes +%module example + +%{ +#include "example.h" +%} + +/* Some functions that manipulate Vectors by value */ +%inline %{ +extern double dot_product(Vector a, Vector b); +extern Vector vector_add(Vector a, Vector b); +%} + +/* Include this because the vector_add() function will leak memory */ +void free(void *); + +/* Some helper functions for our interface */ +%inline %{ + +Vector *new_Vector(double x, double y, double z) { + Vector *v = (Vector *) malloc(sizeof(Vector)); + v->x = x; + v->y = y; + v->z = z; + return v; +} + +void vector_print(Vector *v) { + printf("Vector %p = (%g, %g, %g)\n", v, v->x, v->y, v->z); +} +%} + diff --git a/Examples/tcl/value/index.html b/Examples/tcl/value/index.html new file mode 100644 index 0000000..17a991e --- /dev/null +++ b/Examples/tcl/value/index.html @@ -0,0 +1,122 @@ +<html> +<head> +<title>SWIG:Examples:tcl:value</title> +</head> + +<body bgcolor="#ffffff"> + + +<tt>SWIG/Examples/tcl/value/</tt> +<hr> + +<H2>Passing and Returning Structures by Value</H2> + +<p> +Occasionally, a C program will manipulate structures by value such as shown in the +following code: + +<blockquote> +<pre> +/* File : example.c */ + +typedef struct Vector { + double x, y, z; +} Vector; + +double dot_product(Vector a, Vector b) { + return (a.x*b.x + a.y*b.y + a.z*b.z); +} + +Vector vector_add(Vector a, Vector b) { + Vector r; + r.x = a.x + b.x; + r.y = a.y + b.y; + r.z = a.z + b.z; + return r; +} +</pre> +</blockquote> + +Since SWIG only knows how to manage pointers to structures (not their internal +representation), the following translations are made when wrappers are +created: + +<blockquote> +<pre> +double wrap_dot_product(Vector *a, Vector *b) { + return dot_product(*a,*b); +} + +Vector *wrap_vector_add(Vector *a, Vector *b) { + Vector *r = (Vector *) malloc(sizeof(Vector)); + *r = vector_add(*a,*b); + return r; +} +</pre> +</blockquote> + +The functions are then called using pointers from the scripting language interface. +It should also be noted that any function that returns a structure by value results +in an implicit memory allocation. This will be a memory leak unless you take steps +to free the result (see below). + +<h2>The SWIG interface</h2> + +Click <a href="example.i">here</a> to see a SWIG interface file that +wraps these two functions. In this file, there are a few essential features: + +<ul> +<li>A wrapper for the <tt>free()</tt> function is created so that we +can clean up the return result created by <tt>vector_add()</tt> +function. + +<p> +<li>The %inline directive is used to create a few helper functions for creating new Vector +objects and to print out the value (for debugging purposes). +</ul> + +<h2>A Tcl Script</h2> + +Click <a href="runme.tcl">here</a> to see a script that uses these functions from Tcl. + +<h2>Notes</h2> + +<ul> +<li>When the '<tt>-c++</tt>' option is used, the resulting wrapper code for the return value +changes to the following: + +<blockquote> +<pre> +Vector *wrap_vector_add(Vector *a, Vector *b) { + Vector *r = new Vector(vector_add(*a,*b)); + return r; +} +</pre> +</blockquote> + +Similarly, it would be a mistake to use the <tt>free()</tt> function from C++. A safer +approach would be to write a helper function like this: + +<blockquote> +<pre> +%inline %{ + void delete_Vector(Vector *v) { + delete v; + } +%} +</pre> +</blockquote> + +<p> +<li>Passing parameters by value like this really isn't the best C programming style. +If possible, you might change your application to use pointers. + +<p> +<li>Similar translations are made when C++ references are used. + + +</ul> + +<hr> +</body> +</html> diff --git a/Examples/tcl/value/runme.tcl b/Examples/tcl/value/runme.tcl new file mode 100644 index 0000000..1f6f4af --- /dev/null +++ b/Examples/tcl/value/runme.tcl @@ -0,0 +1,39 @@ +# file: runme.tcl +# Try to load as a dynamic module. + +catch { load ./example[info sharedlibextension] example} + +# Create a couple of a vectors + +set v [new_Vector 1 2 3] +set w [new_Vector 10 11 12] + +puts "I just created the following vectors" +vector_print $v +vector_print $w + +# Now call some of our functions + +puts "\nNow I'm going to compute the dot product" +set d [dot_product $v $w] +puts "dot product = $d (should be 68)" + +# Add the vectors together + +puts "\nNow I'm going to add the vectors together" +set r [vector_add $v $w] +vector_print $r +puts "The value should be (11,13,15)" + +# Now I'd better clean up the return result r + +puts "\nNow I'm going to clean up the return result" +free $r + +puts "Good" + + + + + + diff --git a/Examples/tcl/variables/Makefile b/Examples/tcl/variables/Makefile new file mode 100644 index 0000000..bed049a --- /dev/null +++ b/Examples/tcl/variables/Makefile @@ -0,0 +1,19 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +SRCS = example.c +TARGET = my_tclsh +DLTARGET = example +INTERFACE = example.i + +all:: + $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \ + TARGET='$(DLTARGET)' INTERFACE='$(INTERFACE)' tcl + +static:: + $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \ + TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' tclsh + +clean:: + $(MAKE) -f $(TOP)/Makefile tcl_clean + +check: all diff --git a/Examples/tcl/variables/example.c b/Examples/tcl/variables/example.c new file mode 100644 index 0000000..aa4ffe9 --- /dev/null +++ b/Examples/tcl/variables/example.c @@ -0,0 +1,91 @@ +/* File : example.c */ + +/* I'm a file containing some C global variables */ + +/* Deal with Microsoft's attempt at deprecating C standard runtime functions */ +#if !defined(SWIG_NO_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) +# define _CRT_SECURE_NO_DEPRECATE +#endif + +#include <stdio.h> +#include <stdlib.h> +#include "example.h" + +int ivar = 0; +short svar = 0; +long lvar = 0; +unsigned int uivar = 0; +unsigned short usvar = 0; +unsigned long ulvar = 0; +signed char scvar = 0; +unsigned char ucvar = 0; +char cvar = 0; +float fvar = 0; +double dvar = 0; +char *strvar = 0; +const char cstrvar[] = "Goodbye"; +int *iptrvar = 0; +char name[256] = "Dave"; +char path[256] = "/home/beazley"; + + +/* Global variables involving a structure */ +Point *ptptr = 0; +Point pt = { 10, 20 }; + +/* A variable that we will make read-only in the interface */ +int status = 1; + +/* A debugging function to print out their values */ + +void print_vars() { + printf("ivar = %d\n", ivar); + printf("svar = %d\n", svar); + printf("lvar = %ld\n", lvar); + printf("uivar = %u\n", uivar); + printf("usvar = %u\n", usvar); + printf("ulvar = %lu\n", ulvar); + printf("scvar = %d\n", scvar); + printf("ucvar = %u\n", ucvar); + printf("fvar = %g\n", fvar); + printf("dvar = %g\n", dvar); + printf("cvar = %c\n", cvar); + printf("strvar = %s\n", strvar ? strvar : "(null)"); + printf("cstrvar = %s\n", cstrvar ? cstrvar : "(null)"); + printf("iptrvar = %p\n", iptrvar); + printf("name = %s\n", name); + printf("ptptr = %p (%d, %d)\n", ptptr, ptptr ? ptptr->x : 0, ptptr ? ptptr->y : 0); + printf("pt = (%d, %d)\n", pt.x, pt.y); + printf("status = %d\n", status); +} + +/* A function to create an integer (to test iptrvar) */ + +int *new_int(int value) { + int *ip = (int *) malloc(sizeof(int)); + *ip = value; + return ip; +} + +/* A function to create a point */ + +Point *new_Point(int x, int y) { + Point *p = (Point *) malloc(sizeof(Point)); + p->x = x; + p->y = y; + return p; +} + +char * Point_print(Point *p) { + static char buffer[256]; + if (p) { + sprintf(buffer,"(%d,%d)", p->x,p->y); + } else { + sprintf(buffer,"null"); + } + return buffer; +} + +void pt_print() { + printf("(%d, %d)\n", pt.x, pt.y); +} diff --git a/Examples/tcl/variables/example.h b/Examples/tcl/variables/example.h new file mode 100644 index 0000000..0f7e895 --- /dev/null +++ b/Examples/tcl/variables/example.h @@ -0,0 +1,6 @@ +/* File: example.h */ + +typedef struct { + int x,y; +} Point; + diff --git a/Examples/tcl/variables/example.i b/Examples/tcl/variables/example.i new file mode 100644 index 0000000..9d0101c --- /dev/null +++ b/Examples/tcl/variables/example.i @@ -0,0 +1,51 @@ +/* File : example.i */ +%module example +%{ +#include "example.h" +%} + +#pragma SWIG nowarn=SWIGWARN_TYPEMAP_SWIGTYPELEAK + +/* Some global variable declarations */ +%inline %{ +extern int ivar; +extern short svar; +extern long lvar; +extern unsigned int uivar; +extern unsigned short usvar; +extern unsigned long ulvar; +extern signed char scvar; +extern unsigned char ucvar; +extern char cvar; +extern float fvar; +extern double dvar; +extern char *strvar; +extern const char cstrvar[]; +extern int *iptrvar; +extern char name[256]; + +extern Point *ptptr; +extern Point pt; +%} + + +/* Some read-only variables */ + +%immutable; + +%inline %{ +extern int status; +extern char path[256]; +%} + +%mutable; + +/* Some helper functions to make it easier to test */ +%inline %{ +extern void print_vars(); +extern int *new_int(int value); +extern Point *new_Point(int x, int y); +extern char *Point_print(Point *p); +extern void pt_print(); +%} + diff --git a/Examples/tcl/variables/index.html b/Examples/tcl/variables/index.html new file mode 100644 index 0000000..245a445 --- /dev/null +++ b/Examples/tcl/variables/index.html @@ -0,0 +1,76 @@ +<html> +<head> +<title>SWIG:Examples:tcl:variables</title> +</head> + +<body bgcolor="#ffffff"> + +<tt>SWIG/Examples/tcl/variables/</tt> +<hr> + +<H2>Wrapping C Global Variables</H2> + +<p> +When a C global variable appears in an interface file, SWIG tries to wrap it using a technique +known as "variable linking." The idea is pretty simple---we try to create a Tcl +variable that works exactly like you would expect in a Tcl script, but which magically +retrieves or updates the value of the underlying C variable. +Click <a href="example.i">here</a> to see a SWIG interface with some variable declarations in it. + +<h2>Manipulating Variables from Tcl</h2> + +Click <a href="runme.tcl">here</a> to see a script that updates and prints out the values of +the variables defined in the above file. Notice how the C global variables work just +like normal Tcl variables. + +<h2>Key points</h2> + +<ul> +<li>The <tt>set</tt> statement changes the value of the corresponding C global variable. +<li>Whenever you access the value of a variable such as <tt>$ivar</tt>, the value +of the C global variable is read. +<li>If a C program changes a global variable independently of Tcl, this change is +automatically reflected in the Tcl variable (i.e., reads will always return the +most up to date value of the variable). +<li>When a global variable has the type "<tt>char *</tt>", SWIG manages it as a character +string. However, whenever the value of such a variable is set from Tcl, the old +value is destroyed using <tt>free()</tt> or <tt>delete</tt> (the choice of which depends +on whether or not SWIG was run with the -c++ option). +<li><tt>signed char</tt> and <tt>unsigned char</tt> are handled as small 8-bit integers. +<li>String array variables such as '<tt>char name[256]</tt>' are managed as Tcl strings, but +when setting the value, the result is truncated to the maximum length of the array. Furthermore, the string is assumed to be null-terminated. +<li>When structures and classes are used as global variables, they are mapped into pointers. +Getting the "value" returns a pointer to the global variable. Setting the value of a structure results in a memory copy from a pointer to the global. +</ul> + +<h2>Creating read-only variables</h2> + +The <tt>%immutable</tt> and <tt>%mutable</tt> directives can be used to +specify a collection of read-only variables. For example: + +<blockquote> +<pre> +%immutable; +int status; +double blah; +... +%mutable; +</pre> +</blockquote> + +The <tt>%immutable</tt> directive remains in effect until it is explicitly disabled +using the <tt>%mutable</tt> directive. + +<h2>Comments</h2> +<ul> +<li>Management of global variables is one of the most problematic aspects +of C/C++ wrapping because the scripting interface and resulting memory management +is much trickier than simply creating a wrapper function. +<p> +<li>You may be better off hiding global variables behind a function based +interface. +</ul> + +</body> +</html> +<hr> diff --git a/Examples/tcl/variables/runme.tcl b/Examples/tcl/variables/runme.tcl new file mode 100644 index 0000000..b9e2fd4 --- /dev/null +++ b/Examples/tcl/variables/runme.tcl @@ -0,0 +1,76 @@ +# file: runme.tcl + +catch { load ./example[info sharedlibextension] example} + +# Try to set the values of some global variables + +set ivar 42 +set svar -31000 +set lvar 65537 +set uivar 123456 +set usvar 61000 +set ulvar 654321 +set scvar -13 +set ucvar 251 +set cvar "S" +set fvar 3.14159 +set dvar 2.1828 +set strvar "Hello World" +set iptrvar [new_int 37] +set ptptr [new_Point 37 42] +set name "Bill" + +# Now print out the values of the variables + +puts "Variables (values printed from Tcl)" + +puts "ivar = $ivar" +puts "svar = $svar" +puts "lvar = $lvar" +puts "uivar = $uivar" +puts "usvar = $usvar" +puts "ulvar = $ulvar" +puts "scvar = $scvar" +puts "ucvar = $ucvar" +puts "fvar = $fvar" +puts "dvar = $dvar" +puts "cvar = $cvar" +puts "strvar = $strvar" +puts "cstrvar = $cstrvar" +puts "iptrvar = $iptrvar" +puts "name = $name" +puts "ptptr = $ptptr [Point_print $ptptr]" +puts "pt = $pt [Point_print $pt]" + +puts "\nVariables (values printed from C)" + +print_vars + +puts "\nNow I'm going to try and modify some read only variables"; + +puts " Tring to set 'path'"; +if { [catch { + set path "Whoa!" + puts "Hey, what's going on?!?! This shouldn't work" +}]} { + puts "Good." +} + +puts " Trying to set 'status'"; +if { [catch { + set status 0 + puts "Hey, what's going on?!?! This shouldn't work" +}]} { + puts "Good." +} + +puts "\nI'm going to try and update a structure variable.\n" + +set pt $ptptr + +puts "The new value is" +pt_print +puts "You should see the value [Point_print $ptptr]" + + + |
