Initial commit

This commit is contained in:
Bassem Girgis
2018-12-20 17:34:07 -06:00
parent 7a2d899662
commit 81b4b9e273
34743 changed files with 5940233 additions and 0 deletions

View File

@@ -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

View File

@@ -0,0 +1,23 @@
TOP = ../..
SWIGEXE = $(TOP)/../swig
SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib
CXXSRCS = example.cxx
TARGET = example
INTERFACE = example.i
LIBS = -lm
check: build
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' tcl_run
build:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' tcl_cpp
static:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='mytclsh' INTERFACE='$(INTERFACE)' tclsh_cpp_static
clean:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' tcl_clean

View File

@@ -0,0 +1,28 @@
/* File : example.cxx */
#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() {
return M_PI*radius*radius;
}
double Circle::perimeter() {
return 2*M_PI*radius;
}
double Square::area() {
return width*width;
}
double Square::perimeter() {
return 4*width;
}

View File

@@ -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

View File

@@ -0,0 +1,34 @@
/* 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();
};

View File

@@ -0,0 +1,9 @@
/* File : example.i */
%module example
%{
#include "example.h"
%}
/* Let's just grab the original header file here */
%include "example.h"

View File

@@ -0,0 +1,242 @@
<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="runme.tcl">here</a> to see a script that calls the C++ functions using the
low-level interface.
<li>
Click <a href="runme2.tcl">here</a> to see 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.
<li>SWIG <b>does</b> 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.
<li>C++ Namespaces - %nspace isn't yet supported for Tcl.
</ul>
<hr>
</body>
</html>

View File

@@ -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"

View File

@@ -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"

View File

@@ -0,0 +1,23 @@
TOP = ../..
SWIGEXE = $(TOP)/../swig
SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib
SRCS =
TARGET = my_tclsh
DLTARGET = example
INTERFACE = example.i
check: build
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' tcl_run
build:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='$(DLTARGET)' INTERFACE='$(INTERFACE)' tcl
static:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' tclsh
clean:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' tcl_clean

View File

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

View File

@@ -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>

View File

@@ -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)"
}

View File

@@ -0,0 +1,24 @@
TOP = ../..
SWIGEXE = $(TOP)/../swig
SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib
SRCS = example.c
TARGET = my_tclsh
DLTARGET = example
INTERFACE = example.i
SWIGOPT =
check: build
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' tcl_run
build:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
SWIGOPT='$(SWIGOPT)' TARGET='$(DLTARGET)' INTERFACE='$(INTERFACE)' tcl
static:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' tclsh
clean:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' tcl_clean

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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;
%}

View File

@@ -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"

View File

@@ -0,0 +1,23 @@
TOP = ../..
SWIGEXE = $(TOP)/../swig
SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib
CXXSRCS = example.cxx
TARGET = example
INTERFACE = example.i
LIBS = -lm
check: build
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' tcl_run
build:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' tcl_cpp
static:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='mytclsh' INTERFACE='$(INTERFACE)' tclsh_cpp_static
clean:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' tcl_clean

View File

@@ -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");
}
}

View File

@@ -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);

View File

@@ -0,0 +1,11 @@
/* File : example.i */
%module example
%{
#include "example.h"
%}
/* Let's just grab the original header file here */
%include "example.h"

View File

@@ -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>

View File

@@ -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

View File

@@ -0,0 +1,23 @@
TOP = ../..
SWIGEXE = $(TOP)/../swig
SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib
SRCS = example.c
TARGET = my_tclsh
DLTARGET = example
INTERFACE = example.i
check: build
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' tcl_run
build:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='$(DLTARGET)' INTERFACE='$(INTERFACE)' tcl
static:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' tclsh
clean:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' tcl_clean

View File

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

View File

@@ -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);

View File

@@ -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);

View File

@@ -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>

View File

@@ -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"

View File

