diff options
Diffstat (limited to 'trunk/Examples/perl5')
89 files changed, 4140 insertions, 0 deletions
diff --git a/trunk/Examples/perl5/check.list b/trunk/Examples/perl5/check.list new file mode 100644 index 000000000..e15f02e18 --- /dev/null +++ b/trunk/Examples/perl5/check.list @@ -0,0 +1,14 @@ +# see top-level Makefile.in +class +constants +constants2 +funcptr +import +java +multimap +multiple_inheritance +pointer +reference +simple +value +variables diff --git a/trunk/Examples/perl5/class/Makefile b/trunk/Examples/perl5/class/Makefile new file mode 100644 index 000000000..f53361730 --- /dev/null +++ b/trunk/Examples/perl5/class/Makefile @@ -0,0 +1,19 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +CXXSRCS = example.cxx +TARGET = example +INTERFACE = example.i +LIBS = -lm + +all:: + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' perl5_cpp + +static:: + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + TARGET='myperl' INTERFACE='$(INTERFACE)' perl5_cpp_static + +clean:: + $(MAKE) -f $(TOP)/Makefile perl5_clean + +check: all diff --git a/trunk/Examples/perl5/class/example.cxx b/trunk/Examples/perl5/class/example.cxx new file mode 100644 index 000000000..1e8e203dd --- /dev/null +++ b/trunk/Examples/perl5/class/example.cxx @@ -0,0 +1,28 @@ +/* File : example.c */ + +#include "example.h" +#define M_PI 3.14159265358979323846 + +/* Move the shape to a new location */ +void Shape::move(double dx, double dy) { + x += dx; + y += dy; +} + +int Shape::nshapes = 0; + +double Circle::area(void) { + return M_PI*radius*radius; +} + +double Circle::perimeter(void) { + return 2*M_PI*radius; +} + +double Square::area(void) { + return width*width; +} + +double Square::perimeter(void) { + return 4*width; +} diff --git a/trunk/Examples/perl5/class/example.dsp b/trunk/Examples/perl5/class/example.dsp new file mode 100644 index 000000000..b5ccd1928 --- /dev/null +++ b/trunk/Examples/perl5/class/example.dsp @@ -0,0 +1,152 @@ +# Microsoft Developer Studio Project File - Name="example" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=example - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "example.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "example.mak" CFG="example - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "example - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "example - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "example - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "$(PERL5_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 "$(PERL5_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 "$(PERL5_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 "$(PERL5_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 PERL5_INCLUDE: %PERL5_INCLUDE%
+ echo PERL5_LIB: %PERL5_LIB%
+ echo on
+ ..\..\..\swig.exe -c++ -perl5 $(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 PERL5_INCLUDE: %PERL5_INCLUDE%
+ echo PERL5_LIB: %PERL5_LIB%
+ echo on
+ ..\..\..\swig.exe -c++ -perl5 $(InputPath)
+
+# End Custom Build
+
+!ENDIF
+
+# End Source File
+# End Target
+# End Project
diff --git a/trunk/Examples/perl5/class/example.h b/trunk/Examples/perl5/class/example.h new file mode 100644 index 000000000..b0671d583 --- /dev/null +++ b/trunk/Examples/perl5/class/example.h @@ -0,0 +1,47 @@ +/* File : example.h */ + +class Shape { +public: + Shape() { + nshapes++; + } + virtual ~Shape() { + nshapes--; + }; + double x, y; + void move(double dx, double dy); + virtual double area(void) = 0; + virtual double perimeter(void) = 0; + static int nshapes; +}; + +class Circle : public Shape { +private: + double radius; +public: + Circle(double r) : radius(r) { }; + virtual double area(void); + virtual double perimeter(void); +}; + +class Square : public Shape { +private: + double width; +public: + Square(double w) : width(w) { }; + virtual double area(void); + virtual double perimeter(void); +}; + +typedef Square TSquare; +class CFoo +{ +public: + static Square MakeSquare(void) {return Square(4.0);}; + static TSquare MakeTSquare(void) {return Square(4.0);}; +}; + + + + + diff --git a/trunk/Examples/perl5/class/example.i b/trunk/Examples/perl5/class/example.i new file mode 100644 index 000000000..23ee8a822 --- /dev/null +++ b/trunk/Examples/perl5/class/example.i @@ -0,0 +1,11 @@ +/* File : example.i */ +%module example + +%{ +#include "example.h" +%} + +/* Let's just grab the original header file here */ + +%include "example.h" + diff --git a/trunk/Examples/perl5/class/index.html b/trunk/Examples/perl5/class/index.html new file mode 100644 index 000000000..58a50ad2e --- /dev/null +++ b/trunk/Examples/perl5/class/index.html @@ -0,0 +1,208 @@ +<html> +<head> +<title>SWIG:Examples:perl5:class</title> +</head> + +<body bgcolor="#ffffff"> + + +<tt>SWIG/Examples/perl5/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++ -python example.i +</pre> +</blockquote> + +<h2>A sample Perl script</h2> + +Click <a href="runme.pl">here</a> to see a script that calls the C++ functions from Perl. + +<h2>Key points</h2> + +<ul> +<li>To create a new object, you call a constructor like this: + +<blockquote> +<pre> +$c = example::new_Circle(10.0); +</pre> +</blockquote> + +<p> +<li>To access member data, a pair of accessor functions are used. +For example: + +<blockquote> +<pre> +example::Shape_x_set($c,15); # Set member data +$x = example::Shape_x_get($c); # Get member data +</pre> +</blockquote> + +Note: when accessing member data, the name of the class in which +the data member is defined is used. For example <tt>Shape_x_get()</tt>. + +<p> +<li>To invoke a member function, you simply do this + +<blockquote> +<pre> +print "The area is ", example::Shape_area($c); +</pre> +</blockquote> + +<p> +<li>Type checking knows about the inheritance structure of C++. For example: + +<blockquote> +<pre> +example::Shape_area($c); # Works (c is a Shape) +example::Circle_area($c); # Works (c is a Circle) +example::Square_area($c); # Fails (c is definitely not a Square) +</pre> +</blockquote> + +<p> +<li>To invoke a destructor, simply do this + +<blockquote> +<pre> +example::delete_Shape($c); # Deletes a shape +</pre> +</blockquote> + +<p> +<li>Static member variables are wrapped as C global variables. For example: + +<blockquote> +<pre> +$n = $example::Shape_nshapes; # Get a static data member +$example::Shapes_nshapes = 13; # Set a static data member +</pre> +</blockquote> + +</ul> + +<h2>General Comments</h2> + +<ul> +<li>This low-level interface is not the only way to handle C++ code. Proxy classes +provide a much higher-level interface. + +<p> +<li>SWIG *does* know how to properly perform upcasting of objects in an inheritance +hierarchy (including multiple inheritance). Therefore it is perfectly safe to pass +an object of a derived class to any function involving a base class. + +<p> +<li>A wide variety of C++ features are not currently supported by SWIG. Here is the +short and incomplete list: + +<p> +<ul> +<li>Overloaded methods and functions. SWIG wrappers don't know how to resolve name +conflicts so you must give an alternative name to any overloaded method name using the +%name directive like this: + +<blockquote> +<pre> +void foo(int a); +%name(foo2) void foo(double a, double b); +</pre> +</blockquote> + +<p> +<li>Overloaded operators. Not supported at all. The only workaround for this is +to write a helper function. For example: + +<blockquote> +<pre> +%inline %{ + Vector *vector_add(Vector *a, Vector *b) { + ... whatever ... + } +%} +</pre> +</blockquote> + +<p> +<li>Namespaces. Not supported at all. Won't be supported until SWIG2.0 (if at all). + +</ul> + +<hr> +</body> +</html> diff --git a/trunk/Examples/perl5/class/runme.pl b/trunk/Examples/perl5/class/runme.pl new file mode 100644 index 000000000..076e1437b --- /dev/null +++ b/trunk/Examples/perl5/class/runme.pl @@ -0,0 +1,60 @@ +# file: runme.pl + +# This file illustrates the low-level C++ interface +# created by SWIG. In this case, all of our C++ classes +# get converted into function calls. + +use example; + +# ----- Object creation ----- + +print "Creating some objects:\n"; +$c = new example::Circle(10); +print " Created circle $c\n"; +$s = new example::Square(10); +print " Created square $s\n"; + +# ----- Access a static member ----- + +print "\nA total of $example::Shape::nshapes shapes were created\n"; + +# ----- Member data access ----- + +# Set the location of the object. +# Note: methods in the base class Shape are used since +# x and y are defined there. + +$c->{x} = 20; +$c->{y} = 30; +$s->{x} = -10; +$s->{y} = 5; + +print "\nHere is their current position:\n"; +print " Circle = (",$c->{x},",", $c->{y},")\n"; +print " Square = (",$s->{x},",", $s->{y},")\n"; + +# ----- Call some methods ----- + +print "\nHere are some properties of the shapes:\n"; +foreach $o ($c,$s) { + print " $o\n"; + print " area = ", $o->area(), "\n"; + print " perimeter = ", $o->perimeter(), "\n"; + } + +# ----- Delete everything ----- + +print "\nGuess I'll clean up now\n"; + +# Note: this invokes the virtual destructor + +$c->DESTROY(); +$s->DESTROY(); + +print $example::Shape::nshapes," shapes remain\n"; + +$square = example::CFoo::MakeSquare(); +$tsquare = example::CFoo::MakeTSquare(); +print "Areas ", $square->area(), " ", $tsquare->area(),"\n"; + +print "Goodbye\n"; diff --git a/trunk/Examples/perl5/constants/Makefile b/trunk/Examples/perl5/constants/Makefile new file mode 100644 index 000000000..576d2a095 --- /dev/null +++ b/trunk/Examples/perl5/constants/Makefile @@ -0,0 +1,18 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +SRCS = +TARGET = example +INTERFACE = example.i +SWIGOPT = +all:: + $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' perl5 + +static:: + $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \ + SWIGOPT='$(SWIGOPT)' TARGET='myperl' INTERFACE='$(INTERFACE)' perl5_static + +clean:: + $(MAKE) -f $(TOP)/Makefile perl5_clean + +check: all diff --git a/trunk/Examples/perl5/constants/example.i b/trunk/Examples/perl5/constants/example.i new file mode 100644 index 000000000..4f7b1a4d7 --- /dev/null +++ b/trunk/Examples/perl5/constants/example.i @@ -0,0 +1,27 @@ +/* File : example.i */ +%module example + +/* A few preprocessor macros */ + +#define ICONST 42 +#define FCONST 2.1828 +#define CCONST 'x' +#define CCONST2 '\n' +#define SCONST "Hello World" +#define SCONST2 "\"Hello World\"" + +/* This should work just fine */ +#define EXPR ICONST + 3*(FCONST) + +/* This shouldn't do anything */ +#define EXTERN extern + +/* Neither should this (BAR isn't defined) */ +#define FOO (ICONST + BAR) + +/* The following directives also produce constants */ + +%constant int iconst = 37; +%constant double fconst = 3.14; + + diff --git a/trunk/Examples/perl5/constants/index.html b/trunk/Examples/perl5/constants/index.html new file mode 100644 index 000000000..f38338b63 --- /dev/null +++ b/trunk/Examples/perl5/constants/index.html @@ -0,0 +1,53 @@ +<html> +<head> +<title>SWIG:Examples:perl5:constants</title> +</head> + +<body bgcolor="#ffffff"> + +<tt>SWIG/Examples/perl5/constants/</tt> +<hr> + +<H2>Wrapping C Constants</H2> + +<p> +When SWIG encounters C preprocessor macros and C declarations that look like constants, +it creates Perl5 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 Perl</h2> + +Click <a href="runme.pl">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 Perl constants. +<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 Perl strings. +<li>C string literals such as "Hello World" are converted into Perl 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 Perl constants. + +<p> +<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). +</ul> + +<hr> + + +</body> +</html> diff --git a/trunk/Examples/perl5/constants/runme.pl b/trunk/Examples/perl5/constants/runme.pl new file mode 100644 index 000000000..6e8a6edf1 --- /dev/null +++ b/trunk/Examples/perl5/constants/runme.pl @@ -0,0 +1,29 @@ +# file: runme.pl + +use example; + +print "ICONST = ", $example::ICONST, " (should be 42)\n"; +print "FCONST = ", $example::FCONST, " (should be 2.1828)\n"; +print "CCONST = ", $example::CCONST, " (should be 'x')\n"; +print "CCONST2 = ", $example::CCONST2," (this should be on a new line)\n"; +print "SCONST = ", $example::SCONST, " (should be 'Hello World')\n"; +print "SCONST2 = ", $example::SCONST2, " (should be '\"Hello World\"')\n"; +print "EXPR = ", $example::EXPR, " (should be 48.5484)\n"; +print "iconst = ", $example::iconst, " (should be 37)\n"; +print "fconst = ", $example::fconst, " (should be 3.14)\n"; + + +if ($example::EXTERN) { + print "EXTERN = ", example.EXTERN, " (Arg! This shouldn't print anything)\n"; +} else { + print "EXTERN isn't defined (good)\n"; +} + +if ($example::FOO) { + print "FOO = ", example.FOO, "(Arg! This shouldn't print anything)\n"; +} else { + print "FOO isn't defined (good)\n"; +} + + + diff --git a/trunk/Examples/perl5/constants2/Makefile b/trunk/Examples/perl5/constants2/Makefile new file mode 100644 index 000000000..4ba4b2544 --- /dev/null +++ b/trunk/Examples/perl5/constants2/Makefile @@ -0,0 +1,18 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +SRCS = +TARGET = example +INTERFACE = example.i +SWIGOPT = -const +all:: + $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' perl5 + +static:: + $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \ + SWIGOPT='$(SWIGOPT)' TARGET='myperl' INTERFACE='$(INTERFACE)' perl5_static + +clean:: + $(MAKE) -f $(TOP)/Makefile perl5_clean + +check: all diff --git a/trunk/Examples/perl5/constants2/example.i b/trunk/Examples/perl5/constants2/example.i new file mode 100644 index 000000000..4f7b1a4d7 --- /dev/null +++ b/trunk/Examples/perl5/constants2/example.i @@ -0,0 +1,27 @@ +/* File : example.i */ +%module example + +/* A few preprocessor macros */ + +#define ICONST 42 +#define FCONST 2.1828 +#define CCONST 'x' +#define CCONST2 '\n' +#define SCONST "Hello World" +#define SCONST2 "\"Hello World\"" + +/* This should work just fine */ +#define EXPR ICONST + 3*(FCONST) + +/* This shouldn't do anything */ +#define EXTERN extern + +/* Neither should this (BAR isn't defined) */ +#define FOO (ICONST + BAR) + +/* The following directives also produce constants */ + +%constant int iconst = 37; +%constant double fconst = 3.14; + + diff --git a/trunk/Examples/perl5/constants2/runme.pl b/trunk/Examples/perl5/constants2/runme.pl new file mode 100644 index 000000000..d16f3b3fc --- /dev/null +++ b/trunk/Examples/perl5/constants2/runme.pl @@ -0,0 +1,16 @@ +# file: runme.pl + +use example; + +print "ICONST = ", example::ICONST, " (should be 42)\n"; +print "FCONST = ", example::FCONST, " (should be 2.1828)\n"; +print "CCONST = ", example::CCONST, " (should be 'x')\n"; +print "CCONST2 = ", example::CCONST2," (this should be on a new line)\n"; +print "SCONST = ", example::SCONST, " (should be 'Hello World')\n"; +print "SCONST2 = ", example::SCONST2, " (should be '\"Hello World\"')\n"; +print "EXPR = ", example::EXPR, " (should be 48.5484)\n"; +print "iconst = ", example::iconst, " (should be 37)\n"; +print "fconst = ", example::fconst, " (should be 3.14)\n"; + + + diff --git a/trunk/Examples/perl5/funcptr/Makefile b/trunk/Examples/perl5/funcptr/Makefile new file mode 100644 index 000000000..ce2bbb5b9 --- /dev/null +++ b/trunk/Examples/perl5/funcptr/Makefile @@ -0,0 +1,18 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +SRCS = example.c +TARGET = example +INTERFACE = example.i +SWIGOPT = +all:: + $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' perl5 + +static:: + $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \ + SWIGOPT='$(SWIGOPT)' TARGET='myperl' INTERFACE='$(INTERFACE)' perl5_static + +clean:: + $(MAKE) -f $(TOP)/Makefile perl5_clean + +check: all diff --git a/trunk/Examples/perl5/funcptr/example.c b/trunk/Examples/perl5/funcptr/example.c new file mode 100644 index 000000000..5c4a3dabf --- /dev/null +++ b/trunk/Examples/perl5/funcptr/example.c @@ -0,0 +1,19 @@ +/* File : example.c */ + +int do_op(int a, int b, int (*op)(int,int)) { + return (*op)(a,b); +} + +int add(int a, int b) { + return a+b; +} + +int sub(int a, int b) { + return a-b; +} + +int mul(int a, int b) { + return a*b; +} + +int (*funcvar)(int,int) = add; diff --git a/trunk/Examples/perl5/funcptr/example.h b/trunk/Examples/perl5/funcptr/example.h new file mode 100644 index 000000000..9936e24fc --- /dev/null +++ b/trunk/Examples/perl5/funcptr/example.h @@ -0,0 +1,9 @@ +/* file: example.h */ + +extern int do_op(int,int, int (*op)(int,int)); +extern int add(int,int); +extern int sub(int,int); +extern int mul(int,int); + +extern int (*funcvar)(int,int); + diff --git a/trunk/Examples/perl5/funcptr/example.i b/trunk/Examples/perl5/funcptr/example.i new file mode 100644 index 000000000..8b3bef678 --- /dev/null +++ b/trunk/Examples/perl5/funcptr/example.i @@ -0,0 +1,16 @@ +/* File : example.i */ +%module example +%{ +#include "example.h" +%} + +/* Wrap a function taking a pointer to a function */ +extern int do_op(int a, int b, int (*op)(int, int)); + +/* Now install a bunch of "ops" as constants */ +%constant int (*ADD)(int,int) = add; +%constant int (*SUB)(int,int) = sub; +%constant int (*MUL)(int,int) = mul; + +extern int (*funcvar)(int,int); + diff --git a/trunk/Examples/perl5/funcptr/index.html b/trunk/Examples/perl5/funcptr/index.html new file mode 100644 index 000000000..7333a39f2 --- /dev/null +++ b/trunk/Examples/perl5/funcptr/index.html @@ -0,0 +1,90 @@ +<html> +<head> +<title>SWIG:Examples:perl5:funcptr</title> +</head> + +<body bgcolor="#ffffff"> + + +<tt>SWIG/Examples/perl5/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> +$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.pl">runme.pl</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 Perl function object in as a substitute for a C +function pointer. + +<p> +<li>A perl function can be used as a C/C++ callback if you write some +clever typemaps and are very careful about how you create your extension. +This is an advanced topic not covered here. +</ul> + +<hr> +</body> +</html> + + + + diff --git a/trunk/Examples/perl5/funcptr/runme.pl b/trunk/Examples/perl5/funcptr/runme.pl new file mode 100644 index 000000000..a73b53825 --- /dev/null +++ b/trunk/Examples/perl5/funcptr/runme.pl @@ -0,0 +1,21 @@ +# file: runme.pl + +use example; + +$a = 37; +$b = 42; + +# Now call our C function with a bunch of callbacks + +print "Trying some C callback functions\n"; +print " a = $a\n"; +print " b = $b\n"; +print " ADD(a,b) = ", example::do_op($a,$b,$example::ADD),"\n"; +print " SUB(a,b) = ", example::do_op($a,$b,$example::SUB),"\n"; +print " MUL(a,b) = ", example::do_op($a,$b,$example::MUL),"\n"; + +print "Here is what the C callback function objects look like in Perl\n"; +print " ADD = $example::ADD\n"; +print " SUB = $example::SUB\n"; +print " MUL = $example::MUL\n"; + diff --git a/trunk/Examples/perl5/import/Makefile b/trunk/Examples/perl5/import/Makefile new file mode 100644 index 000000000..60dfdfcee --- /dev/null +++ b/trunk/Examples/perl5/import/Makefile @@ -0,0 +1,20 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +SWIGOPT = +LIBS = + +all:: + $(MAKE) -f $(TOP)/Makefile SWIG='$(SWIG)' SWIGOPT='$(SWIGOPT)' \ + LIBS='$(LIBS)' TARGET='baseclass' INTERFACE='base.i' perl5_cpp + $(MAKE) -f $(TOP)/Makefile SWIG='$(SWIG)' SWIGOPT='$(SWIGOPT)' \ + LIBS='$(LIBS)' TARGET='foo' INTERFACE='foo.i' perl5_cpp + $(MAKE) -f $(TOP)/Makefile SWIG='$(SWIG)' SWIGOPT='$(SWIGOPT)' \ + LIBS='$(LIBS)' TARGET='bar' INTERFACE='bar.i' perl5_cpp + $(MAKE) -f $(TOP)/Makefile SWIG='$(SWIG)' SWIGOPT='$(SWIGOPT)' \ + LIBS='$(LIBS)' TARGET='spam' INTERFACE='spam.i' perl5_cpp + + +clean:: + $(MAKE) -f $(TOP)/Makefile perl5_clean + +check: all diff --git a/trunk/Examples/perl5/import/README b/trunk/Examples/perl5/import/README new file mode 100644 index 000000000..030a33bc5 --- /dev/null +++ b/trunk/Examples/perl5/import/README @@ -0,0 +1,39 @@ +This example tests the %import directive and working with multiple modules. + +Use 'perl runme.pl' 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 uses %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). Build the runtime + project DLL first followed by the other 4 DLLs as they all have a + dependency on the runtime DLL. The Batch build option in the Build menu + is usually the easiest way to do this. Only use the Release builds not + the Debug builds. +- Run the test as described above + diff --git a/trunk/Examples/perl5/import/bar.dsp b/trunk/Examples/perl5/import/bar.dsp new file mode 100644 index 000000000..64786b8f6 --- /dev/null +++ b/trunk/Examples/perl5/import/bar.dsp @@ -0,0 +1,144 @@ +# Microsoft Developer Studio Project File - Name="bar" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=bar - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "bar.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "bar.mak" CFG="bar - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "bar - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "bar - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "bar - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "BAR_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GR /GX /ZI /Od /I "$(PERL5_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 "$(PERL5_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 "$(PERL5_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 "$(PERL5_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 PERL5_INCLUDE: %PERL5_INCLUDE%
+ echo PERL5_LIB: %PERL5_LIB%
+ echo on
+ ..\..\..\swig.exe -c++ -perl5 $(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 PERL5_INCLUDE: %PERL5_INCLUDE%
+ echo PERL5_LIB: %PERL5_LIB%
+ echo on
+ ..\..\..\swig.exe -c++ -perl5 $(InputPath)
+
+# End Custom Build
+
+!ENDIF
+
+# End Source File
+# End Target
+# End Project
diff --git a/trunk/Examples/perl5/import/bar.h b/trunk/Examples/perl5/import/bar.h new file mode 100644 index 000000000..fa4185f1f --- /dev/null +++ b/trunk/Examples/perl5/import/bar.h @@ -0,0 +1,22 @@ +#include "base.h" + +class Bar : public Base { + public: + Bar() { } + ~Bar() { } + virtual void A() { + printf("I'm Bar::A\n"); + } + void B() { + printf("I'm Bar::B\n"); + } + virtual Base *toBase() { + return static_cast<Base *>(this); + } + static Bar *fromBase(Base *b) { + return dynamic_cast<Bar *>(b); + } + +}; + + diff --git a/trunk/Examples/perl5/import/bar.i b/trunk/Examples/perl5/import/bar.i new file mode 100644 index 000000000..5816cbe17 --- /dev/null +++ b/trunk/Examples/perl5/import/bar.i @@ -0,0 +1,9 @@ +%module bar +%{ +#include "bar.h" +%} + +%import base.i +%include "bar.h" + + diff --git a/trunk/Examples/perl5/import/base.dsp b/trunk/Examples/perl5/import/base.dsp new file mode 100644 index 000000000..920891cbf --- /dev/null +++ b/trunk/Examples/perl5/import/base.dsp @@ -0,0 +1,144 @@ +# Microsoft Developer Studio Project File - Name="base" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=base - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "base.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "base.mak" CFG="base - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "base - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "base - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "base - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "BASE_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GR /GX /ZI /Od /I "$(PERL5_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 "$(PERL5_LIB)" /nologo /dll /debug /machine:I386 /out:"baseclass.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 "$(PERL5_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 "$(PERL5_LIB)" /nologo /dll /machine:I386 /out:"baseclass.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 PERL5_INCLUDE: %PERL5_INCLUDE%
+ echo PERL5_LIB: %PERL5_LIB%
+ echo on
+ ..\..\..\swig.exe -c++ -perl5 $(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 PERL5_INCLUDE: %PERL5_INCLUDE%
+ echo PERL5_LIB: %PERL5_LIB%
+ echo on
+ ..\..\..\swig.exe -c++ -perl5 $(InputPath)
+
+# End Custom Build
+
+!ENDIF
+
+# End Source File
+# End Target
+# End Project
diff --git a/trunk/Examples/perl5/import/base.h b/trunk/Examples/perl5/import/base.h new file mode 100644 index 000000000..5a266f68c --- /dev/null +++ b/trunk/Examples/perl5/import/base.h @@ -0,0 +1,18 @@ +#include <stdio.h> + +class Base { + public: + Base() { }; + virtual ~Base() { }; + virtual void A() { + printf("I'm Base::A\n"); + } + void B() { + printf("I'm Base::B\n"); + } + virtual Base *toBase() { + return static_cast<Base *>(this); + } +}; + + diff --git a/trunk/Examples/perl5/import/base.i b/trunk/Examples/perl5/import/base.i new file mode 100644 index 000000000..dc99383a7 --- /dev/null +++ b/trunk/Examples/perl5/import/base.i @@ -0,0 +1,6 @@ +%module baseclass +%{ +#include "base.h" +%} + +%include base.h diff --git a/trunk/Examples/perl5/import/example.dsw b/trunk/Examples/perl5/import/example.dsw new file mode 100644 index 000000000..d395d464b --- /dev/null +++ b/trunk/Examples/perl5/import/example.dsw @@ -0,0 +1,65 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "bar"=.\bar.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "base"=.\base.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "foo"=.\foo.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "spam"=.\spam.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/trunk/Examples/perl5/import/foo.dsp b/trunk/Examples/perl5/import/foo.dsp new file mode 100644 index 000000000..d519a5316 --- /dev/null +++ b/trunk/Examples/perl5/import/foo.dsp @@ -0,0 +1,144 @@ +# Microsoft Developer Studio Project File - Name="foo" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=foo - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "foo.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "foo.mak" CFG="foo - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "foo - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "foo - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "foo - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FOO_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GR /GX /ZI /Od /I "$(PERL5_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 "$(PERL5_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 "$(PERL5_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 "$(PERL5_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 PERL5_INCLUDE: %PERL5_INCLUDE%
+ echo PERL5_LIB: %PERL5_LIB%
+ echo on
+ ..\..\..\swig.exe -c++ -perl5 $(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 PERL5_INCLUDE: %PERL5_INCLUDE%
+ echo PERL5_LIB: %PERL5_LIB%
+ echo on
+ ..\..\..\swig.exe -c++ -perl5 $(InputPath)
+
+# End Custom Build
+
+!ENDIF
+
+# End Source File
+# End Target
+# End Project
diff --git a/trunk/Examples/perl5/import/foo.h b/trunk/Examples/perl5/import/foo.h new file mode 100644 index 000000000..dd5184031 --- /dev/null +++ b/trunk/Examples/perl5/import/foo.h @@ -0,0 +1,21 @@ +#include "base.h" + +class Foo : public Base { + public: + Foo() { } + ~Foo() { } + virtual void A() { + printf("I'm Foo::A\n"); + } + void B() { + printf("I'm Foo::B\n"); + } + virtual Base *toBase() { + return static_cast<Base *>(this); + } + static Foo *fromBase(Base *b) { + return dynamic_cast<Foo *>(b); + } +}; + + diff --git a/trunk/Examples/perl5/import/foo.i b/trunk/Examples/perl5/import/foo.i new file mode 100644 index 000000000..27feb2e6a --- /dev/null +++ b/trunk/Examples/perl5/import/foo.i @@ -0,0 +1,8 @@ +%module foo +%{ +#include "foo.h" +%} + +%import base.i +%include "foo.h" + diff --git a/trunk/Examples/perl5/import/runme.pl b/trunk/Examples/perl5/import/runme.pl new file mode 100644 index 000000000..1db080751 --- /dev/null +++ b/trunk/Examples/perl5/import/runme.pl @@ -0,0 +1,116 @@ +# file: runme.pl +# Test various properties of classes defined in separate modules + +print "Testing the %import directive\n"; +use baseclass; +use foo; +use bar; +use spam; + +# Create some objects + +print "Creating some objects\n"; + +$a = new baseclass::Base(); +$b = new foo::Foo(); +$c = new bar::Bar(); +$d = new spam::Spam(); + +# Try calling some methods +print "Testing some methods\n"; +print "Should see 'Base::A' ---> "; +$a->A(); +print "Should see 'Base::B' ---> "; +$a->B(); + +print "Should see 'Foo::A' ---> "; +$b->A(); +print "Should see 'Foo::B' ---> "; +$b->B(); + +print "Should see 'Bar::A' ---> "; +$c->A(); +print "Should see 'Bar::B' ---> "; +$c->B(); + +print "Should see 'Spam::A' ---> "; +$d->A(); +print "Should see 'Spam::B' ---> "; +$d->B(); + +# Try some casts + +print "\nTesting some casts\n"; + +$x = $a->toBase(); +print "Should see 'Base::A' ---> "; +$x->A(); +print "Should see 'Base::B' ---> "; +$x->B(); + +$x = $b->toBase(); +print "Should see 'Foo::A' ---> "; +$x->A(); + +print "Should see 'Base::B' ---> "; +$x->B(); + +$x = $c->toBase(); +print "Should see 'Bar::A' ---> "; +$x->A(); + +print "Should see 'Base::B' ---> "; +$x->B(); + +$x = $d->toBase(); +print "Should see 'Spam::A' ---> "; +$x->A(); + +print "Should see 'Base::B' ---> "; +$x->B(); + +$x = $d->toBar(); +print "Should see 'Bar::B' ---> "; +$x->B(); + +print "\nTesting some dynamic casts\n"; +$x = $d->toBase(); + +print " Spam -> Base -> Foo : "; +$y = foo::Foo::fromBase($x); +if ($y) { + print "bad swig\n"; +} else { + print "good swig\n"; +} + +print " Spam -> Base -> Bar : "; +$y = bar::Bar::fromBase($x); +if ($y) { + print "good swig\n"; +} else { + print "bad swig\n"; +} + +print " Spam -> Base -> Spam : "; +$y = spam::Spam::fromBase($x); +if ($y) { + print "good swig\n"; +} else { + print "bad swig\n"; +} + +print " Foo -> Spam : "; +#print $b; +$y = spam::Spam::fromBase($b); +print $y; +if ($y) { + print "bad swig\n"; +} else { + print "good swig\n"; +} + + + + + diff --git a/trunk/Examples/perl5/import/spam.dsp b/trunk/Examples/perl5/import/spam.dsp new file mode 100644 index 000000000..e5c8046eb --- /dev/null +++ b/trunk/Examples/perl5/import/spam.dsp @@ -0,0 +1,144 @@ +# Microsoft Developer Studio Project File - Name="spam" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=spam - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "spam.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!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 "$(PERL5_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 "$(PERL5_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 "$(PERL5_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 "$(PERL5_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 PERL5_INCLUDE: %PERL5_INCLUDE%
+ echo PERL5_LIB: %PERL5_LIB%
+ echo on
+ ..\..\..\swig.exe -c++ -perl5 $(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 PERL5_INCLUDE: %PERL5_INCLUDE%
+ echo PERL5_LIB: %PERL5_LIB%
+ echo on
+ ..\..\..\swig.exe -c++ -perl5 $(InputPath)
+
+# End Custom Build
+
+!ENDIF
+
+# End Source File
+# End Target
+# End Project
diff --git a/trunk/Examples/perl5/import/spam.h b/trunk/Examples/perl5/import/spam.h new file mode 100644 index 000000000..b4e7a2646 --- /dev/null +++ b/trunk/Examples/perl5/import/spam.h @@ -0,0 +1,24 @@ +#include "bar.h" + +class Spam : public Bar { + public: + Spam() { } + ~Spam() { } + virtual void A() { + printf("I'm Spam::A\n"); + } + void B() { + printf("I'm Spam::B\n"); + } + virtual Base *toBase() { + return static_cast<Base *>(this); + } + virtual Bar *toBar() { + return static_cast<Bar *>(this); + } + static Spam *fromBase(Base *b) { + return dynamic_cast<Spam *>(b); + } +}; + + diff --git a/trunk/Examples/perl5/import/spam.i b/trunk/Examples/perl5/import/spam.i new file mode 100644 index 000000000..d3d9121db --- /dev/null +++ b/trunk/Examples/perl5/import/spam.i @@ -0,0 +1,9 @@ +%module spam +%{ +#include "spam.h" +%} + +%import bar.i +%include "spam.h" + + diff --git a/trunk/Examples/perl5/index.html b/trunk/Examples/perl5/index.html new file mode 100644 index 000000000..5648c587d --- /dev/null +++ b/trunk/Examples/perl5/index.html @@ -0,0 +1,80 @@ +<html> +<head> +<title>SWIG:Examples:perl5</title> +</head> + +<body bgcolor="#ffffff"> +<H1>SWIG Perl Examples</H1> + +<p> +The following examples illustrate the use of SWIG with Perl. + +<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>. This example shows how to access C global variables from Perl. +<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 to 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 Perl extension, SWIG is run with the following options: + +<blockquote> +<pre> +% swig -perl5 interface.i +</pre> +</blockquote> + +<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> +% swig -perl5 interface.i +% gcc -fpic -c -Dbool=char -I/usr/lib/perl5/5.00503/i386-linux/CORE interface_wrap.c +% gcc -shared interface_wrap.o $(OBJS) -o interface.so +% perl +use interface; +... +</pre> +</blockquote> + +<li>The politically "correct" way to compile a Perl extension module is to use MakeMaker +and related tools (especially if you are considering third-party distribution). Consult +a book such as Advanced Perl Programming for details. + +</ul> + +<h2>Compatibility</h2> + +The examples have been extensively tested on the following platforms: + +<p> +<ul> +<li>Linux +<li>Solaris +</ul> + +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> + +<p> +Due to wide variations in the Perl C API and differences between versions such as the ActivePerl release for Windows, +the code generated by SWIG is extremely messy. We have made every attempt to maintain compatibility with +many Perl releases going as far back as 5.003 and as recent as 5.6. However, 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>. +Better yet, send us a patch. + +</body> +</html> + + diff --git a/trunk/Examples/perl5/inline/Makefile b/trunk/Examples/perl5/inline/Makefile new file mode 100644 index 000000000..4ac085ec3 --- /dev/null +++ b/trunk/Examples/perl5/inline/Makefile @@ -0,0 +1,7 @@ +all: + +run: + perl runme.pl + +clean: + rm -fr _Inline *~ diff --git a/trunk/Examples/perl5/inline/README b/trunk/Examples/perl5/inline/README new file mode 100644 index 000000000..33be94973 --- /dev/null +++ b/trunk/Examples/perl5/inline/README @@ -0,0 +1,2 @@ +This example requires the Inline::SWIG package. + diff --git a/trunk/Examples/perl5/inline/runme.pl b/trunk/Examples/perl5/inline/runme.pl new file mode 100644 index 000000000..8b0f0898f --- /dev/null +++ b/trunk/Examples/perl5/inline/runme.pl @@ -0,0 +1,34 @@ +use Inline SWIG => <<"END_CODE", SWIG_ARGS => '-c++ -proxy', CC => 'g++', LD=>'g++'; + class Foo { + public: + int meaning() { return 42; }; + }; +END_CODE + +my $o = new Foo(); +print $o->meaning(),"\n"; + +use Inline SWIG => ' ', SWIG_INTERFACE => <<"END_CODE", SWIG_ARGS => '-c++', CC => "g++", LD => "g++"; +%include std_string.i +%inline { + template <class Type> + class Bar { + Type _val; + public: + Bar(Type v) : _val(v) {} + Type meaning() { return _val; } + }; +} +%template(Bar_i) Bar<int>; +%template(Bar_d) Bar<double>; +%template(Bar_s) Bar<std::string>; +END_CODE + +my $o = new Bar_i(1); +print $o->meaning(),"\n"; + +my $o = new Bar_d(2); +print $o->meaning(),"\n"; + +my $o = new Bar_s("hello"); +print $o->meaning(),"\n"; diff --git a/trunk/Examples/perl5/java/Example.java b/trunk/Examples/perl5/java/Example.java new file mode 100644 index 000000000..91ddb1ac5 --- /dev/null +++ b/trunk/Examples/perl5/java/Example.java @@ -0,0 +1,29 @@ +public class Example { + public int mPublicInt; + + public Example() { + mPublicInt = 0; + } + + public Example(int IntVal) { + mPublicInt = IntVal; + } + + + public int Add(int a, int b) { + return (a+b); + } + + public float Add(float a, float b) { + return (a+b); + } + + public String Add(String a, String b) { + return (a+b); + } + + public Example Add(Example a, Example b) { + return new Example(a.mPublicInt + b.mPublicInt); + } +} + diff --git a/trunk/Examples/perl5/java/Makefile b/trunk/Examples/perl5/java/Makefile new file mode 100644 index 000000000..882eba70f --- /dev/null +++ b/trunk/Examples/perl5/java/Makefile @@ -0,0 +1,26 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +CXXSRCS = +TARGET = example +INTERFACE = example.i +LIBS = -lm + +all:: Example.class + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' CXX="gcj" \ + CXXSHARED="gcj -fpic -shared Example.class" PERL5_CCFLAGS='' PERL5_EXP='' LIBS="-lstdc++" perl5_cpp + + +clean:: + $(MAKE) -f $(TOP)/Makefile perl5_clean + rm -f *.class Example.h + +check: all + +run: + perl runme.pl + +Example.class: Example.java + gcj -fPIC -C -c -g Example.java + gcjh Example + diff --git a/trunk/Examples/perl5/java/example.i b/trunk/Examples/perl5/java/example.i new file mode 100644 index 000000000..a82abb267 --- /dev/null +++ b/trunk/Examples/perl5/java/example.i @@ -0,0 +1,10 @@ +%module example + +%include <cni.i> + +%{ +#include "Example.h" +%} + + +%include Example.h diff --git a/trunk/Examples/perl5/java/runme.pl b/trunk/Examples/perl5/java/runme.pl new file mode 100644 index 000000000..56ad6e408 --- /dev/null +++ b/trunk/Examples/perl5/java/runme.pl @@ -0,0 +1,29 @@ +use example; + +example::JvCreateJavaVM(undef); +example::JvAttachCurrentThread(undef, undef); + +$e1 = new example::Example(1); +print $e1->{mPublicInt},"\n"; + +$e2 = new example::Example(2); +print $e2->{mPublicInt},"\n"; + +$i = $e1->Add(1,2); +print $i,"\n"; + +$d = $e2->Add(1.0,2.0); +print $d,"\n"; + +$d = $e2->Add("1","2"); +print $d,"\n"; + +$e3 = $e1->Add($e1,$e2); +print $e3->{mPublicInt},"\n"; + + +$s = $e2->Add("a","b"); +print $s,"\n"; + + +example::JvDetachCurrentThread() diff --git a/trunk/Examples/perl5/multimap/Makefile b/trunk/Examples/perl5/multimap/Makefile new file mode 100644 index 000000000..ce2bbb5b9 --- /dev/null +++ b/trunk/Examples/perl5/multimap/Makefile @@ -0,0 +1,18 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +SRCS = example.c +TARGET = example +INTERFACE = example.i +SWIGOPT = +all:: + $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' perl5 + +static:: + $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \ + SWIGOPT='$(SWIGOPT)' TARGET='myperl' INTERFACE='$(INTERFACE)' perl5_static + +clean:: + $(MAKE) -f $(TOP)/Makefile perl5_clean + +check: all diff --git a/trunk/Examples/perl5/multimap/example.c b/trunk/Examples/perl5/multimap/example.c new file mode 100644 index 000000000..b8360fa8a --- /dev/null +++ b/trunk/Examples/perl5/multimap/example.c @@ -0,0 +1,53 @@ +/* File : example.c */ +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> + +/* Compute the greatest common divisor of positive integers */ +int gcd(int x, int y) { + int g; + g = y; + while (x > 0) { + g = x; + x = y % x; + y = g; + } + return g; +} + +int gcdmain(int argc, char *argv[]) { + int x,y; + if (argc != 3) { + printf("usage: gcd x y\n"); + return -1; + } + x = atoi(argv[1]); + y = atoi(argv[2]); + printf("gcd(%d,%d) = %d\n", x,y,gcd(x,y)); + return 0; +} + +int count(char *bytes, int len, char c) { + int i; + int count = 0; + for (i = 0; i < len; i++) { + if (bytes[i] == c) count++; + } + return count; +} + +void capitalize(char *str, int len) { + int i; + for (i = 0; i < len; i++) { + str[i] = (char)toupper(str[i]); + } +} + +void circle(double x, double y) { + double a = x*x + y*y; + if (a > 1.0) { + printf("Bad points %g, %g\n", x,y); + } else { + printf("Good points %g, %g\n", x,y); + } +} diff --git a/trunk/Examples/perl5/multimap/example.dsp b/trunk/Examples/perl5/multimap/example.dsp new file mode 100644 index 000000000..be8a0070e --- /dev/null +++ b/trunk/Examples/perl5/multimap/example.dsp @@ -0,0 +1,148 @@ +# Microsoft Developer Studio Project File - Name="example" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=example - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "example.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "example.mak" CFG="example - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "example - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "example - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "example - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "$(PERL5_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 "$(PERL5_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 "$(PERL5_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 "$(PERL5_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 PERL5_INCLUDE: %PERL5_INCLUDE%
+ echo PERL5_LIB: %PERL5_LIB%
+ echo on
+ ..\..\..\swig.exe -perl5 $(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 PERL5_INCLUDE: %PERL5_INCLUDE%
+ echo PERL5_LIB: %PERL5_LIB%
+ echo on
+ ..\..\..\swig.exe -perl5 $(InputPath)
+
+# End Custom Build
+
+!ENDIF
+
+# End Source File
+# End Target
+# End Project
diff --git a/trunk/Examples/perl5/multimap/example.i b/trunk/Examples/perl5/multimap/example.i new file mode 100644 index 000000000..64eb6a7f7 --- /dev/null +++ b/trunk/Examples/perl5/multimap/example.i @@ -0,0 +1,93 @@ +/* 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 +%include typemaps.i + +extern int gcd(int x, int y); + +%typemap(arginit) (int argc, char *argv[]) "$2 = 0;"; + +%typemap(in) (int argc, char *argv[]) { + AV *tempav; + SV **tv; + I32 len; + int i; + if (!SvROK($input)) { + SWIG_exception(SWIG_ValueError,"$input is not an array."); + } + if (SvTYPE(SvRV($input)) != SVt_PVAV) { + SWIG_exception(SWIG_ValueError,"$input is not an array."); + } + tempav = (AV*)SvRV($input); + len = av_len(tempav); + $1 = (int) len+1; + $2 = (char **) malloc(($1+1)*sizeof(char *)); + for (i = 0; i < $1; i++) { + tv = av_fetch(tempav, i, 0); + $2[i] = (char *) SvPV(*tv,PL_na); + } + $2[i] = 0; +} + +%typemap(freearg) (int argc, char *argv[]) { + free($2); +} + +extern int gcdmain(int argc, char *argv[]); + +%typemap(in) (char *bytes, int len) { + STRLEN temp; + $1 = (char *) SvPV($input, temp); + $2 = (int) temp; +} + +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) { + STRLEN templen; + char *temp; + temp = (char *) SvPV($input,templen); + $2 = (int) templen; + $1 = (char *) malloc($2+1); + memmove($1,temp,$2); +} + +/* Return the mutated string as a new object. */ + +%typemap(argout) (char *str, int len) { + if (argvi >= items) { + EXTEND(sp,1); + } + $result = sv_newmortal(); + sv_setpvn((SV*)ST(argvi++),$1,$2); + 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"); + } +} + +extern void circle(double cx, double cy); + + diff --git a/trunk/Examples/perl5/multimap/runme.pl b/trunk/Examples/perl5/multimap/runme.pl new file mode 100644 index 000000000..416055f5b --- /dev/null +++ b/trunk/Examples/perl5/multimap/runme.pl @@ -0,0 +1,28 @@ +# file: runme.pl + +use example; + +# Call our gcd() function + +$x = 42; +$y = 105; +$g = example::gcd($x,$y); +print "The gcd of $x and $y is $g\n"; + +# Call the gcdmain() function +@a = ("gcdmain","42","105"); +example::gcdmain(\@a); + +# Call the count function +print example::count("Hello World", "l"),"\n"; + +# Call the capitize function + +print example::capitalize("hello world"),"\n"; + + + + + + + diff --git a/trunk/Examples/perl5/multiple_inheritance/Makefile b/trunk/Examples/perl5/multiple_inheritance/Makefile new file mode 100644 index 000000000..fcca38473 --- /dev/null +++ b/trunk/Examples/perl5/multiple_inheritance/Makefile @@ -0,0 +1,19 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +CXXSRCS = +TARGET = example +INTERFACE = example.i +LIBS = + +all:: + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' perl5_cpp + +static:: + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + TARGET='myperl' INTERFACE='$(INTERFACE)' perl5_cpp_static + +clean:: + $(MAKE) -f $(TOP)/Makefile perl5_clean + +check: all diff --git a/trunk/Examples/perl5/multiple_inheritance/example.h b/trunk/Examples/perl5/multiple_inheritance/example.h new file mode 100644 index 000000000..a8f544898 --- /dev/null +++ b/trunk/Examples/perl5/multiple_inheritance/example.h @@ -0,0 +1,31 @@ +/* File : example.h */ + +#include <iostream> + +using namespace std; + +class Bar +{ + public: + virtual void bar () { + cout << "bar" << endl; + } + virtual ~Bar() {} +}; + +class Foo +{ + public: + virtual void foo () { + cout << "foo" << endl; + } + virtual ~Foo() {} +}; + +class Foo_Bar : public Foo, public Bar +{ + public: + virtual void fooBar () { + cout << "foobar" << endl; + } +}; diff --git a/trunk/Examples/perl5/multiple_inheritance/example.i b/trunk/Examples/perl5/multiple_inheritance/example.i new file mode 100644 index 000000000..fbdf7249f --- /dev/null +++ b/trunk/Examples/perl5/multiple_inheritance/example.i @@ -0,0 +1,9 @@ +/* File : example.i */ +%module example + +%{ +#include "example.h" +%} + +/* Let's just grab the original header file here */ +%include "example.h" diff --git a/trunk/Examples/perl5/multiple_inheritance/runme.pl b/trunk/Examples/perl5/multiple_inheritance/runme.pl new file mode 100644 index 000000000..a1130c66e --- /dev/null +++ b/trunk/Examples/perl5/multiple_inheritance/runme.pl @@ -0,0 +1,16 @@ +# file: runme.pl + +# This file test multiple inheritance + +use example; + +$foo_Bar = new example::Foo_Bar(); + +print "must be foo: "; +$foo_Bar->foo(); + +print "must be bar: "; +$foo_Bar->bar(); + +print "must be foobar: "; +$foo_Bar->fooBar(); diff --git a/trunk/Examples/perl5/pointer/Makefile b/trunk/Examples/perl5/pointer/Makefile new file mode 100644 index 000000000..ce2bbb5b9 --- /dev/null +++ b/trunk/Examples/perl5/pointer/Makefile @@ -0,0 +1,18 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +SRCS = example.c +TARGET = example +INTERFACE = example.i +SWIGOPT = +all:: + $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' perl5 + +static:: + $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \ + SWIGOPT='$(SWIGOPT)' TARGET='myperl' INTERFACE='$(INTERFACE)' perl5_static + +clean:: + $(MAKE) -f $(TOP)/Makefile perl5_clean + +check: all diff --git a/trunk/Examples/perl5/pointer/example.c b/trunk/Examples/perl5/pointer/example.c new file mode 100644 index 000000000..8762329fe --- /dev/null +++ b/trunk/Examples/perl5/pointer/example.c @@ -0,0 +1,16 @@ +/* File : example.c */ + +void add(int *x, int *y, int *result) { + *result = *x + *y; +} + +void subtract(int *x, int *y, int *result) { + *result = *x - *y; +} + +int divide(int n, int d, int *r) { + int q; + q = n/d; + *r = n - q*d; + return q; +} diff --git a/trunk/Examples/perl5/pointer/example.i b/trunk/Examples/perl5/pointer/example.i new file mode 100644 index 000000000..38c67d7d2 --- /dev/null +++ b/trunk/Examples/perl5/pointer/example.i @@ -0,0 +1,30 @@ +/* File : example.i */ +%module example + +%{ +extern void add(int *, int *, int *); +extern void subtract(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 subtract(int *INPUT, int *INPUT, int *OUTPUT); + +/* Next we'll use typemaps and the %apply directive */ + +%apply int *OUTPUT { int *r }; +extern int divide(int n, int d, int *r); + + + + diff --git a/trunk/Examples/perl5/pointer/index.html b/trunk/Examples/perl5/pointer/index.html new file mode 100644 index 000000000..94467bc36 --- /dev/null +++ b/trunk/Examples/perl5/pointer/index.html @@ -0,0 +1,171 @@ +<html> +<head> +<title>SWIG:Examples:perl5:pointer</title> +</head> + +<body bgcolor="#ffffff"> + +<tt>SWIG/Examples/perl5/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> +$a = new_int(37); +$b = new_int(42); +$c = new_int(0): +add($a,$b,$c); +$r = get_int($c); +print "Result = $r\n"; +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> +$a = ptrcreate("int",37); +$b = ptrcreate("int",42); +$c = ptrcreate("int"); +add($a,$b,$c); +$r = ptrvalue($c); +print "Result = $r\n"; +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> +$r = add(37,42); +print "Result = $r\n"; +</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 subtract(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.pl">runme.pl</a> (Perl Script) +</ul> + +<h2>Notes</h2> + +<ul> +<li>Since pointers are used for so many different things (arrays, output values, +etc...) the complexity of pointer handling can be as complicated as you want to +make it. + +<p> +<li>More documentation on the typemaps.i and pointer.i library files can be +found in the SWIG user manual. The files also contain documentation. + +<p> +<li>The pointer.i library is designed primarily for convenience. If you +are concerned about performance, you probably want to use a different +approach. + +</ul> + +<hr> +</body> +</html> diff --git a/trunk/Examples/perl5/pointer/runme.pl b/trunk/Examples/perl5/pointer/runme.pl new file mode 100644 index 000000000..4f0a89e82 --- /dev/null +++ b/trunk/Examples/perl5/pointer/runme.pl @@ -0,0 +1,44 @@ +# file: runme.pl + +use example; + +# First create some objects using the pointer library. +print "Testing the pointer library\n"; +$a = example::new_intp(); +$b = example::new_intp(); +$c = example::new_intp(); +example::intp_assign($a,37); +example::intp_assign($b,42); + +print " a = $a\n"; +print " b = $b\n"; +print " c = $c\n"; + +# Call the add() function with some pointers +example::add($a,$b,$c); + +# Now get the result +$r = example::intp_value($c); +print " 37 + 42 = $r\n"; + +# Clean up the pointers +example::delete_intp($a); +example::delete_intp($b); +example::delete_intp($c); + +# Now try the typemap library +# This should be much easier. Now how it is no longer +# necessary to manufacture pointers. + +print "Trying the typemap library\n"; +$r = example::subtract(37,42); +print " 37 - 42 = $r\n"; + +# Now try the version with multiple return values + +print "Testing multiple return values\n"; +($q,$r) = example::divide(42,37); +print " 42/37 = $q remainder $r\n"; + + + diff --git a/trunk/Examples/perl5/reference/Makefile b/trunk/Examples/perl5/reference/Makefile new file mode 100644 index 000000000..4a804258b --- /dev/null +++ b/trunk/Examples/perl5/reference/Makefile @@ -0,0 +1,20 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +CXXSRCS = example.cxx +TARGET = example +INTERFACE = example.i +LIBS = -lm +SWIGOPT = -noproxy + +all:: + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' SWIGOPT='$(SWIGOPT)' perl5_cpp + +static:: + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + TARGET='myperl' INTERFACE='$(INTERFACE)' SWIGOPT='$(SWIGOPT)' perl5_cpp_static + +clean:: + $(MAKE) -f $(TOP)/Makefile perl5_clean + +check: all diff --git a/trunk/Examples/perl5/reference/example.cxx b/trunk/Examples/perl5/reference/example.cxx new file mode 100644 index 000000000..8a513bf49 --- /dev/null +++ b/trunk/Examples/perl5/reference/example.cxx @@ -0,0 +1,46 @@ +/* File : example.cxx */ + +/* Deal with Microsoft's attempt at deprecating C standard runtime functions */ +#if !defined(SWIG_NO_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) +# define _CRT_SECURE_NO_DEPRECATE +#endif + +#include "example.h" +#include <stdio.h> +#include <stdlib.h> + +Vector operator+(const Vector &a, const Vector &b) { + Vector r; + r.x = a.x + b.x; + r.y = a.y + b.y; + r.z = a.z + b.z; + return r; +} + +char *Vector::print() { + static char temp[512]; + sprintf(temp,"Vector %p (%g,%g,%g)", this, x,y,z); + return temp; +} + +VectorArray::VectorArray(int size) { + items = new Vector[size]; + maxsize = size; +} + +VectorArray::~VectorArray() { + delete [] items; +} + +Vector &VectorArray::operator[](int index) { + if ((index < 0) || (index >= maxsize)) { + printf("Panic! Array index out of bounds.\n"); + exit(1); + } + return items[index]; +} + +int VectorArray::size() { + return maxsize; +} + diff --git a/trunk/Examples/perl5/reference/example.h b/trunk/Examples/perl5/reference/example.h new file mode 100644 index 000000000..4915adb1b --- /dev/null +++ b/trunk/Examples/perl5/reference/example.h @@ -0,0 +1,26 @@ +/* File : example.h */ + +class Vector { +private: + double x,y,z; +public: + Vector() : x(0), y(0), z(0) { }; + Vector(double x, double y, double z) : x(x), y(y), z(z) { }; + friend Vector operator+(const Vector &a, const Vector &b); + char *print(); +}; + +class VectorArray { +private: + Vector *items; + int maxsize; +public: + VectorArray(int maxsize); + ~VectorArray(); + Vector &operator[](int); + int size(); +}; + + + + diff --git a/trunk/Examples/perl5/reference/example.i b/trunk/Examples/perl5/reference/example.i new file mode 100644 index 000000000..6daa3b1f4 --- /dev/null +++ b/trunk/Examples/perl5/reference/example.i @@ -0,0 +1,46 @@ +/* File : example.i */ + +/* This file has a few "typical" uses of C++ references. */ + +%module example + +%{ +#include "example.h" +%} + +class Vector { +public: + Vector(double x, double y, double z); + ~Vector(); + char *print(); +}; + +/* This helper function calls an overloaded operator */ +%inline %{ +Vector addv(Vector &a, Vector &b) { + return a+b; +} +%} + +/* Wrapper around an array of vectors class */ + +class VectorArray { +public: + VectorArray(int maxsize); + ~VectorArray(); + int size(); + + /* This wrapper provides an alternative to the [] operator */ + %extend { + Vector &get(int index) { + return (*$self)[index]; + } + void set(int index, Vector &a) { + (*$self)[index] = a; + } + } +}; + + + + diff --git a/trunk/Examples/perl5/reference/index.html b/trunk/Examples/perl5/reference/index.html new file mode 100644 index 000000000..70b4f3d34 --- /dev/null +++ b/trunk/Examples/perl5/reference/index.html @@ -0,0 +1,146 @@ +<html> +<head> +<title>SWIG:Examples:perl5:reference</title> +</head> + +<body bgcolor="#ffffff"> + + +<tt>SWIG/Examples/perl5/reference/</tt> +<hr> + +<H2>C++ Reference Handling</H2> + +<p> +This example tests SWIG's handling of C++ references. Since C++ +references are closely related to pointers (as both refer to a +location in memory), SWIG simply collapses all references into +pointers when creating wrappers. + +<h2>Some examples</h2> + +References are most commonly used as function parameter. For example, +you might have an operator like this: + +<blockquote> +<pre> +Vector operator+(const Vector &a, const Vector &b) { + Vector result; + result.x = a.x + b.x; + result.y = a.y + b.y; + result.z = a.z + b.z; + return result; +} +</pre> +</blockquote> + +or a function: + +<blockquote> +<pre> +Vector addv(const Vector &a, const Vector &b) { + Vector result; + result.x = a.x + b.x; + result.y = a.y + b.y; + result.z = a.z + b.z; + return result; +} +</pre> +</blockquote> + +In these cases, SWIG transforms everything into a pointer and creates a wrapper +that looks like this: + +<blockquote> +<pre> +Vector wrap_addv(Vector *a, Vector *b) { + return addv(*a,*b); +} +</pre> +</blockquote> + +Occasionally, a reference is used as a return value of a function +when the return result is to be used as an lvalue in an expression. +The prototypical example is an operator like this: + +<blockquote> +<pre> +Vector &operator[](int index); +</pre> +</blockquote> + +or a method: + +<blockquote> +<pre> +Vector &get(int index); +</pre> +</blockquote> + +For functions returning references, a wrapper like this is created: + +<blockquote> +<pre> +Vector *wrap_Object_get(Object *self, int index) { + Vector &result = self->get(index); + return &result; +} +</pre> +</blockquote> + +The following <a href="example.h">header file</a> contains some class +definitions with some operators and use of references. + +<h2>SWIG Interface</h2> + +SWIG does NOT support overloaded operators so it can not directly build +an interface to the classes in the above file. However, a number of workarounds +can be made. For example, an overloaded operator can be stuck behind a function +call such as the <tt>addv()</tt> function above. Array access can be handled +with a pair of set/get functions like this: + +<blockquote> +<pre> +class VectorArray { +public: + ... + %addmethods { + Vector &get(int index) { + return (*self)[index]; + } + void set(int index, Vector &a) { + (*self)[index] = a; + } + } + ... +} +</pre> +</blockquote> + +Click <a href="example.i">here</a> to see a SWIG interface file with these additions. + +<h2>Sample Perl script</h2> + +Click <a href="runme.pl">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, it doesn't much matter to Perl. + +<p> +<li>When a program returns a reference, a pointer is returned. +Unlike return by value, memory is not allocated to hold the +return result. + +<p> +<li>SWIG has particular trouble handling various combinations of references +and pointers. This is side effect of an old parsing scheme and +type representation that will be replaced in future versions. + +</ul> + +<hr> +</body> +</html> diff --git a/trunk/Examples/perl5/reference/runme.pl b/trunk/Examples/perl5/reference/runme.pl new file mode 100644 index 000000000..41dc0b873 --- /dev/null +++ b/trunk/Examples/perl5/reference/runme.pl @@ -0,0 +1,74 @@ +# file: runme.pl + +# This file illustrates the manipulation of C++ references in Perl. +# This uses the low-level interface. Proxy classes work differently. + +use example; + +# ----- Object creation ----- + +print "Creating some objects:\n"; +$a = example::new_Vector(3,4,5); +$b = example::new_Vector(10,11,12); + +print " Created",example::Vector_print($a),"\n"; +print " Created",example::Vector_print($b),"\n"; + +# ----- Call an overloaded operator ----- + +# This calls the wrapper we placed around +# +# operator+(const Vector &a, const Vector &) +# +# It returns a new allocated object. + +print "Adding a+b\n"; +$c = example::addv($a,$b); +print " a+b =", example::Vector_print($c),"\n"; + +# Note: Unless we free the result, a memory leak will occur +example::delete_Vector($c); + +# ----- Create a vector array ----- + +# Note: Using the high-level interface here +print "Creating an array of vectors\n"; +$va = example::new_VectorArray(10); +print " va = $va\n"; + +# ----- Set some values in the array ----- + +# These operators copy the value of $a and $b to the vector array +example::VectorArray_set($va,0,$a); +example::VectorArray_set($va,1,$b); + +# This will work, but it will cause a memory leak! + +example::VectorArray_set($va,2,example::addv($a,$b)); + +# The non-leaky way to do it + +$c = example::addv($a,$b); +example::VectorArray_set($va,3,$c); +example::delete_Vector($c); + +# Get some values from the array + +print "Getting some array values\n"; +for ($i = 0; $i < 5; $i++) { + print " va($i) = ", example::Vector_print(example::VectorArray_get($va,$i)), "\n"; +} + +# Watch under resource meter to check on this +print "Making sure we don't leak memory.\n"; +for ($i = 0; $i < 1000000; $i++) { + $c = example::VectorArray_get($va,$i % 10); +} + +# ----- Clean up ----- +print "Cleaning up\n"; + +example::delete_VectorArray($va); +example::delete_Vector($a); +example::delete_Vector($b); + diff --git a/trunk/Examples/perl5/simple/Makefile b/trunk/Examples/perl5/simple/Makefile new file mode 100644 index 000000000..ce2bbb5b9 --- /dev/null +++ b/trunk/Examples/perl5/simple/Makefile @@ -0,0 +1,18 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +SRCS = example.c +TARGET = example +INTERFACE = example.i +SWIGOPT = +all:: + $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' perl5 + +static:: + $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \ + SWIGOPT='$(SWIGOPT)' TARGET='myperl' INTERFACE='$(INTERFACE)' perl5_static + +clean:: + $(MAKE) -f $(TOP)/Makefile perl5_clean + +check: all diff --git a/trunk/Examples/perl5/simple/example.c b/trunk/Examples/perl5/simple/example.c new file mode 100644 index 000000000..1c2af789c --- /dev/null +++ b/trunk/Examples/perl5/simple/example.c @@ -0,0 +1,18 @@ +/* File : example.c */ + +/* A global variable */ +double Foo = 3.0; + +/* Compute the greatest common divisor of positive integers */ +int gcd(int x, int y) { + int g; + g = y; + while (x > 0) { + g = x; + x = y % x; + y = g; + } + return g; +} + + diff --git a/trunk/Examples/perl5/simple/example.dsp b/trunk/Examples/perl5/simple/example.dsp new file mode 100644 index 000000000..be8a0070e --- /dev/null +++ b/trunk/Examples/perl5/simple/example.dsp @@ -0,0 +1,148 @@ +# Microsoft Developer Studio Project File - Name="example" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=example - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "example.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "example.mak" CFG="example - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "example - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "example - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "example - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "$(PERL5_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 "$(PERL5_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 "$(PERL5_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 "$(PERL5_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 PERL5_INCLUDE: %PERL5_INCLUDE%
+ echo PERL5_LIB: %PERL5_LIB%
+ echo on
+ ..\..\..\swig.exe -perl5 $(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 PERL5_INCLUDE: %PERL5_INCLUDE%
+ echo PERL5_LIB: %PERL5_LIB%
+ echo on
+ ..\..\..\swig.exe -perl5 $(InputPath)
+
+# End Custom Build
+
+!ENDIF
+
+# End Source File
+# End Target
+# End Project
diff --git a/trunk/Examples/perl5/simple/example.i b/trunk/Examples/perl5/simple/example.i new file mode 100644 index 000000000..24093b9bf --- /dev/null +++ b/trunk/Examples/perl5/simple/example.i @@ -0,0 +1,7 @@ +/* File : example.i */ +%module example + +%inline %{ +extern int gcd(int x, int y); +extern double Foo; +%} diff --git a/trunk/Examples/perl5/simple/index.html b/trunk/Examples/perl5/simple/index.html new file mode 100644 index 000000000..7f230531d --- /dev/null +++ b/trunk/Examples/perl5/simple/index.html @@ -0,0 +1,99 @@ +<html> +<head> +<title>SWIG:Examples:perl5:simple</title> +</head> + +<body bgcolor="#ffffff"> + + +<tt>SWIG/Examples/perl5/simple/</tt> +<hr> + +<H2>Simple Perl5 Example</H2> + +<p> +This example illustrates how you can hook Perl to a very simple C program containing +a function and a global variable. + +<h2>The C Code</h2> + +Suppose you have the following C code: + +<blockquote> +<pre> +/* File : example.c */ + +/* A global variable */ +double Foo = 3.0; + +/* Compute the greatest common divisor of positive integers */ +int gcd(int x, int y) { + int g; + g = y; + while (x > 0) { + g = x; + x = y % x; + y = g; + } + return g; +} +</pre> +</blockquote> + +<h2>The SWIG interface</h2> + +Here is a simple SWIG interface file: + +<blockquote> +<pre> +/* File: example.i */ +%module example + +extern int gcd(int x, int y); +extern double Foo; +</pre> +</blockquote> + +<h2>Compilation</h2> + +<ol> +<li><tt>swig -perl5 <a href="example.i">example.i</a></tt> +<p> +<li>This produces two files: <tt><a href="example_wrap.c">example_wrap.c</a></tt> and <tt><a href="example.pm">example.pm</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.pl">here</a> to see a script that calls our C functions from Perl. + +<h2>Key points</h2> + +<ul> +<li>Use the <tt>use</tt> statement to load your extension module from Perl. For example: +<blockquote> +<pre> +use example; +</pre> +</blockquote> + +<li>C functions work just like Perl functions. For example: +<blockquote> +<pre> +$g = example::gcd(42,105); +</pre> +</blockquote> + +<li>C global variables are accessed like ordinary Perl variables. For example: +<blockquote> +<pre> +$a = $example::Foo; +</pre> +</blockquote> +</ul> + +<hr> +</body> +</html> diff --git a/trunk/Examples/perl5/simple/runme.pl b/trunk/Examples/perl5/simple/runme.pl new file mode 100644 index 000000000..b8655be8a --- /dev/null +++ b/trunk/Examples/perl5/simple/runme.pl @@ -0,0 +1,23 @@ +# +# Perl5 script for testing simple example + +use example; + +# Call our gcd() function + +$x = 42; +$y = 105; +$g = example::gcd($x,$y); +print "The gcd of $x and $y is $g\n"; + +# Manipulate the Foo global variable + +# Output its current value +print "Foo = $example::Foo\n"; + +# Change its value +$example::Foo = 3.1415926; + +# See if the change took effect +print "Foo = $example::Foo\n"; + diff --git a/trunk/Examples/perl5/value/Makefile b/trunk/Examples/perl5/value/Makefile new file mode 100644 index 000000000..ce2bbb5b9 --- /dev/null +++ b/trunk/Examples/perl5/value/Makefile @@ -0,0 +1,18 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +SRCS = example.c +TARGET = example +INTERFACE = example.i +SWIGOPT = +all:: + $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' perl5 + +static:: + $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \ + SWIGOPT='$(SWIGOPT)' TARGET='myperl' INTERFACE='$(INTERFACE)' perl5_static + +clean:: + $(MAKE) -f $(TOP)/Makefile perl5_clean + +check: all diff --git a/trunk/Examples/perl5/value/example.c b/trunk/Examples/perl5/value/example.c new file mode 100644 index 000000000..4ed2fe10a --- /dev/null +++ b/trunk/Examples/perl5/value/example.c @@ -0,0 +1,15 @@ +/* File : example.c */ + +#include "example.h" + +double dot_product(Vector a, Vector b) { + return (a.x*b.x + a.y*b.y + a.z*b.z); +} + +Vector vector_add(Vector a, Vector b) { + Vector r; + r.x = a.x + b.x; + r.y = a.y + b.y; + r.z = a.z + b.z; + return r; +} diff --git a/trunk/Examples/perl5/value/example.h b/trunk/Examples/perl5/value/example.h new file mode 100644 index 000000000..212cf4bdb --- /dev/null +++ b/trunk/Examples/perl5/value/example.h @@ -0,0 +1,5 @@ +/* File : example.h */ + +typedef struct { + double x, y, z; +} Vector; diff --git a/trunk/Examples/perl5/value/example.i b/trunk/Examples/perl5/value/example.i new file mode 100644 index 000000000..98fd60ed5 --- /dev/null +++ b/trunk/Examples/perl5/value/example.i @@ -0,0 +1,32 @@ +// Tests SWIG's handling of pass-by-value for complex datatypes +%module example + +%{ +#include "example.h" +%} + +/* Some functions that manipulate Vectors by value */ +%inline %{ +extern double dot_product(Vector a, Vector b); +extern Vector vector_add(Vector a, Vector b); +%} + +/* Include this because the vector_add() function will leak memory */ +void free(void *); + +/* Some helper functions for our interface */ +%inline %{ + +Vector *new_Vector(double x, double y, double z) { + Vector *v = (Vector *) malloc(sizeof(Vector)); + v->x = x; + v->y = y; + v->z = z; + return v; +} + +void vector_print(Vector *v) { + printf("Vector %p = (%g, %g, %g)\n", v, v->x, v->y, v->z); +} +%} + diff --git a/trunk/Examples/perl5/value/index.html b/trunk/Examples/perl5/value/index.html new file mode 100644 index 000000000..62c1a032f --- /dev/null +++ b/trunk/Examples/perl5/value/index.html @@ -0,0 +1,126 @@ +<html> +<head> +<title>SWIG:Examples:perl5:value</title> +</head> + +<body bgcolor="#ffffff"> + + +<tt>SWIG/Examples/perl5/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 Perl Script</h2> + +Click <a href="runme.pl">here</a> to see a script that uses these functions from Perl. + +<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>If you use proxy classes and are careful, the SWIG generated wrappers can automatically +clean up the result of return-by-reference when the scripting variable goes out of scope. + +<p> +<li>Passing parameters by value like this really isn't the best C programming style. +If possible, you might change your application to use pointers. + +<p> +<li>Similar translations are made when C++ references are used. + + +</ul> + +<hr> +</body> +</html> diff --git a/trunk/Examples/perl5/value/runme.pl b/trunk/Examples/perl5/value/runme.pl new file mode 100644 index 000000000..dc2660bf1 --- /dev/null +++ b/trunk/Examples/perl5/value/runme.pl @@ -0,0 +1,38 @@ +# file: runme.pl + +use example; + +# Create a couple of a vectors + +$v = example::new_Vector(1,2,3); +$w = example::new_Vector(10,11,12); + +print "I just created the following vectors\n"; +example::vector_print($v); +example::vector_print($w); + +# Now call some of our functions + +print "\nNow I'm going to compute the dot product\n"; +$d = example::dot_product($v,$w); +print "dot product = $d (should be 68)\n"; + +# Add the vectors together + +print "\nNow I'm going to add the vectors together\n"; +$r = example::vector_add($v,$w); +example::vector_print($r); +print "The value should be (11,13,15)\n"; + +# Now I'd better clean up the return result r + +print "\nNow I'm going to clean up the return result\n"; +example::free($r); + +print "Good\n"; + + + + + + diff --git a/trunk/Examples/perl5/variables/Makefile b/trunk/Examples/perl5/variables/Makefile new file mode 100644 index 000000000..ce2bbb5b9 --- /dev/null +++ b/trunk/Examples/perl5/variables/Makefile @@ -0,0 +1,18 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +SRCS = example.c +TARGET = example +INTERFACE = example.i +SWIGOPT = +all:: + $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' perl5 + +static:: + $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \ + SWIGOPT='$(SWIGOPT)' TARGET='myperl' INTERFACE='$(INTERFACE)' perl5_static + +clean:: + $(MAKE) -f $(TOP)/Makefile perl5_clean + +check: all diff --git a/trunk/Examples/perl5/variables/example.c b/trunk/Examples/perl5/variables/example.c new file mode 100644 index 000000000..aa4ffe9b3 --- /dev/null +++ b/trunk/Examples/perl5/variables/example.c @@ -0,0 +1,91 @@ +/* File : example.c */ + +/* I'm a file containing some C global variables */ + +/* Deal with Microsoft's attempt at deprecating C standard runtime functions */ +#if !defined(SWIG_NO_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) +# define _CRT_SECURE_NO_DEPRECATE +#endif + +#include <stdio.h> +#include <stdlib.h> +#include "example.h" + +int ivar = 0; +short svar = 0; +long lvar = 0; +unsigned int uivar = 0; +unsigned short usvar = 0; +unsigned long ulvar = 0; +signed char scvar = 0; +unsigned char ucvar = 0; +char cvar = 0; +float fvar = 0; +double dvar = 0; +char *strvar = 0; +const char cstrvar[] = "Goodbye"; +int *iptrvar = 0; +char name[256] = "Dave"; +char path[256] = "/home/beazley"; + + +/* Global variables involving a structure */ +Point *ptptr = 0; +Point pt = { 10, 20 }; + +/* A variable that we will make read-only in the interface */ +int status = 1; + +/* A debugging function to print out their values */ + +void print_vars() { + printf("ivar = %d\n", ivar); + printf("svar = %d\n", svar); + printf("lvar = %ld\n", lvar); + printf("uivar = %u\n", uivar); + printf("usvar = %u\n", usvar); + printf("ulvar = %lu\n", ulvar); + printf("scvar = %d\n", scvar); + printf("ucvar = %u\n", ucvar); + printf("fvar = %g\n", fvar); + printf("dvar = %g\n", dvar); + printf("cvar = %c\n", cvar); + printf("strvar = %s\n", strvar ? strvar : "(null)"); + printf("cstrvar = %s\n", cstrvar ? cstrvar : "(null)"); + printf("iptrvar = %p\n", iptrvar); + printf("name = %s\n", name); + printf("ptptr = %p (%d, %d)\n", ptptr, ptptr ? ptptr->x : 0, ptptr ? ptptr->y : 0); + printf("pt = (%d, %d)\n", pt.x, pt.y); + printf("status = %d\n", status); +} + +/* A function to create an integer (to test iptrvar) */ + +int *new_int(int value) { + int *ip = (int *) malloc(sizeof(int)); + *ip = value; + return ip; +} + +/* A function to create a point */ + +Point *new_Point(int x, int y) { + Point *p = (Point *) malloc(sizeof(Point)); + p->x = x; + p->y = y; + return p; +} + +char * Point_print(Point *p) { + static char buffer[256]; + if (p) { + sprintf(buffer,"(%d,%d)", p->x,p->y); + } else { + sprintf(buffer,"null"); + } + return buffer; +} + +void pt_print() { + printf("(%d, %d)\n", pt.x, pt.y); +} diff --git a/trunk/Examples/perl5/variables/example.h b/trunk/Examples/perl5/variables/example.h new file mode 100644 index 000000000..0f7e89594 --- /dev/null +++ b/trunk/Examples/perl5/variables/example.h @@ -0,0 +1,6 @@ +/* File: example.h */ + +typedef struct { + int x,y; +} Point; + diff --git a/trunk/Examples/perl5/variables/example.i b/trunk/Examples/perl5/variables/example.i new file mode 100644 index 000000000..9d0101cb7 --- /dev/null +++ b/trunk/Examples/perl5/variables/example.i @@ -0,0 +1,51 @@ +/* File : example.i */ +%module example +%{ +#include "example.h" +%} + +#pragma SWIG nowarn=SWIGWARN_TYPEMAP_SWIGTYPELEAK + +/* Some global variable declarations */ +%inline %{ +extern int ivar; +extern short svar; +extern long lvar; +extern unsigned int uivar; +extern unsigned short usvar; +extern unsigned long ulvar; +extern signed char scvar; +extern unsigned char ucvar; +extern char cvar; +extern float fvar; +extern double dvar; +extern char *strvar; +extern const char cstrvar[]; +extern int *iptrvar; +extern char name[256]; + +extern Point *ptptr; +extern Point pt; +%} + + +/* Some read-only variables */ + +%immutable; + +%inline %{ +extern int status; +extern char path[256]; +%} + +%mutable; + +/* Some helper functions to make it easier to test */ +%inline %{ +extern void print_vars(); +extern int *new_int(int value); +extern Point *new_Point(int x, int y); +extern char *Point_print(Point *p); +extern void pt_print(); +%} + diff --git a/trunk/Examples/perl5/variables/index.html b/trunk/Examples/perl5/variables/index.html new file mode 100644 index 000000000..e4d426e2d --- /dev/null +++ b/trunk/Examples/perl5/variables/index.html @@ -0,0 +1,63 @@ +<html> +<head> +<title>SWIG:Examples:perl5:variables</title> +</head> + +<body bgcolor="#ffffff"> + +<tt>SWIG/Examples/perl5/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 Perl variable that magically +retrieves or updates the value of the underlying C variable when it is +accessed. Click <a href="example.i">here</a> to see a SWIG interface with some variable +declarations in it. + +<h2>Manipulating Variables from Perl</h2> + +Accessing a C global variable from Perl is easy---just reference it like a normal Perl variable. +Click <a href="runme.pl">here</a> to see a script that updates and prints some global variables. + +<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>Notes:</h2> + +<ul> +<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 Perl, 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 Perl 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. +<li>Variables are linked using Perl's magic mechanism. Take a look at the Advanced Perl Programming book to +find out more about this feature. +</ul> + +</body> +</html> +<hr> diff --git a/trunk/Examples/perl5/variables/runme.pl b/trunk/Examples/perl5/variables/runme.pl new file mode 100644 index 000000000..76e3dc8bc --- /dev/null +++ b/trunk/Examples/perl5/variables/runme.pl @@ -0,0 +1,73 @@ +# file: runme.pl + +use example; + +# Try to set the values of some global variables + +$example::ivar = 42; +$example::svar = -31000; +$example::lvar = 65537; +$example::uivar = 123456; +$example::usvar = 61000; +$example::ulvar = 654321; +$example::scvar = -13; +$example::ucvar = 251; +$example::cvar = "S"; +$example::fvar = 3.14159; +$example::dvar = 2.1828; +$example::strvar = "Hello World"; +$example::iptrvar= example::new_int(37); +$example::ptptr = example::new_Point(37,42); +$example::name = "Bill"; + +# Now print out the values of the variables + +print "Variables (values printed from Perl)\n"; + +print "ivar = $example::ivar\n"; +print "svar = $example::svar\n"; +print "lvar = $example::lvar\n"; +print "uivar = $example::uivar\n"; +print "usvar = $example::usvar\n"; +print "ulvar = $example::ulvar\n"; +print "scvar = $example::scvar\n"; +print "ucvar = $example::ucvar\n"; +print "fvar = $example::fvar\n"; +print "dvar = $example::dvar\n"; +print "cvar = $example::cvar\n"; +print "strvar = $example::strvar\n"; +print "cstrvar = $example::cstrvar\n"; +print "iptrvar = $example::iptrvar\n"; +print "name = $example::name\n"; +print "ptptr = $example::ptptr", example::Point_print($example::ptptr), "\n"; +print "pt = $example::pt", example::Point_print($example::pt), "\n"; + +print "\nVariables (values printed from C)\n"; + +example::print_vars(); + +print "\nI'm going to try and update a structure variable.\n"; + +$example::pt = $example::ptptr; + +print "The new value is "; +example::pt_print(); +print "You should see the value", example::Point_print($example::ptptr), "\n"; + + +print "\nNow I'm going to try and modify some read only variables\n"; + + +print " Trying to set 'status'\n"; +eval { $example::status = 0; }; +if (!$@) { + die("status"); +} +print " get error for 'status'\n"; + +print " Tring to set 'path'\n"; +eval { $example::path = "Whoa!";}; +if (!$@) { + die("path"); +} +print " get error for 'path'\n"; diff --git a/trunk/Examples/perl5/xmlstring/Makefile b/trunk/Examples/perl5/xmlstring/Makefile new file mode 100644 index 000000000..36143fc3a --- /dev/null +++ b/trunk/Examples/perl5/xmlstring/Makefile @@ -0,0 +1,23 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +CXXSRCS = example.cxx +TARGET = example +INTERFACE = example.i +LIBS = -lxerces-c -lxerces-depdom -lm + +all:: + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' LIBS=$(LIBS) CXX="g++ -g3" perl5_cpp + +static:: + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + TARGET='myperl' INTERFACE='$(INTERFACE)' perl5_cpp_static + +clean:: + $(MAKE) -f $(TOP)/Makefile perl5_clean + +check: all + + +run: + perl runme.pl diff --git a/trunk/Examples/perl5/xmlstring/example.cxx b/trunk/Examples/perl5/xmlstring/example.cxx new file mode 100644 index 000000000..370dd9ea9 --- /dev/null +++ b/trunk/Examples/perl5/xmlstring/example.cxx @@ -0,0 +1 @@ +#include "example.h" diff --git a/trunk/Examples/perl5/xmlstring/example.h b/trunk/Examples/perl5/xmlstring/example.h new file mode 100644 index 000000000..a1ccf2185 --- /dev/null +++ b/trunk/Examples/perl5/xmlstring/example.h @@ -0,0 +1,36 @@ +#include <xercesc/util/XMLString.hpp> + + +class XMLChTest +{ + XMLCh *_val; + +public: + + XMLChTest() : _val(0) + { + } + + void set(const XMLCh *v) + { + size_t len = XERCES_CPP_NAMESPACE::XMLString::stringLen(v); + delete[] _val; + _val = new XMLCh[len + 1]; + for (int i = 0; i < len; ++i) { + _val[i] = v[i]; + } + _val[len] = 0; + } + + const XMLCh *get() + { + return _val; + } + + XMLCh get_first() + { + return _val[0]; + } + +}; + diff --git a/trunk/Examples/perl5/xmlstring/example.i b/trunk/Examples/perl5/xmlstring/example.i new file mode 100644 index 000000000..8a9e02e40 --- /dev/null +++ b/trunk/Examples/perl5/xmlstring/example.i @@ -0,0 +1,10 @@ +%module example + +%include <xmlstring.i> + +%{ +#include "example.h" +%} + + +%include example.h diff --git a/trunk/Examples/perl5/xmlstring/runme.pl b/trunk/Examples/perl5/xmlstring/runme.pl new file mode 100644 index 000000000..1b223d4ca --- /dev/null +++ b/trunk/Examples/perl5/xmlstring/runme.pl @@ -0,0 +1,8 @@ +use example; + + +$e1 = new example::XMLChTest(); +$e1->set("hello"); +print $e1->get(),"\n"; +print $e1->get_first(),"\n"; + diff --git a/trunk/Examples/perl5/xmlstring/xmlstring.i b/trunk/Examples/perl5/xmlstring/xmlstring.i new file mode 100644 index 000000000..3ef53169d --- /dev/null +++ b/trunk/Examples/perl5/xmlstring/xmlstring.i @@ -0,0 +1,111 @@ +%include <perlstrings.swg> + +%fragment("<XMLCh.h>","header") +%{ +#include <xercesc/util/XMLString.hpp> +#include <xercesc/util/TransService.hpp> +#include <xercesc/util/XMLUTF8Transcoder.hpp> +%} + +%fragment("SWIG_UTF8Transcoder","header",fragment="<XMLCh.h>") { +SWIGINTERN XERCES_CPP_NAMESPACE::XMLTranscoder* +SWIG_UTF8Transcoder() { + using namespace XERCES_CPP_NAMESPACE; + static int init = 0; + static XMLTranscoder* UTF8_TRANSCODER = NULL; + static XMLCh* UTF8_ENCODING = NULL; + if (!init) { + XMLTransService::Codes failReason; + XMLPlatformUtils::Initialize(); // first we must create the transservice + UTF8_ENCODING = XMLString::transcode("UTF-8"); + UTF8_TRANSCODER = XMLPlatformUtils::fgTransService->makeNewTranscoderFor(UTF8_ENCODING, + failReason, + 1024); + init = 1; + } + return UTF8_TRANSCODER; +} +} + +%fragment("SWIG_AsXMLChPtrAndSize","header",fragment="SWIG_AsCharPtrAndSize",fragment="SWIG_UTF8Transcoder") { +SWIGINTERN int +SWIG_AsXMLChPtrAndSize(SV *obj, XMLCh **val, size_t* psize, int *alloc) +{ + if (!val) { + return SWIG_AsCharPtrAndSize(obj, 0, 0, 0); + } else { + size_t size; + char *cptr = 0; + int calloc = SWIG_OLDOBJ; + int res = SWIG_AsCharPtrAndSize(obj, &cptr, &size, &calloc); + if (SWIG_IsOK(res)) { + STRLEN length = size - 1; + if (SvUTF8(obj)) { + unsigned int charsEaten = 0; + unsigned char* sizes = %new_array(size, unsigned char); + *val = %new_array(size, XMLCh); + unsigned int chars_stored = + SWIG_UTF8Transcoder()->transcodeFrom((const XMLByte*) cptr, + (unsigned int) length, + (XMLCh*) *val, + (unsigned int) length, + charsEaten, + (unsigned char*)sizes + ); + %delete_array(sizes); + // indicate the end of the string + (*val)[chars_stored] = '\0'; + } else { + *val = XERCES_CPP_NAMESPACE::XMLString::transcode(cptr); + } + if (psize) *psize = size; + if (alloc) *alloc = SWIG_NEWOBJ; + if (calloc == SWIG_NEWOBJ) %delete_array(cptr); + return SWIG_NEWOBJ; + } else { + return res; + } + } +} +} + +%fragment("SWIG_FromXMLChPtrAndSize","header",fragment="SWIG_UTF8Transcoder") { +SWIGINTERNINLINE SV * +SWIG_FromXMLChPtrAndSize(const XMLCh* input, size_t size) +{ + SV *output = sv_newmortal(); + unsigned int charsEaten = 0; + int length = size; // string length + XMLByte* res = %new_array(length * UTF8_MAXLEN, XMLByte); // output string + unsigned int total_chars = + SWIG_UTF8Transcoder()->transcodeTo((const XMLCh*) input, + (unsigned int) length, + (XMLByte*) res, + (unsigned int) length*UTF8_MAXLEN, + charsEaten, + XERCES_CPP_NAMESPACE::XMLTranscoder::UnRep_Throw + ); + res[total_chars] = '\0'; + sv_setpv((SV*)output, (char *)res ); + SvUTF8_on((SV*)output); + %delete_array(res); + return output; +} +} + +%init { + if (!SWIG_UTF8Transcoder()) { + croak("ERROR: XML::Xerces: INIT: Could not create UTF-8 transcoder"); + } +} + + +%include <typemaps/strings.swg> +%typemaps_string(%checkcode(UNISTRING), %checkcode(UNICHAR), + XMLCh, XMLCh, + SWIG_AsXMLChPtrAndSize, + SWIG_FromXMLChPtrAndSize, + XERCES_CPP_NAMESPACE::XMLString::stringLen, + "<XMLCh.h>", INT_MIN, INT_MAX); + + |