@@ -0,0 +1,26 @@
TOP = ../..
SWIGEXE = $(TOP)/../swig
SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib
SWIGOPT =
LIBS =
check: build
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' tcl_run
build:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
SWIGOPT='$(SWIGOPT)' LIBS='$(LIBS)' TARGET='base' INTERFACE='base.i' tcl_cpp
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
SWIGOPT='$(SWIGOPT)' LIBS='$(LIBS)' TARGET='foo' INTERFACE='foo.i' tcl_cpp
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
SWIGOPT='$(SWIGOPT)' LIBS='$(LIBS)' TARGET='bar' INTERFACE='bar.i' tcl_cpp
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
SWIGOPT='$(SWIGOPT)' LIBS='$(LIBS)' TARGET='spam' INTERFACE='spam.i' tcl_cpp
clean:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' tcl_clean

View File

@@ -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

View File

@@ -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

View File

@@ -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);
}
};

View File

@@ -0,0 +1,9 @@
%module bar
%{
#include "bar.h"
%}
%import base.i
%include "bar.h"

View File

@@ -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

View File

@@ -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);
}
};

View File

@@ -0,0 +1,6 @@
%module base
%{
#include "base.h"
%}
%include base.h

View File

@@ -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>
{{{
}}}
###############################################################################

View File

@@ -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

View File

@@ -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);
}
};

View File

@@ -0,0 +1,8 @@
%module foo
%{
#include "foo.h"
%}
%import base.i
%include "foo.h"

View File

@@ -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"
}

View File

@@ -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

View File

@@ -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);
}
};

View File

@@ -0,0 +1,9 @@
%module spam
%{
#include "spam.h"
%}
%import bar.i
%include "spam.h"

View File

@@ -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>

View File

@@ -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);
}
}

View File

@@ -0,0 +1,24 @@
TOP = ../..
SWIGEXE = $(TOP)/../swig
SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib
CXXSRCS =
TARGET = example
INTERFACE = example.i
LIBS = -lm
check: build
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' tcl_run
build: Example.class Example.h
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \
TCLCXXSHARED="gcj -fpic -shared Example.class " LIBS="-lstdc++" DEFS='' tcl_cpp
clean:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' tcl_clean
rm -f *.class Example.h
Example.class Example.h: $(SRCDIR)Example.java
gcj -d . -fPIC -C -c -g $(SRCDIR)Example.java
gcjh Example.class

View File

@@ -0,0 +1,8 @@
%module example
%include <cni.i>
%{
#include "Example.h"
%}
%include Example.h

View File

@@ -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

View File

@@ -0,0 +1,23 @@
TOP = ../..
SWIGEXE = $(TOP)/../swig
SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib
SRCS = example.c
TARGET = my_tclsh
DLTARGET = example
INTERFACE = example.i
check: build
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' tcl_run
build:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='$(DLTARGET)' INTERFACE='$(INTERFACE)' tcl
static:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' tclsh
clean:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' tcl_clean

View File

@@ -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);
}
}

View File

@@ -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

View File

@@ -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);

View File

@@ -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

View File

@@ -0,0 +1,23 @@
TOP = ../..
SWIGEXE = $(TOP)/../swig
SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib
CXXSRCS =
TARGET = example
INTERFACE = example.i
LIBS = -lm
check: build
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' tcl_run
build:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' tcl_cpp
static:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='mytclsh' INTERFACE='$(INTERFACE)' tclsh_cpp_static
clean:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' tcl_clean

View File

@@ -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; }
};

View File

@@ -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;
}
};

View File

@@ -0,0 +1,27 @@
# 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]
puts "c = $c [$c str]"
set d [$a * $b]
puts "a*b = [$d str]"
# Alternative calling convention
set e [Complex_- $a $c]
puts "a-c = [Complex_str $e]"
set f [new_ComplexCopy $e]
puts "f = [$f str]"
# Call assignment operator
$c = $f
puts "c = [$c str]"

View File

@@ -0,0 +1,23 @@
TOP = ../..
SWIGEXE = $(TOP)/../swig
SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib
SRCS = example.c
TARGET = my_tclsh
DLTARGET = example
INTERFACE = example.i
check: build
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' tcl_run
build:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='$(DLTARGET)' INTERFACE='$(INTERFACE)' tcl
static:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' tclsh
clean:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' tcl_clean

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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>

View File

@@ -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"

View File

@@ -0,0 +1,23 @@
TOP = ../..
SWIGEXE = $(TOP)/../swig
SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib
CXXSRCS = example.cxx
TARGET = example
INTERFACE = example.i
LIBS = -lm
check: build
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' tcl_run
build:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' tcl_cpp
static:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='mytclsh' INTERFACE='$(INTERFACE)' tclsh_cpp_static
clean:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' tcl_clean

View File

@@ -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)", (void *)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;
}

View File

@@ -0,0 +1,22 @@
/* 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();
};

View File

@@ -0,0 +1,42 @@
/* 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;
}
}
};

View File

@@ -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 &amp;a, const Vector &amp;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 &amp;a, const Vector &amp;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 &amp;operator[](int index);
</pre>
</blockquote>
or a method:
<blockquote>
<pre>
Vector &amp;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 &amp;result = self-&gt;get(index);
return &amp;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 &amp;get(int index) {
return (*self)[index];
}
void set(int index, Vector &amp;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-&gt;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>

View File

@@ -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

View File

@@ -0,0 +1,23 @@
TOP = ../..
SWIGEXE = $(TOP)/../swig
SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib
SRCS = example.c
TARGET = my_tclsh
DLTARGET = example
INTERFACE = example.i
check: build
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' tcl_run
build:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='$(DLTARGET)' INTERFACE='$(INTERFACE)' tcl
static:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' tclsh
clean:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' tcl_clean

View File

@@ -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;
}

View File

@@ -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

View File

@@ -0,0 +1,7 @@
/* File : example.i */
%module example
%inline %{
extern int gcd(int x, int y);
extern double Foo;
%}

View File

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

View File

@@ -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"

View File

@@ -0,0 +1,24 @@
TOP = ../..
SWIGEXE = $(TOP)/../swig
SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib
CXXSRCS =
TARGET = my_tclsh
DLTARGET = example
INTERFACE = example.i
LIBS = -lm
check: build
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' tcl_run
build:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='$(DLTARGET)' INTERFACE='$(INTERFACE)' tcl_cpp
static:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' tclsh_cpp_static
clean:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' tcl_clean

View File

@@ -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));
}

View File

@@ -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"

View File

@@ -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]]"

View File

@@ -0,0 +1,23 @@
TOP = ../..
SWIGEXE = $(TOP)/../swig
SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib
SRCS = example.c
TARGET = my_tclsh
DLTARGET = example
INTERFACE = example.i
check: build
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' tcl_run
build:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='$(DLTARGET)' INTERFACE='$(INTERFACE)' tcl
static:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' tclsh
clean:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' tcl_clean

View File

@@ -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;
}

View File

@@ -0,0 +1,5 @@
/* File : example.h */
typedef struct {
double x, y, z;
} Vector;

View File

@@ -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", (void *)v, v->x, v->y, v->z);
}
%}

View File

@@ -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>

View File

@@ -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"

View File

@@ -0,0 +1,23 @@
TOP = ../..
SWIGEXE = $(TOP)/../swig
SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib
SRCS = example.c
TARGET = my_tclsh
DLTARGET = example
INTERFACE = example.i
check: build
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' tcl_run
build:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='$(DLTARGET)' INTERFACE='$(INTERFACE)' tcl
static:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' tclsh
clean:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' tcl_clean

View File

@@ -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);
printf("iptrvar = %p\n", (void *)iptrvar);
printf("name = %s\n", name);
printf("ptptr = %p (%d, %d)\n", (void *)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);
}

View File

@@ -0,0 +1,6 @@
/* File: example.h */
typedef struct {
int x,y;
} Point;

View File

@@ -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();
%}

View File

@@ -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>

View File

@@ -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]"