diff options
author | Lorry Tar Creator <lorry-tar-importer@baserock.org> | 2009-08-18 20:56:02 +0000 |
---|---|---|
committer | Lorry <lorry@roadtrain.codethink.co.uk> | 2012-09-25 16:59:08 +0000 |
commit | 9f8a09ed743cedd9547bf0661d518647966ab114 (patch) | |
tree | 9c7803d3b27a8ec22e91792ac7f7932efa128b20 /Examples/ruby | |
download | swig-tarball-master.tar.gz |
Imported from /srv/lorry/lorry-area/swig-tarball/swig-1.3.40.tar.gz.HEADswig-1.3.40master
Diffstat (limited to 'Examples/ruby')
134 files changed, 5852 insertions, 0 deletions
diff --git a/Examples/ruby/check.list b/Examples/ruby/check.list new file mode 100644 index 0000000..131dcbb --- /dev/null +++ b/Examples/ruby/check.list @@ -0,0 +1,23 @@ +# see top-level Makefile.in +class +constants +enum +free_function +funcptr +funcptr2 +functor +hashargs +import +import_template +java +mark_function +multimap +operator +overloading +pointer +reference +simple +std_vector +template +value +variables diff --git a/Examples/ruby/class/Makefile b/Examples/ruby/class/Makefile new file mode 100644 index 0000000..56c84c6 --- /dev/null +++ b/Examples/ruby/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)' ruby_cpp + +static:: + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + TARGET='myruby' INTERFACE='$(INTERFACE)' ruby_cpp_static + +clean:: + $(MAKE) -f $(TOP)/Makefile ruby_clean + +check: all diff --git a/Examples/ruby/class/example.cxx b/Examples/ruby/class/example.cxx new file mode 100644 index 0000000..1e8e203 --- /dev/null +++ b/Examples/ruby/class/example.cxx @@ -0,0 +1,28 @@ +/* File : example.c */ + +#include "example.h" +#define M_PI 3.14159265358979323846 + +/* Move the shape to a new location */ +void Shape::move(double dx, double dy) { + x += dx; + y += dy; +} + +int Shape::nshapes = 0; + +double Circle::area(void) { + return M_PI*radius*radius; +} + +double Circle::perimeter(void) { + return 2*M_PI*radius; +} + +double Square::area(void) { + return width*width; +} + +double Square::perimeter(void) { + return 4*width; +} diff --git a/Examples/ruby/class/example.dsp b/Examples/ruby/class/example.dsp new file mode 100644 index 0000000..2adab78 --- /dev/null +++ b/Examples/ruby/class/example.dsp @@ -0,0 +1,154 @@ +# 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 "$(RUBY_INCLUDE)" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE_EXPORTS" /D NT=1 /D "IMPORT" /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 "$(RUBY_LIB)" /nologo /dll /debug /machine:I386 /out:"example.dll" /pdbtype:sept
+# SUBTRACT LINK32 /pdb:none
+
+!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 "$(RUBY_INCLUDE)" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE_EXPORTS" /D NT=1 /D "IMPORT" /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 "$(RUBY_LIB)" /nologo /dll /machine:I386 /out:"example.dll"
+# SUBTRACT LINK32 /pdb:none
+
+!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 RUBY_INCLUDE: %RUBY_INCLUDE%
+ echo RUBY_LIB: %RUBY_LIB%
+ echo on
+ ..\..\..\swig.exe -c++ -ruby $(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 RUBY_INCLUDE: %RUBY_INCLUDE%
+ echo RUBY_LIB: %RUBY_LIB%
+ echo on
+ ..\..\..\swig.exe -c++ -ruby $(InputPath)
+
+# End Custom Build
+
+!ENDIF
+
+# End Source File
+# End Target
+# End Project
diff --git a/Examples/ruby/class/example.h b/Examples/ruby/class/example.h new file mode 100644 index 0000000..46d9013 --- /dev/null +++ b/Examples/ruby/class/example.h @@ -0,0 +1,39 @@ +/* File : example.h */ + +class Shape { +public: + Shape() { + nshapes++; + } + virtual ~Shape() { + nshapes--; + }; + double x, y; + void move(double dx, double dy); + virtual double area(void) = 0; + virtual double perimeter(void) = 0; + static int nshapes; +}; + +class Circle : public Shape { +private: + double radius; +public: + Circle(double r) : radius(r) { }; + virtual double area(void); + virtual double perimeter(void); +}; + +class Square : public Shape { +private: + double width; +public: + Square(double w) : width(w) { }; + virtual double area(void); + virtual double perimeter(void); +}; + + + + + diff --git a/Examples/ruby/class/example.i b/Examples/ruby/class/example.i new file mode 100644 index 0000000..75700b3 --- /dev/null +++ b/Examples/ruby/class/example.i @@ -0,0 +1,10 @@ +/* File : example.i */ +%module example + +%{ +#include "example.h" +%} + +/* Let's just grab the original header file here */ +%include "example.h" + diff --git a/Examples/ruby/class/index.html b/Examples/ruby/class/index.html new file mode 100644 index 0000000..67eeac9 --- /dev/null +++ b/Examples/ruby/class/index.html @@ -0,0 +1,199 @@ +<html> +<head> +<title>SWIG:Examples:ruby:class</title> +</head> + +<body bgcolor="#ffffff"> + + +<tt>SWIG/Examples/ruby/class/</tt> +<hr> + +<H2>Wrapping a simple C++ class</H2> + +<p> +This example illustrates C++ class wrapping performed by SWIG. +C++ classes are simply transformed into Ruby classes that provide methods to +access 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++ -ruby example.i +</pre> +</blockquote> + +<h2>A sample Ruby script</h2> + +Click <a href="runme.rb">here</a> to see a script that calls the C++ functions from Ruby. + +<h2>Key points</h2> + +<ul> +<li>To create a new object, you call a constructor like this: + +<blockquote> +<pre> +c = Example::Circle.new(10) +</pre> +</blockquote> + +<p> +<li>To access member data, a pair of accessor methods are used. +For example: + +<blockquote> +<pre> +c.x = 15 # Set member data +x = c.x # Get member data +</pre> +</blockquote> + +<p> +<li>To invoke a member function, you simply do this + +<blockquote> +<pre> +print "The area is ", c.area, "\n" +</pre> +</blockquote> + +<p> +<li>When a instance of Ruby level wrapper class is garbage collected by +Ruby interpreter, the corresponding C++ destructor is automatically invoked. +(Note: destructors are currently not inherited. This might change later. +Until then, use <tt>-make_default</tt>). + +<p> +<li>Static member variables are wrapped as Ruby class accessor methods. +For example: + +<blockquote> +<pre> +n = Shape.nshapes # Get a static data member +Shapes.nshapes = 13 # Set a static data member +</pre> +</blockquote> + +</ul> + +<h2>General Comments</h2> + +<ul> +<li>Ruby module of SWIG differs from other language modules in wrapping C++ +interfaces. They provides lower-level interfaces and optional higher-level +interfaces know as proxy classes. Ruby module needs no such redundancy +due to Ruby's sophisticated extension API. + +<p> +<li>SWIG *does* know how to properly perform upcasting of objects in +an inheritance hierarchy except for multiple inheritance. + +<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> +<p> + +<li>Dave's snide remark: Like a large bottle of strong Tequilla, it's better to +use C++ in moderation. + +</ul> + +<hr> +</body> +</html> diff --git a/Examples/ruby/class/runme.rb b/Examples/ruby/class/runme.rb new file mode 100644 index 0000000..de73bcd --- /dev/null +++ b/Examples/ruby/class/runme.rb @@ -0,0 +1,49 @@ +# file: runme.rb + +# This file illustrates the C++ interface created by SWIG. +# All of our C++ classes get converted into Ruby classes. + +require 'example' + +# ----- Object creation ----- + +print "Creating some objects:\n" +c = Example::Circle.new(10) +print " Created circle #{c}\n" +s = Example::Square.new(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 + +# Notice how we can do this using functions specific to +# the 'Circle' class. +c.x = 20 +c.y = 30 + +# Now use the same functions in the base class +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" +for o in [c, s] + print " #{o}\n" + print " area = ", o.area, "\n" + print " perimeter = ", o.perimeter, "\n" +end +# Notice how the Shape#area() and Shape#perimeter() functions really +# invoke the appropriate virtual method on each object. + +print "\n", Example::Shape.nshapes," shapes remain\n" +print "Goodbye\n" diff --git a/Examples/ruby/constants/Makefile b/Examples/ruby/constants/Makefile new file mode 100644 index 0000000..7dce3be --- /dev/null +++ b/Examples/ruby/constants/Makefile @@ -0,0 +1,18 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +SRCS = +TARGET = example +INTERFACE = example.i + +all:: + $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \ + TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' ruby + +static:: + $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \ + TARGET='myruby' INTERFACE='$(INTERFACE)' ruby_static + +clean:: + $(MAKE) -f $(TOP)/Makefile ruby_clean + +check: all diff --git a/Examples/ruby/constants/example.i b/Examples/ruby/constants/example.i new file mode 100644 index 0000000..14eb23c --- /dev/null +++ b/Examples/ruby/constants/example.i @@ -0,0 +1,27 @@ +/* File : example.i */ +%module example + +/* A few preprocessor macros */ + +#define ICONST 42 +#define FCONST 2.1828 +#define CCONST 'x' +#define CCONST2 '\n' +#define SCONST "Hello World" +#define SCONST2 "\"Hello World\"" + +/* This should work just fine */ +#define EXPR ICONST + 3*(FCONST) + +/* This shouldn't do anything */ +#define EXTERN extern + +/* Neither should this (BAR isn't defined) */ +#define FOO (ICONST + BAR) + +/* The following directives also produce constants */ + +%constant int Iconst = 37; +%constant double Fconst = 3.14; + + diff --git a/Examples/ruby/constants/index.html b/Examples/ruby/constants/index.html new file mode 100644 index 0000000..3b63f3d --- /dev/null +++ b/Examples/ruby/constants/index.html @@ -0,0 +1,64 @@ +<html> +<head> +<title>SWIG:Examples:ruby:constants</title> +</head> + +<body bgcolor="#ffffff"> + +<tt>SWIG/Examples/ruby/constants/</tt> +<hr> + +<H2>Wrapping C Constants</H2> + +<p> +When SWIG encounters C preprocessor macros and C declarations that look like constants, +it creates Ruby constants 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 Ruby</h2> + +Click <a href="run.rb">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 Ruby 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 Ruby strings. +<li>C string literals such as "Hello World" are converted into Ruby 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 Ruby constants. + +<li>Constants that begin with lower case character are automatically capitalized. +For example: +<blockquote> +<pre> +const int iconst = 37; +</pre> +</blockquote> +is capitalized as <tt>Example::Iconst</tt> because Ruby constants name must begin +with upper case character. + +<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/Examples/ruby/constants/runme.rb b/Examples/ruby/constants/runme.rb new file mode 100755 index 0000000..2a6b5f5 --- /dev/null +++ b/Examples/ruby/constants/runme.rb @@ -0,0 +1,25 @@ +# file: runme.rb + +require '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" + +begin + print "EXTERN = ", Example::EXTERN, " (Arg! This shouldn't print anything)\n" +rescue NameError + print "EXTERN isn't defined (good)\n" +end + +begin + print "FOO = ", Example::FOO, " (Arg! This shouldn't print anything)\n" +rescue NameError + print "FOO isn't defined (good)\n" +end diff --git a/Examples/ruby/enum/Makefile b/Examples/ruby/enum/Makefile new file mode 100644 index 0000000..56c84c6 --- /dev/null +++ b/Examples/ruby/enum/Makefile @@ -0,0 +1,19 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +CXXSRCS = example.cxx +TARGET = example +INTERFACE = example.i +LIBS = -lm + +all:: + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' ruby_cpp + +static:: + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + TARGET='myruby' INTERFACE='$(INTERFACE)' ruby_cpp_static + +clean:: + $(MAKE) -f $(TOP)/Makefile ruby_clean + +check: all diff --git a/Examples/ruby/enum/example.cxx b/Examples/ruby/enum/example.cxx new file mode 100644 index 0000000..6785e57 --- /dev/null +++ b/Examples/ruby/enum/example.cxx @@ -0,0 +1,37 @@ +/* File : example.c */ + +#include "example.h" +#include <stdio.h> + +void Foo::enum_test(speed s) { + if (s == IMPULSE) { + printf("IMPULSE speed\n"); + } else if (s == WARP) { + printf("WARP speed\n"); + } else if (s == LUDICROUS) { + printf("LUDICROUS speed\n"); + } else { + printf("Unknown speed\n"); + } +} + +void enum_test(color c, Foo::speed s) { + if (c == RED) { + printf("color = RED, "); + } else if (c == BLUE) { + printf("color = BLUE, "); + } else if (c == GREEN) { + printf("color = GREEN, "); + } else { + printf("color = Unknown color!, "); + } + if (s == Foo::IMPULSE) { + printf("speed = IMPULSE speed\n"); + } else if (s == Foo::WARP) { + printf("speed = WARP speed\n"); + } else if (s == Foo::LUDICROUS) { + printf("speed = LUDICROUS speed\n"); + } else { + printf("speed = Unknown speed!\n"); + } +} diff --git a/Examples/ruby/enum/example.h b/Examples/ruby/enum/example.h new file mode 100644 index 0000000..525d62a --- /dev/null +++ b/Examples/ruby/enum/example.h @@ -0,0 +1,13 @@ +/* File : example.h */ + +enum color { RED, BLUE, GREEN }; + +class Foo { + public: + Foo() { } + enum speed { IMPULSE, WARP, LUDICROUS }; + void enum_test(speed s); +}; + +void enum_test(color c, Foo::speed s); + diff --git a/Examples/ruby/enum/example.i b/Examples/ruby/enum/example.i new file mode 100644 index 0000000..23ee8a8 --- /dev/null +++ b/Examples/ruby/enum/example.i @@ -0,0 +1,11 @@ +/* File : example.i */ +%module example + +%{ +#include "example.h" +%} + +/* Let's just grab the original header file here */ + +%include "example.h" + diff --git a/Examples/ruby/enum/index.html b/Examples/ruby/enum/index.html new file mode 100644 index 0000000..d773d9c --- /dev/null +++ b/Examples/ruby/enum/index.html @@ -0,0 +1,35 @@ +<html> +<head> +<title>SWIG:Examples:ruby:enum</title> +</head> + +<body bgcolor="#ffffff"> + + +<tt>SWIG/Examples/ruby/enum/</tt> +<hr> + +<H2>Wrapping enumerations</H2> + +<p> +This example tests SWIG's ability to wrap enumerations. By default, SWIG +converts enumeration specifications into integer constants. Further use +of enumerated types are handled as integers. + +<ul> +<li><a href="example.h">example.h</a>. Header file containing some enums. +<li><a href="example.i">example.i</a>. Interface file. +<li><a href="runme.rb">runme.rb</a>. Sample Ruby script. +</ul> + +<h2>Notes</h2> + +<ul> +<li>SWIG allows arbitrary integers to be passed as enum values. However, +the result of passing an integer not corresponding to any of the values +specified in the <tt>enum</tt> specification is undefined. +</ul> + +<hr> +</body> +</html> diff --git a/Examples/ruby/enum/runme.rb b/Examples/ruby/enum/runme.rb new file mode 100644 index 0000000..cd6a76f --- /dev/null +++ b/Examples/ruby/enum/runme.rb @@ -0,0 +1,30 @@ +# file: runme.rb + +require 'example' + +# ----- Object creation ----- + +# Print out the value of some enums +print "*** color ***\n" +print " RED = #{Example::RED}\n" +print " BLUE = #{Example::BLUE}\n" +print " GREEN = #{Example::GREEN}\n" + +print "\n*** Foo::speed ***\n" +print " Foo::IMPULSE = #{Example::Foo::IMPULSE}\n" +print " Foo::WARP = #{Example::Foo::WARP}\n" +print " Foo::LUDICROUS = #{Example::Foo::LUDICROUS}\n" + +print "\nTesting use of enums with functions\n\n" + +Example::enum_test(Example::RED, Example::Foo::IMPULSE) +Example::enum_test(Example::BLUE, Example::Foo::WARP) +Example::enum_test(Example::GREEN, Example::Foo::LUDICROUS) +Example::enum_test(1234, 5678) + +print "\nTesting use of enum with class method\n" +f = Example::Foo.new() + +f.enum_test(Example::Foo::IMPULSE) +f.enum_test(Example::Foo::WARP) +f.enum_test(Example::Foo::LUDICROUS) diff --git a/Examples/ruby/exception_class/Makefile b/Examples/ruby/exception_class/Makefile new file mode 100644 index 0000000..016a5ad --- /dev/null +++ b/Examples/ruby/exception_class/Makefile @@ -0,0 +1,19 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +CXXSRCS = +TARGET = example +INTERFACE = example.i +LIBS = -lm + +all:: + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' ruby_cpp + +static:: + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + TARGET='myruby' INTERFACE='$(INTERFACE)' ruby_cpp_static + +clean:: + $(MAKE) -f $(TOP)/Makefile ruby_clean + +check: all diff --git a/Examples/ruby/exception_class/example.h b/Examples/ruby/exception_class/example.h new file mode 100644 index 0000000..9facde4 --- /dev/null +++ b/Examples/ruby/exception_class/example.h @@ -0,0 +1,51 @@ +/* File : example.h */ + +// A simple exception +class EmptyError { }; +class FullError { + public: + int maxsize; + FullError(int m) : maxsize(m) { } +}; + +template<typename T> class Queue { + int maxsize; + T *items; + int nitems; + int last; + public: + Queue(int size) { + maxsize = size; + items = new T[size]; + nitems = 0; + last = 0; + } + ~Queue() { + delete [] items; + } + void enqueue(T x) throw(FullError) { + if (nitems == maxsize) { + throw FullError(maxsize); + } + items[last] = x; + last = (last + 1) % maxsize; + nitems++; + } + T dequeue() { + T x; + if (nitems == 0) throw EmptyError(); + x = items[(last + maxsize - nitems) % maxsize]; + nitems--; + return x; + } + int length() { + return nitems; + } +}; + + + + + + + diff --git a/Examples/ruby/exception_class/example.i b/Examples/ruby/exception_class/example.i new file mode 100644 index 0000000..5094b7a --- /dev/null +++ b/Examples/ruby/exception_class/example.i @@ -0,0 +1,46 @@ +/* This example illustrates the use of the %exceptionclass feature. By + default, if a method has a throws specification then SWIG will generate + code to catch the exception and pass it on the scripting language. + + If a method does not have a throws specification, but does throw + an exception, then the %exceptionclass feature can be used to tell + SWIG about the exception class so it can be properly added to Ruby. + This is done by making the exception class inherit from rb_eRuntimeError.*/ + +%module example + +%{ +#include "example.h" +%} + + +/* The EmpytError doesn't appear in a throw declaration, and hence + we need to tell SWIG that the dequeue method throws it. This can + now be done via the %catchs feature. */ +%catches(EmptyError) *::dequeue(); + + +/* What the catches clause is doing under the covers is this: + +%exceptionclass EmptyError; + +%exception *::dequeue { + try { + $action + } catch(EmptyError& e) { + // Create a new instance of the EmptyError, wrap it as a Ruby object that Ruby owns, + // and return it as the exception. For this to work EmtpyError must inherit from + // a standard Ruby exception class such as rb_eRuntimeError. SWIG automatically does + // this when the class is marked as %exceptionclass or is a throws specification. + %raise(SWIG_NewPointerObj(new EmptyError(e),SWIGTYPE_p_EmptyError, SWIG_POINTER_OWN), + "EmptyError", SWIGTYPE_p_EmptyError); + } +} +*/ + +/* Grab the original header file */ +%include "example.h" + +/* Instantiate a few templates */ +%template(IntQueue) Queue<int>; +%template(DoubleQueue) Queue<double>; diff --git a/Examples/ruby/exception_class/runme.rb b/Examples/ruby/exception_class/runme.rb new file mode 100644 index 0000000..c198c14 --- /dev/null +++ b/Examples/ruby/exception_class/runme.rb @@ -0,0 +1,45 @@ +require 'example' + +q = Example::IntQueue.new(10) + +puts "Inserting items into intQueue" + +begin + 0.upto(100) do |i| + q.enqueue(i) + end +rescue Example::FullError => e + puts "Maxsize is: #{e.maxsize}" +end + +puts "Removing items" + +begin + loop do + q.dequeue() + end +rescue Example::EmptyError => e + ## do nothing +end + +q = Example::DoubleQueue.new(1000) + +puts "Inserting items into doubleQueue" + +begin + 0.upto(100) do |i| + q.enqueue(i*1.5) + end +rescue Example::FullError => e + puts "Maxsize is: #{e.maxsize}" +end + +puts "Removing items" + +begin + loop do + q.dequeue() + end +rescue Example::EmptyError => e + # do nothing +end diff --git a/Examples/ruby/free_function/Makefile b/Examples/ruby/free_function/Makefile new file mode 100644 index 0000000..56c84c6 --- /dev/null +++ b/Examples/ruby/free_function/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)' ruby_cpp + +static:: + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + TARGET='myruby' INTERFACE='$(INTERFACE)' ruby_cpp_static + +clean:: + $(MAKE) -f $(TOP)/Makefile ruby_clean + +check: all diff --git a/Examples/ruby/free_function/example.cxx b/Examples/ruby/free_function/example.cxx new file mode 100644 index 0000000..402a947 --- /dev/null +++ b/Examples/ruby/free_function/example.cxx @@ -0,0 +1,67 @@ +#include "example.h" + +Animal::Animal(const char* name) : name_(name) +{ +} + +Animal::~Animal() +{ +} + +/* Return the animal's name */ +const char* Animal::get_name() const +{ + return name_.c_str(); +} + +Zoo::Zoo() +{ +} + +Zoo::~Zoo() +{ + IterType iter = this->animals.begin(); + IterType end = this->animals.end(); + + for(; iter != end; ++iter) + { + Animal* animal = *iter; + delete animal; + } +} + +/* Create a new animal. */ +Animal* Zoo::create_animal(const char* name) +{ + return new Animal(name); +} + +/* Add a new animal to the zoo. */ +void Zoo::add_animal(Animal* animal) +{ + animals.push_back(animal); +} + +Animal* Zoo::remove_animal(size_t i) +{ + /* Note a production implementation should check + for out of range errors. */ + Animal* result = this->animals[i]; + IterType iter = this->animals.begin(); + std::advance(iter, i); + this->animals.erase(iter); + + return result; +} + +/* Return the number of animals in the zoo. */ +size_t Zoo::get_num_animals() const +{ + return animals.size(); +} + +/* Return a pointer to the ith animal */ +Animal* Zoo::get_animal(size_t i) const +{ + return animals[i]; +} diff --git a/Examples/ruby/free_function/example.dsp b/Examples/ruby/free_function/example.dsp new file mode 100644 index 0000000..2adab78 --- /dev/null +++ b/Examples/ruby/free_function/example.dsp @@ -0,0 +1,154 @@ +# 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 "$(RUBY_INCLUDE)" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE_EXPORTS" /D NT=1 /D "IMPORT" /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 "$(RUBY_LIB)" /nologo /dll /debug /machine:I386 /out:"example.dll" /pdbtype:sept
+# SUBTRACT LINK32 /pdb:none
+
+!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 "$(RUBY_INCLUDE)" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE_EXPORTS" /D NT=1 /D "IMPORT" /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 "$(RUBY_LIB)" /nologo /dll /machine:I386 /out:"example.dll"
+# SUBTRACT LINK32 /pdb:none
+
+!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 RUBY_INCLUDE: %RUBY_INCLUDE%
+ echo RUBY_LIB: %RUBY_LIB%
+ echo on
+ ..\..\..\swig.exe -c++ -ruby $(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 RUBY_INCLUDE: %RUBY_INCLUDE%
+ echo RUBY_LIB: %RUBY_LIB%
+ echo on
+ ..\..\..\swig.exe -c++ -ruby $(InputPath)
+
+# End Custom Build
+
+!ENDIF
+
+# End Source File
+# End Target
+# End Project
diff --git a/Examples/ruby/free_function/example.h b/Examples/ruby/free_function/example.h new file mode 100644 index 0000000..933bb36 --- /dev/null +++ b/Examples/ruby/free_function/example.h @@ -0,0 +1,49 @@ +#ifndef _EXAMPLE_H_ +#define _EXAMPLE_H_ + +#include <vector> +#include <string> + +class Animal +{ +protected: + std::string name_; +public: + // Construct an animal with a name + Animal(const char* name); + + // Destruct an animal + ~Animal(); + + // Return the animal's name + const char* get_name() const; +}; + +class Zoo +{ +private: + typedef std::vector<Animal*> AnimalsType; + typedef AnimalsType::iterator IterType; +protected: + AnimalsType animals; +public: + Zoo(); + ~Zoo(); + + /* Create a new animal */ + static Animal* create_animal(const char* name); + + /* Add a new animal to the zoo */ + void add_animal(Animal* animal); + + /* Remove an animal from the zoo */ + Animal* remove_animal(size_t i); + + /* Return the number of animals in the zoo */ + size_t get_num_animals() const; + + /* Return a pointer to the ith animal */ + Animal* get_animal(size_t i) const; +}; + +#endif /*_EXAMPLE_H_*/ diff --git a/Examples/ruby/free_function/example.i b/Examples/ruby/free_function/example.i new file mode 100644 index 0000000..a446b3f --- /dev/null +++ b/Examples/ruby/free_function/example.i @@ -0,0 +1,41 @@ +%module example + +%{ +#include "example.h" +%} + +/* Specify that ownership is transferred to the zoo + when calling add_animal */ +%apply SWIGTYPE *DISOWN { Animal* animal }; + +/* Track objects */ +%trackobjects; + +/* Specify the mark function */ +%freefunc Zoo "free_Zoo"; + +%include "example.h" + +%header %{ + static void free_Zoo(void* ptr) { + Zoo* zoo = (Zoo*) ptr; + + /* Loop over each object and call SWIG_RubyRemoveTracking */ + int count = zoo->get_num_animals(); + + for(int i = 0; i < count; ++i) { + /* Get an animal */ + Animal* animal = zoo->get_animal(i); + /* Unlink the Ruby object from the C++ object */ + SWIG_RubyUnlinkObjects(animal); + /* Now remove the tracking for this animal */ + SWIG_RubyRemoveTracking(animal); + } + + /* Now call SWIG_RubyRemoveTracking for the zoo */ + SWIG_RubyRemoveTracking(ptr); + + /* Now free the zoo which will free the animals it contains */ + delete zoo; + } +%} diff --git a/Examples/ruby/free_function/runme.rb b/Examples/ruby/free_function/runme.rb new file mode 100644 index 0000000..1d88b6f --- /dev/null +++ b/Examples/ruby/free_function/runme.rb @@ -0,0 +1,46 @@ +require 'example' + +begin + begin + # Create an animal and zoo + tiger1 = Example::Animal.new("tiger1") + zoo = Example::Zoo.new + + # At the animal to the zoo - this will transfer ownership + # of the underlying C++ object to the C++ zoo object + zoo.add_animal(tiger1) + + # get the id of the tiger + id1 = tiger1.object_id + + # Unset the tiger + tiger1 = nil + end + + # Force a gc + GC.start + + # Get the tiger and its id + tiger2 = zoo.get_animal(0) + id2 = tiger2.object_id + + # The ids should not be the same + if id1==id2 + raise RuntimeError, "Id's should not be the same" + end + + zoo = nil +end + +GC.start + +# This method is no longer valid since the zoo freed the underlying +# C++ object +ok = false +begin + puts tiger2.get_name +rescue ObjectPreviouslyDeleted => error + ok = true +end + +raise(RuntimeError, "Incorrect exception raised - should be ObjectPreviouslyDeleted") unless ok diff --git a/Examples/ruby/funcptr/Makefile b/Examples/ruby/funcptr/Makefile new file mode 100644 index 0000000..8c4fe10 --- /dev/null +++ b/Examples/ruby/funcptr/Makefile @@ -0,0 +1,18 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +SRCS = example.c +TARGET = example +INTERFACE = example.i + +all:: + $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \ + TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' ruby + +static:: + $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \ + TARGET='myruby' INTERFACE='$(INTERFACE)' ruby_static + +clean:: + $(MAKE) -f $(TOP)/Makefile ruby_clean + +check: all diff --git a/Examples/ruby/funcptr/example.c b/Examples/ruby/funcptr/example.c new file mode 100644 index 0000000..99583b7 --- /dev/null +++ b/Examples/ruby/funcptr/example.c @@ -0,0 +1,17 @@ +/* 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; +} diff --git a/Examples/ruby/funcptr/example.h b/Examples/ruby/funcptr/example.h new file mode 100644 index 0000000..9936e24 --- /dev/null +++ b/Examples/ruby/funcptr/example.h @@ -0,0 +1,9 @@ +/* file: example.h */ + +extern int do_op(int,int, int (*op)(int,int)); +extern int add(int,int); +extern int sub(int,int); +extern int mul(int,int); + +extern int (*funcvar)(int,int); + diff --git a/Examples/ruby/funcptr/example.i b/Examples/ruby/funcptr/example.i new file mode 100644 index 0000000..39390da --- /dev/null +++ b/Examples/ruby/funcptr/example.i @@ -0,0 +1,15 @@ +/* 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; + + diff --git a/Examples/ruby/funcptr/index.html b/Examples/ruby/funcptr/index.html new file mode 100644 index 0000000..980106c --- /dev/null +++ b/Examples/ruby/funcptr/index.html @@ -0,0 +1,90 @@ +<html> +<head> +<title>SWIG:Examples:ruby:funcptr</title> +</head> + +<body bgcolor="#ffffff"> + + +<tt>SWIG/Examples/ruby/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.rb">runme.rb</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 Ruby proc object in as a substitute for a C +function pointer. + +<p> +<li>A ruby proc can be used as a C/C++ callback if you write some +clever typemaps and are very careful about how you create your extension. +This is an advanced topic not covered here. +</ul> + +<hr> +</body> +</html> + + + + diff --git a/Examples/ruby/funcptr/runme.rb b/Examples/ruby/funcptr/runme.rb new file mode 100644 index 0000000..4a5b014 --- /dev/null +++ b/Examples/ruby/funcptr/runme.rb @@ -0,0 +1,21 @@ +# file: runme.rb + +require '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 Ruby\n" +print " ADD = #{Example::ADD}\n" +print " SUB = #{Example::SUB}\n" +print " MUL = #{Example::MUL}\n" + diff --git a/Examples/ruby/funcptr2/Makefile b/Examples/ruby/funcptr2/Makefile new file mode 100644 index 0000000..8c4fe10 --- /dev/null +++ b/Examples/ruby/funcptr2/Makefile @@ -0,0 +1,18 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +SRCS = example.c +TARGET = example +INTERFACE = example.i + +all:: + $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \ + TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' ruby + +static:: + $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \ + TARGET='myruby' INTERFACE='$(INTERFACE)' ruby_static + +clean:: + $(MAKE) -f $(TOP)/Makefile ruby_clean + +check: all diff --git a/Examples/ruby/funcptr2/example.c b/Examples/ruby/funcptr2/example.c new file mode 100644 index 0000000..5c4a3da --- /dev/null +++ b/Examples/ruby/funcptr2/example.c @@ -0,0 +1,19 @@ +/* File : example.c */ + +int do_op(int a, int b, int (*op)(int,int)) { + return (*op)(a,b); +} + +int add(int a, int b) { + return a+b; +} + +int sub(int a, int b) { + return a-b; +} + +int mul(int a, int b) { + return a*b; +} + +int (*funcvar)(int,int) = add; diff --git a/Examples/ruby/funcptr2/example.h b/Examples/ruby/funcptr2/example.h new file mode 100644 index 0000000..9936e24 --- /dev/null +++ b/Examples/ruby/funcptr2/example.h @@ -0,0 +1,9 @@ +/* file: example.h */ + +extern int do_op(int,int, int (*op)(int,int)); +extern int add(int,int); +extern int sub(int,int); +extern int mul(int,int); + +extern int (*funcvar)(int,int); + diff --git a/Examples/ruby/funcptr2/example.i b/Examples/ruby/funcptr2/example.i new file mode 100644 index 0000000..681775a --- /dev/null +++ b/Examples/ruby/funcptr2/example.i @@ -0,0 +1,18 @@ +/* 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 */ +%callback("%(upper)s"); +int add(int, int); +int sub(int, int); +int mul(int, int); +%nocallback; + +extern int (*funcvar)(int,int); + diff --git a/Examples/ruby/funcptr2/runme.rb b/Examples/ruby/funcptr2/runme.rb new file mode 100644 index 0000000..99b9842 --- /dev/null +++ b/Examples/ruby/funcptr2/runme.rb @@ -0,0 +1,22 @@ +require 'example' + +a = 37 +b = 42 + +# Now call our C function with a bunch of callbacks + +puts "Trying some C callback functions" +puts " a = #{a}" +puts " b = #{b}" +puts " ADD(a,b) = #{Example.do_op(a,b,Example::ADD)}" +puts " SUB(a,b) = #{Example.do_op(a,b,Example::SUB)}" +puts " MUL(a,b) = #{Example.do_op(a,b,Example::MUL)}" + +puts "Here is what the C callback function objects look like in Ruby" +puts " ADD = #{Example::ADD}" +puts " SUB = #{Example::SUB}" +puts " MUL = #{Example::MUL}" + +puts "Call the functions directly..." +puts " add(a,b) = #{Example.add(a,b)}" +puts " sub(a,b) = #{Example.sub(a,b)}" diff --git a/Examples/ruby/functor/Makefile b/Examples/ruby/functor/Makefile new file mode 100644 index 0000000..730698d --- /dev/null +++ b/Examples/ruby/functor/Makefile @@ -0,0 +1,18 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +TARGET = example +INTERFACE = example.i +LIBS = -lm + +all:: + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' ruby_cpp + +static:: + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + TARGET='myruby' INTERFACE='$(INTERFACE)' ruby_cpp_static + +clean:: + $(MAKE) -f $(TOP)/Makefile ruby_clean + +check: all diff --git a/Examples/ruby/functor/example.i b/Examples/ruby/functor/example.i new file mode 100644 index 0000000..903c978 --- /dev/null +++ b/Examples/ruby/functor/example.i @@ -0,0 +1,26 @@ +/* File : example.i */ +%module example + +%inline %{ +// From B. Strousjoup, "The C++ Programming Language, Third Edition", p. 514 +template<class T> class Sum { + T res; +public: + Sum(T i = 0) : res(i) { } + void operator() (T x) { res += x; } + T result() const { return res; } +}; + +%} + +/** + * Rename the application operator to call() for Ruby. + * Note: this is normally automatic, but if you had to do it yourself + * you would use this directive: + * + * %rename(call) *::operator(); + */ + +// Instantiate a few versions +%template(IntSum) Sum<int>; +%template(DoubleSum) Sum<double>; diff --git a/Examples/ruby/functor/runme.rb b/Examples/ruby/functor/runme.rb new file mode 100644 index 0000000..3f78dce --- /dev/null +++ b/Examples/ruby/functor/runme.rb @@ -0,0 +1,17 @@ +# Operator overloading example +require 'example' + +a = Example::IntSum.new(0) +b = Example::DoubleSum.new(100.0) + +# Use the objects. They should be callable just like a normal +# Ruby function. + +(0..100).each do |i| + a.call(i) # note: function call + b.call(Math.sqrt(i)) # note: function call +end + +puts a.result +puts b.result + diff --git a/Examples/ruby/hashargs/Makefile b/Examples/ruby/hashargs/Makefile new file mode 100644 index 0000000..a2fbbd3 --- /dev/null +++ b/Examples/ruby/hashargs/Makefile @@ -0,0 +1,20 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +SRCS = +TARGET = example +INTERFACE = example.i +LIBS = -lm +SWIGOPT = + +all:: + $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' ruby + +static:: + $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \ + TARGET='myruby' INTERFACE='$(INTERFACE)' ruby_static + +clean:: + $(MAKE) -f $(TOP)/Makefile ruby_clean + +check: all diff --git a/Examples/ruby/hashargs/example.i b/Examples/ruby/hashargs/example.i new file mode 100644 index 0000000..159bbd3 --- /dev/null +++ b/Examples/ruby/hashargs/example.i @@ -0,0 +1,36 @@ +%module example + +%typemap(in) (int nattributes, const char **names, const int *values) (VALUE keys_ary, int i, VALUE key, VALUE val) { + Check_Type($input, T_HASH); + $1 = NUM2INT(rb_funcall($input, rb_intern("size"), 0, NULL)); + $2 = NULL; + $3 = NULL; + if ($1 > 0) { + $2 = (char **) malloc($1*sizeof(char *)); + $3 = (int *) malloc($1*sizeof(int)); + keys_ary = rb_funcall($input, rb_intern("keys"), 0, NULL); + for (i = 0; i < $1; i++) { + key = rb_ary_entry(keys_ary, i); + val = rb_hash_aref($input, key); + Check_Type(key, T_STRING); + Check_Type(val, T_FIXNUM); + $2[i] = STR2CSTR(key); + $3[i] = NUM2INT(val); + } + } +} + +%typemap(freearg) (int nattributes, const char **names, const int *values) { + free((void *) $2); + free((void *) $3); +} + +%inline %{ +void setVitalStats(const char *person, int nattributes, const char **names, const int *values) { + int i; + printf("Name: %s\n", person); + for (i = 0; i < nattributes; i++) { + printf(" %s => %d\n", names[i], values[i]); + } +} +%} diff --git a/Examples/ruby/hashargs/runme.rb b/Examples/ruby/hashargs/runme.rb new file mode 100755 index 0000000..0b06f69 --- /dev/null +++ b/Examples/ruby/hashargs/runme.rb @@ -0,0 +1,26 @@ +require 'example' + +include Example + +# Pass arguments in as one or more key-value pairs +setVitalStats("Fred", + 'age' => 42, + 'weight' => 270 + ) + +# The order doesn't matter +setVitalStats("Sally", + 'age' => 29, + 'weight' => 115, + 'height' => 72 + ) + +# Can also pass a hash directly +params = { + 'ears' => 2, + 'eyes' => 2 +} +setVitalStats("Bob", params) + +# An empty hash is fine too +setVitalStats("Joe", {}) diff --git a/Examples/ruby/import/Makefile b/Examples/ruby/import/Makefile new file mode 100644 index 0000000..acae6e6 --- /dev/null +++ b/Examples/ruby/import/Makefile @@ -0,0 +1,19 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +SWIGOPT = +LIBS = + +all:: + $(MAKE) -f $(TOP)/Makefile SWIG='$(SWIG)' SWIGOPT='$(SWIGOPT)' \ + LIBS='$(LIBS)' TARGET='base' INTERFACE='base.i' ruby_cpp + $(MAKE) -f $(TOP)/Makefile SWIG='$(SWIG)' SWIGOPT='$(SWIGOPT)' \ + LIBS='$(LIBS)' TARGET='foo' INTERFACE='foo.i' ruby_cpp + $(MAKE) -f $(TOP)/Makefile SWIG='$(SWIG)' SWIGOPT='$(SWIGOPT)' \ + LIBS='$(LIBS)' TARGET='bar' INTERFACE='bar.i' ruby_cpp + $(MAKE) -f $(TOP)/Makefile SWIG='$(SWIG)' SWIGOPT='$(SWIGOPT)' \ + LIBS='$(LIBS)' TARGET='spam' INTERFACE='spam.i' ruby_cpp + +clean:: + $(MAKE) -f $(TOP)/Makefile ruby_clean + +check: all diff --git a/Examples/ruby/import/README b/Examples/ruby/import/README new file mode 100644 index 0000000..c529cd9 --- /dev/null +++ b/Examples/ruby/import/README @@ -0,0 +1,39 @@ +This example tests the %import directive and working with multiple modules. + +Use 'ruby runme.rb' 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/Examples/ruby/import/bar.dsp b/Examples/ruby/import/bar.dsp new file mode 100644 index 0000000..29d9abf --- /dev/null +++ b/Examples/ruby/import/bar.dsp @@ -0,0 +1,146 @@ +# 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 "$(RUBY_INCLUDE)" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "BAR_EXPORTS" /D NT=1 /D "IMPORT" /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 "$(RUBY_LIB)" /nologo /dll /debug /machine:I386 /out:"bar.dll" /pdbtype:sept
+# SUBTRACT LINK32 /pdb:none
+
+!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 "$(RUBY_INCLUDE)" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "BAR_EXPORTS" /D NT=1 /D "IMPORT" /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 "$(RUBY_LIB)" /nologo /dll /machine:I386 /out:"bar.dll"
+# SUBTRACT LINK32 /pdb:none
+
+!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 RUBY_INCLUDE: %RUBY_INCLUDE%
+ echo RUBY_LIB: %RUBY_LIB%
+ echo on
+ ..\..\..\swig.exe -c++ -ruby $(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 RUBY_INCLUDE: %RUBY_INCLUDE%
+ echo RUBY_LIB: %RUBY_LIB%
+ echo on
+ ..\..\..\swig.exe -c++ -ruby $(InputPath)
+
+# End Custom Build
+
+!ENDIF
+
+# End Source File
+# End Target
+# End Project
diff --git a/Examples/ruby/import/bar.h b/Examples/ruby/import/bar.h new file mode 100644 index 0000000..1c99f28 --- /dev/null +++ b/Examples/ruby/import/bar.h @@ -0,0 +1,21 @@ +#include "base.h" + +class Bar : public Base { + public: + Bar() { } + ~Bar() { } + virtual const char * A() const { + return "Bar::A"; + } + const char * B() const { + return "Bar::B"; + } + virtual Base *toBase() { + return static_cast<Base *>(this); + } + static Bar *fromBase(Base *b) { + return dynamic_cast<Bar *>(b); + } +}; + + diff --git a/Examples/ruby/import/bar.i b/Examples/ruby/import/bar.i new file mode 100644 index 0000000..5816cbe --- /dev/null +++ b/Examples/ruby/import/bar.i @@ -0,0 +1,9 @@ +%module bar +%{ +#include "bar.h" +%} + +%import base.i +%include "bar.h" + + diff --git a/Examples/ruby/import/base.dsp b/Examples/ruby/import/base.dsp new file mode 100644 index 0000000..174afef --- /dev/null +++ b/Examples/ruby/import/base.dsp @@ -0,0 +1,146 @@ +# 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 "$(RUBY_INCLUDE)" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "BASE_EXPORTS" /D NT=1 /D "IMPORT" /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 "$(RUBY_LIB)" /nologo /dll /debug /machine:I386 /out:"base.dll" /pdbtype:sept
+# SUBTRACT LINK32 /pdb:none
+
+!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 "$(RUBY_INCLUDE)" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "BASE_EXPORTS" /D NT=1 /D "IMPORT" /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 "$(RUBY_LIB)" /nologo /dll /machine:I386 /out:"base.dll"
+# SUBTRACT LINK32 /pdb:none
+
+!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 RUBY_INCLUDE: %RUBY_INCLUDE%
+ echo RUBY_LIB: %RUBY_LIB%
+ echo on
+ ..\..\..\swig.exe -c++ -ruby $(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 RUBY_INCLUDE: %RUBY_INCLUDE%
+ echo RUBY_LIB: %RUBY_LIB%
+ echo on
+ ..\..\..\swig.exe -c++ -ruby $(InputPath)
+
+# End Custom Build
+
+!ENDIF
+
+# End Source File
+# End Target
+# End Project
diff --git a/Examples/ruby/import/base.h b/Examples/ruby/import/base.h new file mode 100644 index 0000000..fec0f32 --- /dev/null +++ b/Examples/ruby/import/base.h @@ -0,0 +1,16 @@ +class Base { + public: + Base() { }; + virtual ~Base() { }; + virtual const char * A() const { + return "Base::A"; + } + const char * B() const { + return "Base::B"; + } + virtual Base *toBase() { + return static_cast<Base *>(this); + } +}; + + diff --git a/Examples/ruby/import/base.i b/Examples/ruby/import/base.i new file mode 100644 index 0000000..f6e19ef --- /dev/null +++ b/Examples/ruby/import/base.i @@ -0,0 +1,6 @@ +%module base +%{ +#include "base.h" +%} + +%include base.h diff --git a/Examples/ruby/import/example.dsw b/Examples/ruby/import/example.dsw new file mode 100644 index 0000000..d395d46 --- /dev/null +++ b/Examples/ruby/import/example.dsw @@ -0,0 +1,65 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "bar"=.\bar.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "base"=.\base.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "foo"=.\foo.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "spam"=.\spam.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/Examples/ruby/import/foo.dsp b/Examples/ruby/import/foo.dsp new file mode 100644 index 0000000..7f47549 --- /dev/null +++ b/Examples/ruby/import/foo.dsp @@ -0,0 +1,146 @@ +# 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 "$(RUBY_INCLUDE)" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FOO_EXPORTS" /D NT=1 /D "IMPORT" /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 "$(RUBY_LIB)" /nologo /dll /debug /machine:I386 /out:"foo.dll" /pdbtype:sept
+# SUBTRACT LINK32 /pdb:none
+
+!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 "$(RUBY_INCLUDE)" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FOO_EXPORTS" /D NT=1 /D "IMPORT" /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 "$(RUBY_LIB)" /nologo /dll /machine:I386 /out:"foo.dll"
+# SUBTRACT LINK32 /pdb:none
+
+!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 RUBY_INCLUDE: %RUBY_INCLUDE%
+ echo RUBY_LIB: %RUBY_LIB%
+ echo on
+ ..\..\..\swig.exe -c++ -ruby $(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 RUBY_INCLUDE: %RUBY_INCLUDE%
+ echo RUBY_LIB: %RUBY_LIB%
+ echo on
+ ..\..\..\swig.exe -c++ -ruby $(InputPath)
+
+# End Custom Build
+
+!ENDIF
+
+# End Source File
+# End Target
+# End Project
diff --git a/Examples/ruby/import/foo.h b/Examples/ruby/import/foo.h new file mode 100644 index 0000000..1abe2c0 --- /dev/null +++ b/Examples/ruby/import/foo.h @@ -0,0 +1,21 @@ +#include "base.h" + +class Foo : public Base { + public: + Foo() { } + ~Foo() { } + virtual const char * A() const { + return "Foo::A"; + } + const char * B() const { + return "Foo::B"; + } + virtual Base *toBase() { + return static_cast<Base *>(this); + } + static Foo *fromBase(Base *b) { + return dynamic_cast<Foo *>(b); + } +}; + + diff --git a/Examples/ruby/import/foo.i b/Examples/ruby/import/foo.i new file mode 100644 index 0000000..27feb2e --- /dev/null +++ b/Examples/ruby/import/foo.i @@ -0,0 +1,8 @@ +%module foo +%{ +#include "foo.h" +%} + +%import base.i +%include "foo.h" + diff --git a/Examples/ruby/import/runme.rb b/Examples/ruby/import/runme.rb new file mode 100644 index 0000000..32ca482 --- /dev/null +++ b/Examples/ruby/import/runme.rb @@ -0,0 +1,90 @@ +# file: runme.rb +# Test various properties of classes defined in separate modules + +puts "Testing the %import directive" + +require 'base' +require 'foo' +require 'bar' +require 'spam' + +# Create some objects + +puts "Creating some objects" + +a = Base::Base.new +b = Foo::Foo.new +c = Bar::Bar.new +d = Spam::Spam.new + +# Try calling some methods +puts "Testing some methods" +puts "Should see 'Base::A' ---> #{a.A}" +puts "Should see 'Base::B' ---> #{a.B}" + +puts "Should see 'Foo::A' ---> #{b.A}" +puts "Should see 'Foo::B' ---> #{b.B}" + +puts "Should see 'Bar::A' ---> #{c.A}" +puts "Should see 'Bar::B' ---> #{c.B}" + +puts "Should see 'Spam::A' ---> #{d.A}" +puts "Should see 'Spam::B' ---> #{d.B}" + +# Try some casts + +puts "\nTesting some casts\n" + +x = a.toBase +puts "Should see 'Base::A' ---> #{x.A}" +puts "Should see 'Base::B' ---> #{x.B}" + +x = b.toBase +puts "Should see 'Foo::A' ---> #{x.A}" +puts "Should see 'Base::B' ---> #{x.B}" + +x = c.toBase +puts "Should see 'Bar::A' ---> #{x.A}" +puts "Should see 'Base::B' ---> #{x.B}" + +x = d.toBase +puts "Should see 'Spam::A' ---> #{x.A}" +puts "Should see 'Base::B' ---> #{x.B}" + +x = d.toBar +puts "Should see 'Bar::B' ---> #{x.B}" + +puts "\nTesting some dynamic casts\n" +x = d.toBase + +puts " Spam -> Base -> Foo : " +y = Foo::Foo.fromBase(x) +if y != nil + puts "bad swig" +else + puts "good swig" +end + +puts " Spam -> Base -> Bar : " +y = Bar::Bar.fromBase(x) +if y != nil + puts "good swig" +else + puts "bad swig" +end + +puts " Spam -> Base -> Spam : " +y = Spam::Spam.fromBase(x) +if y != nil + puts "good swig" +else + puts "bad swig" +end + +puts " Foo -> Spam : " +y = Spam::Spam.fromBase(b) +if y != nil + puts "bad swig" +else + puts "good swig" +end diff --git a/Examples/ruby/import/spam.dsp b/Examples/ruby/import/spam.dsp new file mode 100644 index 0000000..72729f2 --- /dev/null +++ b/Examples/ruby/import/spam.dsp @@ -0,0 +1,146 @@ +# 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 "$(RUBY_INCLUDE)" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SPAM_EXPORTS" /D NT=1 /D "IMPORT" /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 "$(RUBY_LIB)" /nologo /dll /debug /machine:I386 /out:"spam.dll" /pdbtype:sept
+# SUBTRACT LINK32 /pdb:none
+
+!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 "$(RUBY_INCLUDE)" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SPAM_EXPORTS" /D NT=1 /D "IMPORT" /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 "$(RUBY_LIB)" /nologo /dll /machine:I386 /out:"spam.dll"
+# SUBTRACT LINK32 /pdb:none
+
+!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 RUBY_INCLUDE: %RUBY_INCLUDE%
+ echo RUBY_LIB: %RUBY_LIB%
+ echo on
+ ..\..\..\swig.exe -c++ -ruby $(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 RUBY_INCLUDE: %RUBY_INCLUDE%
+ echo RUBY_LIB: %RUBY_LIB%
+ echo on
+ ..\..\..\swig.exe -c++ -ruby $(InputPath)
+
+# End Custom Build
+
+!ENDIF
+
+# End Source File
+# End Target
+# End Project
diff --git a/Examples/ruby/import/spam.h b/Examples/ruby/import/spam.h new file mode 100644 index 0000000..57db845 --- /dev/null +++ b/Examples/ruby/import/spam.h @@ -0,0 +1,24 @@ +#include "bar.h" + +class Spam : public Bar { + public: + Spam() { } + ~Spam() { } + virtual const char * A() const { + return "Spam::A"; + } + const char * B() const { + return "Spam::B"; + } + virtual Base *toBase() { + return static_cast<Base *>(this); + } + virtual Bar *toBar() { + return static_cast<Bar *>(this); + } + static Spam *fromBase(Base *b) { + return dynamic_cast<Spam *>(b); + } +}; + + diff --git a/Examples/ruby/import/spam.i b/Examples/ruby/import/spam.i new file mode 100644 index 0000000..d3d9121 --- /dev/null +++ b/Examples/ruby/import/spam.i @@ -0,0 +1,9 @@ +%module spam +%{ +#include "spam.h" +%} + +%import bar.i +%include "spam.h" + + diff --git a/Examples/ruby/import_template/Makefile b/Examples/ruby/import_template/Makefile new file mode 100644 index 0000000..acae6e6 --- /dev/null +++ b/Examples/ruby/import_template/Makefile @@ -0,0 +1,19 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +SWIGOPT = +LIBS = + +all:: + $(MAKE) -f $(TOP)/Makefile SWIG='$(SWIG)' SWIGOPT='$(SWIGOPT)' \ + LIBS='$(LIBS)' TARGET='base' INTERFACE='base.i' ruby_cpp + $(MAKE) -f $(TOP)/Makefile SWIG='$(SWIG)' SWIGOPT='$(SWIGOPT)' \ + LIBS='$(LIBS)' TARGET='foo' INTERFACE='foo.i' ruby_cpp + $(MAKE) -f $(TOP)/Makefile SWIG='$(SWIG)' SWIGOPT='$(SWIGOPT)' \ + LIBS='$(LIBS)' TARGET='bar' INTERFACE='bar.i' ruby_cpp + $(MAKE) -f $(TOP)/Makefile SWIG='$(SWIG)' SWIGOPT='$(SWIGOPT)' \ + LIBS='$(LIBS)' TARGET='spam' INTERFACE='spam.i' ruby_cpp + +clean:: + $(MAKE) -f $(TOP)/Makefile ruby_clean + +check: all diff --git a/Examples/ruby/import_template/README b/Examples/ruby/import_template/README new file mode 100644 index 0000000..9170a7a --- /dev/null +++ b/Examples/ruby/import_template/README @@ -0,0 +1,30 @@ +This example tests the %import directive and working with multiple modules. + +Use 'ruby runme.rb' 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 + diff --git a/Examples/ruby/import_template/bar.h b/Examples/ruby/import_template/bar.h new file mode 100644 index 0000000..1aa907d --- /dev/null +++ b/Examples/ruby/import_template/bar.h @@ -0,0 +1,22 @@ +#include "base.h" + +template<class T> class Bar : public Base<T> { + public: + Bar() { } + ~Bar() { } + virtual const char * A() const { + return "Bar::A"; + } + const char * B() const { + return "Bar::B"; + } + virtual Base<T> *toBase() { + return static_cast<Base<T> *>(this); + } + static Bar<T> *fromBase(Base<T> *b) { + return dynamic_cast<Bar<T> *>(b); + } + +}; + + diff --git a/Examples/ruby/import_template/bar.i b/Examples/ruby/import_template/bar.i new file mode 100644 index 0000000..357de0d --- /dev/null +++ b/Examples/ruby/import_template/bar.i @@ -0,0 +1,11 @@ +%module bar +%{ +#include "bar.h" +%} + +%import base.i +%include "bar.h" + +%template(IntBar) Bar<int>; + + diff --git a/Examples/ruby/import_template/base.h b/Examples/ruby/import_template/base.h new file mode 100644 index 0000000..e88c440 --- /dev/null +++ b/Examples/ruby/import_template/base.h @@ -0,0 +1,18 @@ +#include <stdio.h> + +template<class T> class Base { + public: + Base() { }; + virtual ~Base() { }; + virtual const char * A() const { + return "Base::A"; + } + const char * B() const { + return "Base::B"; + } + virtual Base<T> *toBase() { + return static_cast<Base<T> *>(this); + } +}; + + diff --git a/Examples/ruby/import_template/base.i b/Examples/ruby/import_template/base.i new file mode 100644 index 0000000..bcf1a5f --- /dev/null +++ b/Examples/ruby/import_template/base.i @@ -0,0 +1,7 @@ +%module base +%{ +#include "base.h" +%} + +%include base.h +%template(IntBase) Base<int>; diff --git a/Examples/ruby/import_template/foo.h b/Examples/ruby/import_template/foo.h new file mode 100644 index 0000000..6262574 --- /dev/null +++ b/Examples/ruby/import_template/foo.h @@ -0,0 +1,21 @@ +#include "base.h" + +template<class T> class Foo : public Base<T> { + public: + Foo() { } + ~Foo() { } + virtual const char * A() const { + return "Foo::A"; + } + const char * B() const { + return "Foo::B"; + } + virtual Base<T> *toBase() { + return static_cast<Base<T> *>(this); + } + static Foo<T> *fromBase(Base<T> *b) { + return dynamic_cast<Foo<T> *>(b); + } +}; + + diff --git a/Examples/ruby/import_template/foo.i b/Examples/ruby/import_template/foo.i new file mode 100644 index 0000000..37e655e --- /dev/null +++ b/Examples/ruby/import_template/foo.i @@ -0,0 +1,10 @@ +%module foo +%{ +#include "foo.h" +%} + +%import base.i +%include "foo.h" + +%template(IntFoo) Foo<int>; + diff --git a/Examples/ruby/import_template/runme.rb b/Examples/ruby/import_template/runme.rb new file mode 100644 index 0000000..b9ca19f --- /dev/null +++ b/Examples/ruby/import_template/runme.rb @@ -0,0 +1,92 @@ +# file: runme.rb +# Test various properties of classes defined in separate modules + +puts "Testing the %import directive with templates" + +require 'base' +require 'foo' +require 'bar' +require 'spam' + +# Create some objects + +puts "Creating some objects" + +a = Base::IntBase.new +b = Foo::IntFoo.new +c = Bar::IntBar.new +d = Spam::IntSpam.new + +# Try calling some methods +puts "Testing some methods" +puts "" +puts "Should see 'Base::A' ---> #{a.A}" +puts "Should see 'Base::B' ---> #{a.B}" + +puts "Should see 'Foo::A' ---> #{b.A}" +puts "Should see 'Foo::B' ---> #{b.B}" + +puts "Should see 'Bar::A' ---> #{c.A}" +puts "Should see 'Bar::B' ---> #{c.B}" + +puts "Should see 'Spam::A' ---> #{d.A}" +puts "Should see 'Spam::B' ---> #{d.B}" + +# Try some casts + +puts "\nTesting some casts\n" +puts "" + +x = a.toBase +puts "Should see 'Base::A' ---> #{x.A}" +puts "Should see 'Base::B' ---> #{x.B}" + +x = b.toBase +puts "Should see 'Foo::A' ---> #{x.A}" +puts "Should see 'Base::B' ---> #{x.B}" + +x = c.toBase +puts "Should see 'Bar::A' ---> #{x.A}" +puts "Should see 'Base::B' ---> #{x.B}" + +x = d.toBase +puts "Should see 'Spam::A' ---> #{x.A}" +puts "Should see 'Base::B' ---> #{x.B}" + +x = d.toBar +puts "Should see 'Bar::B' ---> #{x.B}" + +puts "\nTesting some dynamic casts\n" +x = d.toBase + +puts " Spam -> Base -> Foo : " +y = Foo::IntFoo.fromBase(x) +if y != nil + puts "bad swig" +else + puts "good swig" +end + +puts " Spam -> Base -> Bar : " +y = Bar::IntBar.fromBase(x) +if y != nil + puts "good swig" +else + puts "bad swig" +end + +puts " Spam -> Base -> Spam : " +y = Spam::IntSpam.fromBase(x) +if y != nil + puts "good swig" +else + puts "bad swig" +end + +puts " Foo -> Spam : " +y = Spam::IntSpam.fromBase(b) +if y != nil + puts "bad swig" +else + puts "good swig" +end diff --git a/Examples/ruby/import_template/spam.h b/Examples/ruby/import_template/spam.h new file mode 100644 index 0000000..a27b088 --- /dev/null +++ b/Examples/ruby/import_template/spam.h @@ -0,0 +1,24 @@ +#include "bar.h" + +template<class T> class Spam : public Bar<T> { + public: + Spam() { } + ~Spam() { } + virtual const char * A() const { + return "Spam::A"; + } + const char * B() const { + return "Spam::B"; + } + virtual Base<T> *toBase() { + return static_cast<Base<T> *>(this); + } + virtual Bar<T> *toBar() { + return static_cast<Bar<T> *>(this); + } + static Spam<T> *fromBase(Base<T> *b) { + return dynamic_cast<Spam<T> *>(b); + } +}; + + diff --git a/Examples/ruby/import_template/spam.i b/Examples/ruby/import_template/spam.i new file mode 100644 index 0000000..ff0ca11 --- /dev/null +++ b/Examples/ruby/import_template/spam.i @@ -0,0 +1,10 @@ +%module spam +%{ +#include "spam.h" +%} + +%import bar.i +%include "spam.h" + +%template(IntSpam) Spam<int>; + diff --git a/Examples/ruby/index.html b/Examples/ruby/index.html new file mode 100644 index 0000000..f04146e --- /dev/null +++ b/Examples/ruby/index.html @@ -0,0 +1,94 @@ + +<head> +<title>SWIG:Examples:ruby</title> +</head> + +<body bgcolor="#ffffff"> +<H1>SWIG Ruby Examples</H1> + +<p> +The following examples illustrate the use of SWIG with Ruby. + +<ul> +<li><a href="simple/index.html">simple</a>. A minimal example showing how SWIG can +be used to wrap a C function, a global variable, and a constant. +<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>. An example showing how to access C global variables from Ruby. +<li><a href="value/index.html">value</a>. How to pass and return structures by value. +<li><a href="class/index.html">class</a>. Wrapping 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. +<li><a href="enum/index.html">enum</a>. Enumeration. +</ul> + +<h2>Compilation Issues</h2> + +<ul> +<li>To create a Ruby extension, SWIG is run with the following options: + +<blockquote> +<pre> +% swig -ruby interface.i +</pre> +</blockquote> + +<li> +Please see the <a href="../../Doc/Manual/Windows.html">Windows</a> page in the main manual for information on using the examples on Windows. <p> +</li> + +<li>On Unix 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 -ruby interface.i +% gcc -fpic -c interface_wrap.c -I/usr/local/lib/ruby/1.4/i686-linux +% gcc -shared interface_wrap.o $(OBJS) -o interface.so +% ruby +require 'interface' +Interface.blah(...) +... +</pre> +</blockquote> + +<li>The politically "correct" way to compile a Ruby extension is to follow the steps +described <tt>README.EXT</tt> in Ruby distribution: + +<p> +<ol> +<li>Create a file called <tt>extconf.rb</tt> that looks like the following: + +<blockquote> +<pre> +require 'mkmf' +create_makefile('interface') +</pre> +</blockquote> +<li>Type the following to build the extension: + +<blockquote> +<pre> +% ruby extconf.rb +% make +</pre> +</blockquote> +</ol> +</ul> + +<h2>Compatibility</h2> + +The examples have been extensively tested on the following platforms: + +<ul> +<li>Linux +</ul> + +Your mileage may vary. If you experience a problem, please let us know by +contacting us on the <a href="http://www.swig.org/mail.html">mailing lists</a>. +</body> +</html> + + diff --git a/Examples/ruby/java/Example.java b/Examples/ruby/java/Example.java new file mode 100644 index 0000000..91ddb1a --- /dev/null +++ b/Examples/ruby/java/Example.java @@ -0,0 +1,29 @@ +public class Example { + public int mPublicInt; + + public Example() { + mPublicInt = 0; + } + + public Example(int IntVal) { + mPublicInt = IntVal; + } + + + public int Add(int a, int b) { + return (a+b); + } + + public float Add(float a, float b) { + return (a+b); + } + + public String Add(String a, String b) { + return (a+b); + } + + public Example Add(Example a, Example b) { + return new Example(a.mPublicInt + b.mPublicInt); + } +} + diff --git a/Examples/ruby/java/Makefile b/Examples/ruby/java/Makefile new file mode 100644 index 0000000..e525d88 --- /dev/null +++ b/Examples/ruby/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" LIBS="-lstdc++" DEFS='' ruby_cpp + + +clean:: + $(MAKE) -f $(TOP)/Makefile python_clean + rm -f *.class Example.h + +check: all + +run: + ruby runme.rb + +Example.class: Example.java + gcj -fPIC -C -c -g Example.java + gcjh Example + diff --git a/Examples/ruby/java/example.i b/Examples/ruby/java/example.i new file mode 100644 index 0000000..13d5b5e --- /dev/null +++ b/Examples/ruby/java/example.i @@ -0,0 +1,9 @@ +%module example +%include <cni.i> + +%{ +#include "Example.h" +%} + + +%include Example.h diff --git a/Examples/ruby/java/runme.rb b/Examples/ruby/java/runme.rb new file mode 100644 index 0000000..fc018b7 --- /dev/null +++ b/Examples/ruby/java/runme.rb @@ -0,0 +1,18 @@ +require 'example' + +Example.JvCreateJavaVM(nil) +Example.JvAttachCurrentThread(nil, nil) + +e1 = Example::Example.new(1) +e2 = Example::Example.new(2) + +print e1.Add(1,2),"\n" +print e1.Add(1.0,2.0),"\n" +e3 = e1.Add(e1,e2) +print e3.mPublicInt,"\n" + + +print e1.Add("1","2"),"\n" + +Example.JvDetachCurrentThread() + diff --git a/Examples/ruby/mark_function/Makefile b/Examples/ruby/mark_function/Makefile new file mode 100644 index 0000000..56c84c6 --- /dev/null +++ b/Examples/ruby/mark_function/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)' ruby_cpp + +static:: + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + TARGET='myruby' INTERFACE='$(INTERFACE)' ruby_cpp_static + +clean:: + $(MAKE) -f $(TOP)/Makefile ruby_clean + +check: all diff --git a/Examples/ruby/mark_function/example.cxx b/Examples/ruby/mark_function/example.cxx new file mode 100644 index 0000000..504e8fc --- /dev/null +++ b/Examples/ruby/mark_function/example.cxx @@ -0,0 +1,61 @@ +#include "example.h" + +Animal::Animal(const char* name) : name_(name) +{ +} + +Animal::~Animal() +{ + name_ = "Destroyed"; +} + +/* Return the animal's name */ +const char* Animal::get_name() const +{ + return name_.c_str(); +} + +Zoo::Zoo() +{ +} + +Zoo::~Zoo() +{ + return; +} + +/* Create a new animal. */ +Animal* Zoo::create_animal(const char* name) +{ + return new Animal(name); +} + +/* Add a new animal to the zoo. */ +void Zoo::add_animal(Animal* animal) +{ + animals.push_back(animal); +} + +Animal* Zoo::remove_animal(size_t i) +{ + /* Note a production implementation should check + for out of range errors. */ + Animal* result = this->animals[i]; + IterType iter = this->animals.begin(); + std::advance(iter, i); + this->animals.erase(iter); + + return result; +} + +/* Return the number of animals in the zoo. */ +size_t Zoo::get_num_animals() const +{ + return animals.size(); +} + +/* Return a pointer to the ith animal */ +Animal* Zoo::get_animal(size_t i) const +{ + return animals[i]; +} diff --git a/Examples/ruby/mark_function/example.dsp b/Examples/ruby/mark_function/example.dsp new file mode 100644 index 0000000..2adab78 --- /dev/null +++ b/Examples/ruby/mark_function/example.dsp @@ -0,0 +1,154 @@ +# 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 "$(RUBY_INCLUDE)" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE_EXPORTS" /D NT=1 /D "IMPORT" /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 "$(RUBY_LIB)" /nologo /dll /debug /machine:I386 /out:"example.dll" /pdbtype:sept
+# SUBTRACT LINK32 /pdb:none
+
+!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 "$(RUBY_INCLUDE)" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE_EXPORTS" /D NT=1 /D "IMPORT" /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 "$(RUBY_LIB)" /nologo /dll /machine:I386 /out:"example.dll"
+# SUBTRACT LINK32 /pdb:none
+
+!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 RUBY_INCLUDE: %RUBY_INCLUDE%
+ echo RUBY_LIB: %RUBY_LIB%
+ echo on
+ ..\..\..\swig.exe -c++ -ruby $(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 RUBY_INCLUDE: %RUBY_INCLUDE%
+ echo RUBY_LIB: %RUBY_LIB%
+ echo on
+ ..\..\..\swig.exe -c++ -ruby $(InputPath)
+
+# End Custom Build
+
+!ENDIF
+
+# End Source File
+# End Target
+# End Project
diff --git a/Examples/ruby/mark_function/example.h b/Examples/ruby/mark_function/example.h new file mode 100644 index 0000000..933bb36 --- /dev/null +++ b/Examples/ruby/mark_function/example.h @@ -0,0 +1,49 @@ +#ifndef _EXAMPLE_H_ +#define _EXAMPLE_H_ + +#include <vector> +#include <string> + +class Animal +{ +protected: + std::string name_; +public: + // Construct an animal with a name + Animal(const char* name); + + // Destruct an animal + ~Animal(); + + // Return the animal's name + const char* get_name() const; +}; + +class Zoo +{ +private: + typedef std::vector<Animal*> AnimalsType; + typedef AnimalsType::iterator IterType; +protected: + AnimalsType animals; +public: + Zoo(); + ~Zoo(); + + /* Create a new animal */ + static Animal* create_animal(const char* name); + + /* Add a new animal to the zoo */ + void add_animal(Animal* animal); + + /* Remove an animal from the zoo */ + Animal* remove_animal(size_t i); + + /* Return the number of animals in the zoo */ + size_t get_num_animals() const; + + /* Return a pointer to the ith animal */ + Animal* get_animal(size_t i) const; +}; + +#endif /*_EXAMPLE_H_*/ diff --git a/Examples/ruby/mark_function/example.i b/Examples/ruby/mark_function/example.i new file mode 100644 index 0000000..6380fa0 --- /dev/null +++ b/Examples/ruby/mark_function/example.i @@ -0,0 +1,37 @@ +%module example + +%{ +#include "example.h" +%} + +/* Tell SWIG that create_animal creates a new object */ +%newobject Zoo::create_animal; + +/* Keep track of mappings between C/C++ structs/classes + and Ruby objects so we can implement a mark function. */ +%trackobjects; + + +/* Specify the mark function */ +%markfunc Zoo "mark_Zoo"; + +%include "example.h" + +%header %{ + static void mark_Zoo(void* ptr) { + Zoo* zoo = (Zoo*) ptr; + + /* Loop over each object and tell the garbage collector + that we are holding a reference to them. */ + int count = zoo->get_num_animals(); + + for(int i = 0; i < count; ++i) { + Animal* animal = zoo->get_animal(i); + VALUE object = SWIG_RubyInstanceFor(animal); + + if (object != Qnil) { + rb_gc_mark(object); + } + } + } +%} diff --git a/Examples/ruby/mark_function/runme.rb b/Examples/ruby/mark_function/runme.rb new file mode 100644 index 0000000..6d84ee8 --- /dev/null +++ b/Examples/ruby/mark_function/runme.rb @@ -0,0 +1,23 @@ +require 'example' + +# create a zoo +zoo = Example::Zoo.new + +begin + # Add in an couple of animals + tiger1 = Example::Animal.new("tiger1") + zoo.add_animal(tiger1) + + # unset variables to force gc + tiger = nil +end + +GC.start + +# Now get the tiger again +tiger2 = zoo.get_animal(0) + +# Call a method to verify the animal is still valid and not gc'ed +if tiger2.get_name != "tiger1" + raise RuntimeError, "Wrong animal name" +end diff --git a/Examples/ruby/multimap/Makefile b/Examples/ruby/multimap/Makefile new file mode 100644 index 0000000..8c4fe10 --- /dev/null +++ b/Examples/ruby/multimap/Makefile @@ -0,0 +1,18 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +SRCS = example.c +TARGET = example +INTERFACE = example.i + +all:: + $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \ + TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' ruby + +static:: + $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \ + TARGET='myruby' INTERFACE='$(INTERFACE)' ruby_static + +clean:: + $(MAKE) -f $(TOP)/Makefile ruby_clean + +check: all diff --git a/Examples/ruby/multimap/example.c b/Examples/ruby/multimap/example.c new file mode 100644 index 0000000..b8360fa --- /dev/null +++ b/Examples/ruby/multimap/example.c @@ -0,0 +1,53 @@ +/* File : example.c */ +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> + +/* Compute the greatest common divisor of positive integers */ +int gcd(int x, int y) { + int g; + g = y; + while (x > 0) { + g = x; + x = y % x; + y = g; + } + return g; +} + +int gcdmain(int argc, char *argv[]) { + int x,y; + if (argc != 3) { + printf("usage: gcd x y\n"); + return -1; + } + x = atoi(argv[1]); + y = atoi(argv[2]); + printf("gcd(%d,%d) = %d\n", x,y,gcd(x,y)); + return 0; +} + +int count(char *bytes, int len, char c) { + int i; + int count = 0; + for (i = 0; i < len; i++) { + if (bytes[i] == c) count++; + } + return count; +} + +void capitalize(char *str, int len) { + int i; + for (i = 0; i < len; i++) { + str[i] = (char)toupper(str[i]); + } +} + +void circle(double x, double y) { + double a = x*x + y*y; + if (a > 1.0) { + printf("Bad points %g, %g\n", x,y); + } else { + printf("Good points %g, %g\n", x,y); + } +} diff --git a/Examples/ruby/multimap/example.dsp b/Examples/ruby/multimap/example.dsp new file mode 100644 index 0000000..4888299 --- /dev/null +++ b/Examples/ruby/multimap/example.dsp @@ -0,0 +1,150 @@ +# 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 "$(RUBY_INCLUDE)" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE_EXPORTS" /D NT=1 /D "IMPORT" /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 "$(RUBY_LIB)" /nologo /dll /debug /machine:I386 /out:"example.dll" /pdbtype:sept
+# SUBTRACT LINK32 /pdb:none
+
+!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 "$(RUBY_INCLUDE)" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE_EXPORTS" /D NT=1 /D "IMPORT" /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 "$(RUBY_LIB)" /nologo /dll /machine:I386 /out:"example.dll"
+# SUBTRACT LINK32 /pdb:none
+
+!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 RUBY_INCLUDE: %RUBY_INCLUDE%
+ echo RUBY_LIB: %RUBY_LIB%
+ echo on
+ ..\..\..\swig.exe -ruby $(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 RUBY_INCLUDE: %RUBY_INCLUDE%
+ echo RUBY_LIB: %RUBY_LIB%
+ echo on
+ ..\..\..\swig.exe -ruby $(InputPath)
+
+# End Custom Build
+
+!ENDIF
+
+# End Source File
+# End Target
+# End Project
diff --git a/Examples/ruby/multimap/example.i b/Examples/ruby/multimap/example.i new file mode 100644 index 0000000..56952ec --- /dev/null +++ b/Examples/ruby/multimap/example.i @@ -0,0 +1,92 @@ +%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(in) (int argc, char *argv[]) { + int i; + + if (TYPE($input) != T_ARRAY) { + SWIG_exception(SWIG_ValueError, "Expected an array"); + } + $1 = RARRAY($input)->len; + if ($1 == 0) { + SWIG_exception(SWIG_ValueError, "List must contain at least 1 element"); + } + $2 = (char **) malloc(($1+1)*sizeof(char *)); + for (i = 0; i < $1; i++) { + VALUE s = rb_ary_entry($input,i); + if (TYPE(s) != T_STRING) { + free($2); + SWIG_exception(SWIG_ValueError, "List items must be strings"); + } + $2[i] = STR2CSTR(s); + } + $2[i] = 0; +} + +%typemap(freearg) (int argc, char *argv[]) { + free($2); +} + +extern int gcdmain(int argc, char *argv[]); + +%typemap(in) (char *bytes, int len) { + if (TYPE($input) != T_STRING) { + SWIG_exception(SWIG_ValueError, "Expected a string"); + } + $1 = STR2CSTR($input); + $2 = RSTRING($input)->len; +} + +extern int count(char *bytes, int len, char c); + + +/* This example shows how to wrap a function that mutates a string */ + +%typemap(in) (char *str, int len) { + char *temp; + if (TYPE($input) != T_STRING) { + SWIG_exception(SWIG_ValueError,"Expected a string"); + } + temp = STR2CSTR($input); + $2 = RSTRING($input)->len; + $1 = (char *) malloc($2+1); + memmove($1,temp,$2); +} + +/* Return the mutated string as a new object. */ + +%typemap(argout, fragment="output_helper") (char *str, int len) { + VALUE o; + o = rb_str_new($1,$2); + $result = output_helper($result,o); + free($1); +} + +extern void capitalize(char *str, int len); + +/* A multi-valued constraint. Force two arguments to lie + inside the unit circle */ + +%typemap(check) (double cx, double cy) { + double a = $1*$1 + $2*$2; + if (a > 1.0) { + SWIG_exception(SWIG_ValueError,"$1_name and $2_name must be in unit circle"); + } +} + +extern void circle(double cx, double cy); + + diff --git a/Examples/ruby/multimap/runme.rb b/Examples/ruby/multimap/runme.rb new file mode 100755 index 0000000..dde8351 --- /dev/null +++ b/Examples/ruby/multimap/runme.rb @@ -0,0 +1,22 @@ +# file: runme.rb + +require 'example' + +# Call our gcd() function + +x = 42 +y = 105 +g = Example.gcd(x,y) +printf "The gcd of %d and %d is %d\n",x,y,g + +# Call the gcdmain() function +Example.gcdmain(["gcdmain","42","105"]) + +# Call the count function + +printf "%d\n",Example.count("Hello World","l") + +# Call the capitalize function + +printf "%s\n",Example.capitalize("hello world") + diff --git a/Examples/ruby/operator/Makefile b/Examples/ruby/operator/Makefile new file mode 100644 index 0000000..4c16edb --- /dev/null +++ b/Examples/ruby/operator/Makefile @@ -0,0 +1,20 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +CXXSRCS = +TARGET = example +INTERFACE = example.i +LIBS = -lm +SWIGOPT = + +all:: + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' ruby_cpp + +static:: + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + TARGET='myruby' INTERFACE='$(INTERFACE)' ruby_cpp_static + +clean:: + $(MAKE) -f $(TOP)/Makefile ruby_clean + +check: all diff --git a/Examples/ruby/operator/example.h b/Examples/ruby/operator/example.h new file mode 100644 index 0000000..4da6a23 --- /dev/null +++ b/Examples/ruby/operator/example.h @@ -0,0 +1,36 @@ +/* File : example.h */ +#include <math.h> + +class Complex { +private: + double rpart, ipart; +public: + Complex(double r = 0, double i = 0) : rpart(r), ipart(i) { } + Complex(const Complex &c) : rpart(c.rpart), ipart(c.ipart) { } + Complex &operator=(const Complex &c) { + rpart = c.rpart; + ipart = c.ipart; + return *this; + } + Complex operator+(const Complex &c) const { + return Complex(rpart+c.rpart, ipart+c.ipart); + } + Complex operator-(const Complex &c) const { + return Complex(rpart-c.rpart, ipart-c.ipart); + } + Complex operator*(const Complex &c) const { + return Complex(rpart*c.rpart - ipart*c.ipart, + rpart*c.ipart + c.rpart*ipart); + } + Complex operator-() const { + return Complex(-rpart, -ipart); + } + + double re() const { return rpart; } + double im() const { return ipart; } +}; + + + + + diff --git a/Examples/ruby/operator/example.i b/Examples/ruby/operator/example.i new file mode 100644 index 0000000..b7e013f --- /dev/null +++ b/Examples/ruby/operator/example.i @@ -0,0 +1,26 @@ +/* File : example.i */ +%module example + +%warnfilter(SWIGWARN_IGNORE_OPERATOR_EQ); + + +%{ +#include "example.h" +%} + +/* This header file is a little tough to handle because it has overloaded + operators and constructors. We're going to try and deal with that here */ + +/* Grab the original header file */ +%include "example.h" + +/* An output method that turns a complex into a short string */ +%extend Complex { + char *__str__() { + static char temp[512]; + sprintf(temp,"(%g,%g)", $self->re(), $self->im()); + return temp; + } +}; + + diff --git a/Examples/ruby/operator/runme.rb b/Examples/ruby/operator/runme.rb new file mode 100644 index 0000000..518d91e --- /dev/null +++ b/Examples/ruby/operator/runme.rb @@ -0,0 +1,25 @@ +# Operator overloading example +require 'example' + +include Example + +a = Complex.new(2, 3) +b = Complex.new(-5, 10) + +puts "a = #{a}" +puts "b = #{b}" + +c = a + b +puts "c = #{c}" +puts "a*b = #{a*b}" +puts "a-c = #{a-c}" + +# This should invoke Complex's copy constructor +e = Complex.new(a-c) +e = a - c +puts "e = #{e}" + +# Big expression +f = ((a+b)*(c+b*e)) + (-a) +puts "f = #{f}" + diff --git a/Examples/ruby/overloading/Makefile b/Examples/ruby/overloading/Makefile new file mode 100644 index 0000000..56c84c6 --- /dev/null +++ b/Examples/ruby/overloading/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)' ruby_cpp + +static:: + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + TARGET='myruby' INTERFACE='$(INTERFACE)' ruby_cpp_static + +clean:: + $(MAKE) -f $(TOP)/Makefile ruby_clean + +check: all diff --git a/Examples/ruby/overloading/example.cxx b/Examples/ruby/overloading/example.cxx new file mode 100644 index 0000000..49d998d --- /dev/null +++ b/Examples/ruby/overloading/example.cxx @@ -0,0 +1,125 @@ +#include <iostream> + +#include "example.h" + +// Overloaded constructors for class Bar +Bar::Bar() { + std::cout << "Called Bar::Bar()" << std::endl; +} + +Bar::Bar(const Bar&) { + std::cout << "Called Bar::Bar(const Bar&)" << std::endl; +} + +Bar::Bar(double x) { + std::cout << "Called Bar::Bar(double) with x = " << x << std::endl; +} + +Bar::Bar(double x, char *y) { + std::cout << "Called Bar::Bar(double, char *) with x, y = " << x << ", \"" << y << "\"" << std::endl; +} + +Bar::Bar(int x, int y) { + std::cout << "Called Bar::Bar(int, int) with x, y = " << x << ", " << y << std::endl; +} + +Bar::Bar(char *x) { + std::cout << "Called Bar::Bar(char *) with x = \"" << x << "\"" << std::endl; +} + +Bar::Bar(int x) { + std::cout << "Called Bar::Bar(int) with x = " << x << std::endl; +} + +Bar::Bar(long x) { + std::cout << "Called Bar::Bar(long) with x = " << x << std::endl; +} + +Bar::Bar(Bar *x) { + std::cout << "Called Bar::Bar(Bar *) with x = " << x << std::endl; +} + +// Overloaded member functions +void Bar::foo(const Bar& x) { + std::cout << "Called Bar::foo(const Bar&) with &x = " << &x << std::endl; +} + +void Bar::foo(double x) { + std::cout << "Called Bar::foo(double) with x = " << x << std::endl; +} + +void Bar::foo(double x, char *y) { + std::cout << "Called Bar::foo(double, char *) with x, y = " << x << ", \"" << y << "\"" << std::endl; +} + +void Bar::foo(int x, int y) { + std::cout << "Called Bar::foo(int, int) with x, y = " << x << ", " << y << std::endl; +} + +void Bar::foo(char *x) { + std::cout << "Called Bar::foo(char *) with x = \"" << x << "\"" << std::endl; +} + +void Bar::foo(int x) { + std::cout << "Called Bar::foo(int) with x = " << x << std::endl; +} + +void Bar::foo(long x) { + std::cout << "Called Bar::foo(long) with x = " << x << std::endl; +} + +void Bar::foo(Bar *x) { + std::cout << "Called Bar::foo(Bar *) with x = " << x << std::endl; +} + +void Bar::spam(int x, int y, int z) { + std::cout << "Called Bar::spam(int, int, int) with x, y, z = " << x << ", " << y << ", " << z << std::endl; +} + +void Bar::spam(double x, int y, int z) { + std::cout << "Called Bar::spam(double, int, int) with x, y, z = " << x << ", " << y << ", " << z << std::endl; +} + +// Overloaded global methods +void foo(const Bar& x) { + std::cout << "Called foo(const Bar& x) with &x = " << &x << std::endl; +} + +void foo(double x) { + std::cout << "Called foo(double) with x = " << x << std::endl; +} + +void foo(double x, char *y) { + std::cout << "Called foo(double, char *) with x, y = " << x << ", \"" << y << "\"" << std::endl; +} + +void foo(int x, int y) { + std::cout << "Called foo(int, int) with x, y = " << x << ", " << y << std::endl; +} + +void foo(char *x) { + std::cout << "Called foo(char *) with x = \"" << x << "\"" << std::endl; +} + +void foo(int x) { + std::cout << "Called foo(int) with x = " << x << std::endl; +} + +void foo(long x) { + std::cout << "Called foo(long) with x = " << x << std::endl; +} + +void foo(Bar *x) { + std::cout << "Called foo(Bar *) with x = " << x << std::endl; +} + +// Overloaded global spam() functions +void spam(int x, int y, int z) { + std::cout << "Called spam(int, int, int) with x, y, z = " << x << ", " << y << ", " << z << std::endl; +} + +void spam(double x, int y, int z) { + std::cout << "Called spam(double, int, int) with x, y, z = " << x << ", " << y << ", " << z << std::endl; +} + + diff --git a/Examples/ruby/overloading/example.h b/Examples/ruby/overloading/example.h new file mode 100644 index 0000000..e47a122 --- /dev/null +++ b/Examples/ruby/overloading/example.h @@ -0,0 +1,41 @@ +#ifndef EXAMPLE_H +#define EXAMPLE_H + +class Bar { +public: + Bar(); + Bar(const Bar&); + Bar(double); + Bar(double, char *); + Bar(int, int); + Bar(char *); + Bar(long); + Bar(int); + Bar(Bar *); + + void foo(const Bar&); + void foo(double); + void foo(double, char *); + void foo(int, int); + void foo(char *); + void foo(long); + void foo(int); + void foo(Bar *); + + void spam(int x, int y=2, int z=3); + void spam(double x, int y=2, int z=3); +}; + +void foo(const Bar&); +void foo(double); +void foo(double, char *); +void foo(int, int); +void foo(char *); +void foo(int); +void foo(long); +void foo(Bar *); + +void spam(int x, int y=2, int z=3); +void spam(double x, int y=2, int z=3); + +#endif diff --git a/Examples/ruby/overloading/example.i b/Examples/ruby/overloading/example.i new file mode 100644 index 0000000..17ad669 --- /dev/null +++ b/Examples/ruby/overloading/example.i @@ -0,0 +1,24 @@ +%module example + +%{ +#include "example.h" +%} + +/** + * These overloaded declarations conflict with other overloads (as far as + * SWIG's Ruby module's implementation for overloaded methods is concerned). + * One option is use the %rename directive to rename the conflicting methods; + * here, we're just using %ignore to avoid wrapping some of the overloaded + * functions altogether. + */ + +%ignore Bar::Bar(Bar *); +%ignore Bar::Bar(long); + +%ignore Bar::foo(const Bar&); +%ignore Bar::foo(long); + +%ignore ::foo(const Bar&); +%ignore ::foo(int); + +%include example.h diff --git a/Examples/ruby/overloading/runme.rb b/Examples/ruby/overloading/runme.rb new file mode 100644 index 0000000..9f12333 --- /dev/null +++ b/Examples/ruby/overloading/runme.rb @@ -0,0 +1,88 @@ +require 'example' + +# This should invoke foo(double) +Example.foo(3.14159) + +# This should invoke foo(double, char *) +Example.foo(3.14159, "Pi") + +# This should invoke foo(int, int) +Example.foo(3, 4) + +# This should invoke foo(char *) +Example.foo("This is a test") + +# This should invoke foo(long) +Example.foo(42) + +# This should invoke Bar::Bar() followed by foo(Bar *) +Example.foo(Example::Bar.new) + +# Skip a line +puts "" + +# Each of the following three calls should invoke spam(int, int, int) +Example.spam(3) +Example.spam(3, 4) +Example.spam(3, 4, 5) + +# Skip a line +puts "" + +# Each of the following three calls should invoke spam(double, int, int) +Example.spam(3.0) +Example.spam(3.0, 4) +Example.spam(3.0, 4, 5) + +# Skip a line +puts "" + +# This should invoke Bar::Bar(double) +Example::Bar.new(3.14159) + +# This should invoke Bar::Bar(double, char *) +Example::Bar.new(3.14159, "Pi") + +# This should invoke Bar::Bar(int, int) +Example::Bar.new(3, 4) + +# This should invoke Bar::Bar(char *) +Example::Bar.new("This is a test") + +# This should invoke Bar::Bar(int) +Example::Bar.new(42) + +# This should invoke Bar::Bar() for the input argument, +# followed by Bar::Bar(const Bar&). +Example::Bar.new(Example::Bar.new) + +# Skip a line +puts "" + +# Construct a new Bar instance (invokes Bar::Bar()) +bar = Example::Bar.new + +# This should invoke Bar::foo(double) +bar.foo(3.14159) + +# This should invoke Bar::foo(double, char *) +bar.foo(3.14159, "Pi") + +# This should invoke Bar::foo(int, int) +bar.foo(3, 4) + +# This should invoke Bar::foo(char *) +bar.foo("This is a test") + +# This should invoke Bar::foo(int) +bar.foo(42) + +# This should invoke Bar::Bar() to construct the input +# argument, followed by Bar::foo(Bar *). +bar.foo(Example::Bar.new) + +# This should invoke Bar::spam(int x, int y, int z) +bar.spam(1) + +# This should invoke Bar::spam(double x, int y, int z) +bar.spam(3.14159) diff --git a/Examples/ruby/pointer/Makefile b/Examples/ruby/pointer/Makefile new file mode 100644 index 0000000..8c4fe10 --- /dev/null +++ b/Examples/ruby/pointer/Makefile @@ -0,0 +1,18 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +SRCS = example.c +TARGET = example +INTERFACE = example.i + +all:: + $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \ + TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' ruby + +static:: + $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \ + TARGET='myruby' INTERFACE='$(INTERFACE)' ruby_static + +clean:: + $(MAKE) -f $(TOP)/Makefile ruby_clean + +check: all diff --git a/Examples/ruby/pointer/example.c b/Examples/ruby/pointer/example.c new file mode 100644 index 0000000..b877d9a --- /dev/null +++ b/Examples/ruby/pointer/example.c @@ -0,0 +1,16 @@ +/* File : example.c */ + +void add(int *x, int *y, int *result) { + *result = *x + *y; +} + +void sub(int *x, int *y, int *result) { + *result = *x - *y; +} + +int divide(int n, int d, int *r) { + int q; + q = n/d; + *r = n - q*d; + return q; +} diff --git a/Examples/ruby/pointer/example.i b/Examples/ruby/pointer/example.i new file mode 100644 index 0000000..a8ac794 --- /dev/null +++ b/Examples/ruby/pointer/example.i @@ -0,0 +1,30 @@ +/* File : example.i */ +%module example + +%{ +extern void add(int *, int *, int *); +extern void sub(int *, int *, int *); +extern int divide(int, int, int *); +%} + +/* This example illustrates a couple of different techniques + for manipulating C pointers */ + +/* First we'll use the pointer library */ +extern void add(int *x, int *y, int *result); +%include cpointer.i +%pointer_functions(int, intp); + +/* Next we'll use some typemaps */ + +%include typemaps.i +extern void sub(int *INPUT, int *INPUT, int *OUTPUT); + +/* Next we'll use typemaps and the %apply directive */ + +%apply int *OUTPUT { int *r }; +extern int divide(int n, int d, int *r); + + + + diff --git a/Examples/ruby/pointer/index.html b/Examples/ruby/pointer/index.html new file mode 100644 index 0000000..2b9c40b --- /dev/null +++ b/Examples/ruby/pointer/index.html @@ -0,0 +1,171 @@ +<html> +<head> +<title>SWIG:Examples:ruby:pointer</title> +</head> + +<body bgcolor="#ffffff"> + +<tt>SWIG/Examples/ruby/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 sub(int *x, int *y, int *r); +void mul(int *x, int *y, int *r); +... etc ... +</pre> +</blockquote> + +</ul> + +<h2>Example</h2> + +The following example illustrates the use of these features for pointer +extraction. + +<ul> +<li> <a href="example.c">example.c</a> (C Source) +<li> <a href="example.i">example.i</a> (Swig interface) +<li> <a href="runme.rb">runme.rb</a> (Ruby Script) +</ul> + +<h2>Notes</h2> + +<ul> +<li>Since pointers are used for so many different things (arrays, output values, +etc...) the complexity of pointer handling can be as complicated as you want to +make it. + +<p> +<li>More documentation on the typemaps.i and pointer.i library files can be +found in the SWIG user manual. The files also contain documentation. + +<p> +<li>The pointer.i library is designed primarily for convenience. If you +are concerned about performance, you probably want to use a different +approach. + +</ul> + +<hr> +</body> +</html> diff --git a/Examples/ruby/pointer/runme.rb b/Examples/ruby/pointer/runme.rb new file mode 100644 index 0000000..d696b02 --- /dev/null +++ b/Examples/ruby/pointer/runme.rb @@ -0,0 +1,45 @@ +# file: runme.rb + +require '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::sub(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/Examples/ruby/reference/Makefile b/Examples/ruby/reference/Makefile new file mode 100644 index 0000000..56c84c6 --- /dev/null +++ b/Examples/ruby/reference/Makefile @@ -0,0 +1,19 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +CXXSRCS = example.cxx +TARGET = example +INTERFACE = example.i +LIBS = -lm + +all:: + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' ruby_cpp + +static:: + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + TARGET='myruby' INTERFACE='$(INTERFACE)' ruby_cpp_static + +clean:: + $(MAKE) -f $(TOP)/Makefile ruby_clean + +check: all diff --git a/Examples/ruby/reference/example.cxx b/Examples/ruby/reference/example.cxx new file mode 100644 index 0000000..8a513bf --- /dev/null +++ b/Examples/ruby/reference/example.cxx @@ -0,0 +1,46 @@ +/* File : example.cxx */ + +/* Deal with Microsoft's attempt at deprecating C standard runtime functions */ +#if !defined(SWIG_NO_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) +# define _CRT_SECURE_NO_DEPRECATE +#endif + +#include "example.h" +#include <stdio.h> +#include <stdlib.h> + +Vector operator+(const Vector &a, const Vector &b) { + Vector r; + r.x = a.x + b.x; + r.y = a.y + b.y; + r.z = a.z + b.z; + return r; +} + +char *Vector::print() { + static char temp[512]; + sprintf(temp,"Vector %p (%g,%g,%g)", this, x,y,z); + return temp; +} + +VectorArray::VectorArray(int size) { + items = new Vector[size]; + maxsize = size; +} + +VectorArray::~VectorArray() { + delete [] items; +} + +Vector &VectorArray::operator[](int index) { + if ((index < 0) || (index >= maxsize)) { + printf("Panic! Array index out of bounds.\n"); + exit(1); + } + return items[index]; +} + +int VectorArray::size() { + return maxsize; +} + diff --git a/Examples/ruby/reference/example.h b/Examples/ruby/reference/example.h new file mode 100644 index 0000000..4915adb --- /dev/null +++ b/Examples/ruby/reference/example.h @@ -0,0 +1,26 @@ +/* File : example.h */ + +class Vector { +private: + double x,y,z; +public: + Vector() : x(0), y(0), z(0) { }; + Vector(double x, double y, double z) : x(x), y(y), z(z) { }; + friend Vector operator+(const Vector &a, const Vector &b); + char *print(); +}; + +class VectorArray { +private: + Vector *items; + int maxsize; +public: + VectorArray(int maxsize); + ~VectorArray(); + Vector &operator[](int); + int size(); +}; + + + + diff --git a/Examples/ruby/reference/example.i b/Examples/ruby/reference/example.i new file mode 100644 index 0000000..6daa3b1 --- /dev/null +++ b/Examples/ruby/reference/example.i @@ -0,0 +1,46 @@ +/* File : example.i */ + +/* This file has a few "typical" uses of C++ references. */ + +%module example + +%{ +#include "example.h" +%} + +class Vector { +public: + Vector(double x, double y, double z); + ~Vector(); + char *print(); +}; + +/* This helper function calls an overloaded operator */ +%inline %{ +Vector addv(Vector &a, Vector &b) { + return a+b; +} +%} + +/* Wrapper around an array of vectors class */ + +class VectorArray { +public: + VectorArray(int maxsize); + ~VectorArray(); + int size(); + + /* This wrapper provides an alternative to the [] operator */ + %extend { + Vector &get(int index) { + return (*$self)[index]; + } + void set(int index, Vector &a) { + (*$self)[index] = a; + } + } +}; + + + + diff --git a/Examples/ruby/reference/index.html b/Examples/ruby/reference/index.html new file mode 100644 index 0000000..d45dbe3 --- /dev/null +++ b/Examples/ruby/reference/index.html @@ -0,0 +1,147 @@ +<html> +<head> +<title>SWIG:Examples:ruby:reference</title> +</head> + +<body bgcolor="#ffffff"> + + +<tt>SWIG/Examples/ruby/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 Ruby script</h2> + +Click <a href="runme.rb">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, Ruby only supports the 'x.a' +notation so it doesn't much matter. + +<p> +<li>When a program returns a reference, a pointer is returned. +Unlike return by value, memory is not allocated to hold the +return result. + +<p> +<li>SWIG has particular trouble handling various combinations of references +and pointers. This is side effect of an old parsing scheme and +type representation that will be replaced in future versions. + +</ul> + +<hr> +</body> +</html> diff --git a/Examples/ruby/reference/runme.rb b/Examples/ruby/reference/runme.rb new file mode 100644 index 0000000..67b76fc --- /dev/null +++ b/Examples/ruby/reference/runme.rb @@ -0,0 +1,60 @@ +# file: runme.rb + +# This file illustrates the manipulation of C++ references in Ruby. + +require 'example' + +# ----- Object creation ----- + +print "Creating some objects:\n" +a = Example::Vector.new(3,4,5) +b = Example::Vector.new(10,11,12) + +print " Created ", a.print, "\n" +print " Created ", b.print, "\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 = ", c.print, "\n" + +# ----- Create a vector array ----- + +print "Creating an array of vectors\n" +va = Example::VectorArray.new(10) +print " va = #{va}\n" + +# ----- Set some values in the array ----- + +# These operators copy the value of a and b to the vector array +va.set(0, a) +va.set(1, b) + +va.set(2, Example::addv(a,b)) + +c = Example::addv(a,b) +va.set(3, c) + +=begin commented out due to GC issue + +# Get some values from the array + +print "Getting some array values\n" +for i in 0...5 + print " va(#{i}) = ", va.get(i).print, "\n" +end + +# Watch under resource meter to check on this +print "Making sure we don't leak memory.\n" +for i in 0...1000000 + c = va.get(i % 10) +end + +=end diff --git a/Examples/ruby/simple/Makefile b/Examples/ruby/simple/Makefile new file mode 100644 index 0000000..8c4fe10 --- /dev/null +++ b/Examples/ruby/simple/Makefile @@ -0,0 +1,18 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +SRCS = example.c +TARGET = example +INTERFACE = example.i + +all:: + $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \ + TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' ruby + +static:: + $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \ + TARGET='myruby' INTERFACE='$(INTERFACE)' ruby_static + +clean:: + $(MAKE) -f $(TOP)/Makefile ruby_clean + +check: all diff --git a/Examples/ruby/simple/example.c b/Examples/ruby/simple/example.c new file mode 100644 index 0000000..1c2af78 --- /dev/null +++ b/Examples/ruby/simple/example.c @@ -0,0 +1,18 @@ +/* File : example.c */ + +/* A global variable */ +double Foo = 3.0; + +/* Compute the greatest common divisor of positive integers */ +int gcd(int x, int y) { + int g; + g = y; + while (x > 0) { + g = x; + x = y % x; + y = g; + } + return g; +} + + diff --git a/Examples/ruby/simple/example.dsp b/Examples/ruby/simple/example.dsp new file mode 100644 index 0000000..4888299 --- /dev/null +++ b/Examples/ruby/simple/example.dsp @@ -0,0 +1,150 @@ +# 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 "$(RUBY_INCLUDE)" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE_EXPORTS" /D NT=1 /D "IMPORT" /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 "$(RUBY_LIB)" /nologo /dll /debug /machine:I386 /out:"example.dll" /pdbtype:sept
+# SUBTRACT LINK32 /pdb:none
+
+!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 "$(RUBY_INCLUDE)" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXAMPLE_EXPORTS" /D NT=1 /D "IMPORT" /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 "$(RUBY_LIB)" /nologo /dll /machine:I386 /out:"example.dll"
+# SUBTRACT LINK32 /pdb:none
+
+!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 RUBY_INCLUDE: %RUBY_INCLUDE%
+ echo RUBY_LIB: %RUBY_LIB%
+ echo on
+ ..\..\..\swig.exe -ruby $(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 RUBY_INCLUDE: %RUBY_INCLUDE%
+ echo RUBY_LIB: %RUBY_LIB%
+ echo on
+ ..\..\..\swig.exe -ruby $(InputPath)
+
+# End Custom Build
+
+!ENDIF
+
+# End Source File
+# End Target
+# End Project
diff --git a/Examples/ruby/simple/example.i b/Examples/ruby/simple/example.i new file mode 100644 index 0000000..24093b9 --- /dev/null +++ b/Examples/ruby/simple/example.i @@ -0,0 +1,7 @@ +/* File : example.i */ +%module example + +%inline %{ +extern int gcd(int x, int y); +extern double Foo; +%} diff --git a/Examples/ruby/simple/index.html b/Examples/ruby/simple/index.html new file mode 100644 index 0000000..b2ab14e --- /dev/null +++ b/Examples/ruby/simple/index.html @@ -0,0 +1,97 @@ +<html> +<head> +<title>SWIG:Examples:ruby:simple</title> +</head> + +<body bgcolor="#ffffff"> + + +<tt>SWIG/Examples/ruby/simple/</tt> +<hr> + +<H2>Simple Ruby Example</H2> + +<p> +This example illustrates how you can hook Ruby 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 -ruby <a href="example.i">example.i</a></tt> +<p> +<li>Compile <tt><a href="example_wrap.c">example_wrap.c</a></tt> and <tt><a href="example.c">example.c</a></tt> +to create the extension <tt>example.so</tt>. +</ol> + +<h2>Using the extension</h2> + +Click <a href="run.rb">here</a> to see a script that calls our C functions from Ruby. + +<h2>Key points</h2> + +<ul> +<li>Use the <tt>require</tt> function to load your extension library from Ruby. For example: +<blockquote> +<pre> +require 'example' +</pre> +</blockquote> + +<li>C functions work just like Ruby functions. For example: +<blockquote> +<pre> +g = Example.gcd(42,105) +</pre> +</blockquote> + +<li>C global variables are accessed through module method. For example: +<blockquote> +<pre> +a = Example.Foo +</pre> +</blockquote> +</ul> + +<hr> +</body> +</html> diff --git a/Examples/ruby/simple/runme.rb b/Examples/ruby/simple/runme.rb new file mode 100755 index 0000000..9cc47b2 --- /dev/null +++ b/Examples/ruby/simple/runme.rb @@ -0,0 +1,21 @@ +# file: runme.rb + +require 'example' + +# Call our gcd() function + +x = 42 +y = 105 +g = Example.gcd(x,y) +printf "The gcd of %d and %d is %d\n",x,y,g + +# 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/Examples/ruby/std_vector/Makefile b/Examples/ruby/std_vector/Makefile new file mode 100644 index 0000000..15c9d70 --- /dev/null +++ b/Examples/ruby/std_vector/Makefile @@ -0,0 +1,20 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +CXXSRCS = +TARGET = example +INTERFACE = example.i +LIBS = -lm +SWIGOPT = + +all:: + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' ruby_cpp + +static:: + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + SWIGOPT='$(SWIGOPT)' TARGET='myruby' INTERFACE='$(INTERFACE)' ruby_cpp_static + +clean:: + $(MAKE) -f $(TOP)/Makefile ruby_clean + +check: all diff --git a/Examples/ruby/std_vector/example.h b/Examples/ruby/std_vector/example.h new file mode 100644 index 0000000..4f0dac7 --- /dev/null +++ b/Examples/ruby/std_vector/example.h @@ -0,0 +1,25 @@ +/* File : example.h */ + +#include <vector> +#include <algorithm> +#include <functional> +#include <numeric> + +double average(std::vector<int> v) { + return std::accumulate(v.begin(),v.end(),0.0)/v.size(); +} + +std::vector<double> half(const std::vector<double>& v) { + std::vector<double> w(v); + for (unsigned int i=0; i<w.size(); i++) + w[i] /= 2.0; + return w; +} + +void halve_in_place(std::vector<double>& v) { + // would you believe this is the same as the above? + std::transform(v.begin(),v.end(),v.begin(), + std::bind2nd(std::divides<double>(),2.0)); +} + + diff --git a/Examples/ruby/std_vector/example.i b/Examples/ruby/std_vector/example.i new file mode 100644 index 0000000..aa58b66 --- /dev/null +++ b/Examples/ruby/std_vector/example.i @@ -0,0 +1,17 @@ +/* File : example.i */ +%module example + +%{ +#include "example.h" +%} + +%include stl.i +/* instantiate the required template specializations */ +namespace std { + %template(IntVector) vector<int>; + %template(DoubleVector) vector<double>; +} + +/* Let's just grab the original header file here */ +%include "example.h" + diff --git a/Examples/ruby/std_vector/runme.rb b/Examples/ruby/std_vector/runme.rb new file mode 100644 index 0000000..8511905 --- /dev/null +++ b/Examples/ruby/std_vector/runme.rb @@ -0,0 +1,36 @@ +# file: runme.rb + +require 'example' + +# Call average with a Ruby array... + +puts Example::average([1,2,3,4]) + +# ... or a wrapped std::vector<int> + +v = Example::IntVector.new(4) +0.upto(v.size-1) { |i| v[i] = i+1 } +puts Example::average(v) + + +# half will return a Ruby array. +# Call it with a Ruby array... + +w = Example::half([1.0, 1.5, 2.0, 2.5, 3.0]) +0.upto(w.size-1) { |i| print w[i],"; " } +puts + +# ... or a wrapped std::vector<double> + +v = Example::DoubleVector.new +[1,2,3,4].each { |i| v.push(i) } +w = Example::half(v) +0.upto(w.size-1) { |i| print w[i],"; " } +puts + +# now halve a wrapped std::vector<double> in place + +Example::halve_in_place(v) +0.upto(v.size-1) { |i| print v[i],"; " } +puts + diff --git a/Examples/ruby/template/Makefile b/Examples/ruby/template/Makefile new file mode 100644 index 0000000..15c9d70 --- /dev/null +++ b/Examples/ruby/template/Makefile @@ -0,0 +1,20 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +CXXSRCS = +TARGET = example +INTERFACE = example.i +LIBS = -lm +SWIGOPT = + +all:: + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' ruby_cpp + +static:: + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + SWIGOPT='$(SWIGOPT)' TARGET='myruby' INTERFACE='$(INTERFACE)' ruby_cpp_static + +clean:: + $(MAKE) -f $(TOP)/Makefile ruby_clean + +check: all diff --git a/Examples/ruby/template/example.h b/Examples/ruby/template/example.h new file mode 100644 index 0000000..7401df6 --- /dev/null +++ b/Examples/ruby/template/example.h @@ -0,0 +1,32 @@ +/* File : example.h */ + +// Some template definitions + +template<class T> T max(T a, T b) { return a>b ? a : b; } + +template<class T> class vector { + T *v; + int sz; + public: + vector(int _sz) { + v = new T[_sz]; + sz = _sz; + } + T &get(int index) { + return v[index]; + } + void set(int index, T &val) { + v[index] = val; + } +#ifdef SWIG + %extend { + T getitem(int index) { + return $self->get(index); + } + void setitem(int index, T val) { + $self->set(index,val); + } + } +#endif +}; + diff --git a/Examples/ruby/template/example.i b/Examples/ruby/template/example.i new file mode 100644 index 0000000..d5ddf7a --- /dev/null +++ b/Examples/ruby/template/example.i @@ -0,0 +1,21 @@ +/* File : example.i */ +%module example + +%{ +#ifdef max +#undef max +#endif + +#include "example.h" +%} + +/* Let's just grab the original header file here */ +%include "example.h" + +/* Now instantiate some specific template declarations */ + +%template(maxint) max<int>; +%template(maxdouble) max<double>; +%template(Vecint) vector<int>; +%template(Vecdouble) vector<double>; + diff --git a/Examples/ruby/template/runme.rb b/Examples/ruby/template/runme.rb new file mode 100644 index 0000000..6c9c4eb --- /dev/null +++ b/Examples/ruby/template/runme.rb @@ -0,0 +1,25 @@ +# file: runme.rb + +require 'example' + +# Call some templated functions +puts Example::maxint(3, 7) +puts Example::maxdouble(3.14, 2.18) + +# Create some class + +iv = Example::Vecint.new(100) +dv = Example::Vecdouble.new(1000) + +100.times { |i| iv.setitem(i, 2*i) } + +1000.times { |i| dv.setitem(i, 1.0/(i+1)) } + +sum = 0 +100.times { |i| sum = sum + iv.getitem(i) } + +puts sum + +sum = 0.0 +1000.times { |i| sum = sum + dv.getitem(i) } +puts sum diff --git a/Examples/ruby/value/Makefile b/Examples/ruby/value/Makefile new file mode 100644 index 0000000..8c4fe10 --- /dev/null +++ b/Examples/ruby/value/Makefile @@ -0,0 +1,18 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +SRCS = example.c +TARGET = example +INTERFACE = example.i + +all:: + $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \ + TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' ruby + +static:: + $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \ + TARGET='myruby' INTERFACE='$(INTERFACE)' ruby_static + +clean:: + $(MAKE) -f $(TOP)/Makefile ruby_clean + +check: all diff --git a/Examples/ruby/value/example.c b/Examples/ruby/value/example.c new file mode 100644 index 0000000..4ed2fe1 --- /dev/null +++ b/Examples/ruby/value/example.c @@ -0,0 +1,15 @@ +/* File : example.c */ + +#include "example.h" + +double dot_product(Vector a, Vector b) { + return (a.x*b.x + a.y*b.y + a.z*b.z); +} + +Vector vector_add(Vector a, Vector b) { + Vector r; + r.x = a.x + b.x; + r.y = a.y + b.y; + r.z = a.z + b.z; + return r; +} diff --git a/Examples/ruby/value/example.h b/Examples/ruby/value/example.h new file mode 100644 index 0000000..212cf4b --- /dev/null +++ b/Examples/ruby/value/example.h @@ -0,0 +1,5 @@ +/* File : example.h */ + +typedef struct { + double x, y, z; +} Vector; diff --git a/Examples/ruby/value/example.i b/Examples/ruby/value/example.i new file mode 100644 index 0000000..98fd60e --- /dev/null +++ b/Examples/ruby/value/example.i @@ -0,0 +1,32 @@ +// Tests SWIG's handling of pass-by-value for complex datatypes +%module example + +%{ +#include "example.h" +%} + +/* Some functions that manipulate Vectors by value */ +%inline %{ +extern double dot_product(Vector a, Vector b); +extern Vector vector_add(Vector a, Vector b); +%} + +/* Include this because the vector_add() function will leak memory */ +void free(void *); + +/* Some helper functions for our interface */ +%inline %{ + +Vector *new_Vector(double x, double y, double z) { + Vector *v = (Vector *) malloc(sizeof(Vector)); + v->x = x; + v->y = y; + v->z = z; + return v; +} + +void vector_print(Vector *v) { + printf("Vector %p = (%g, %g, %g)\n", v, v->x, v->y, v->z); +} +%} + diff --git a/Examples/ruby/value/index.html b/Examples/ruby/value/index.html new file mode 100644 index 0000000..cd99ba1 --- /dev/null +++ b/Examples/ruby/value/index.html @@ -0,0 +1,114 @@ +<html> +<head> +<title>SWIG:Examples:ruby:value</title> +</head> + +<body bgcolor="#ffffff"> + + +<tt>SWIG/Examples/ruby/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 Ruby Script</h2> + +Click <a href="runme.rb">here</a> to see a script that uses these functions from Ruby. + +<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> + +<p> +<li>If you define C structure (or C++ class with '<tt>-c++</tt>' option) +in the interface file, the SWIG generated wrappers can automaticallyclean +up the result of return-by-reference by GC. + +<p> +<li>Passing parameters by value like this really isn't the best C programming style. +If possible, you might change your application to use pointers. + +<p> +<li>Similar translations are made when C++ references are used. + + +</ul> + +<hr> +</body> +</html> diff --git a/Examples/ruby/value/runme.rb b/Examples/ruby/value/runme.rb new file mode 100644 index 0000000..9372c03 --- /dev/null +++ b/Examples/ruby/value/runme.rb @@ -0,0 +1,32 @@ +# file: runme.rb + +require '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/Examples/ruby/variables/Makefile b/Examples/ruby/variables/Makefile new file mode 100644 index 0000000..8c4fe10 --- /dev/null +++ b/Examples/ruby/variables/Makefile @@ -0,0 +1,18 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +SRCS = example.c +TARGET = example +INTERFACE = example.i + +all:: + $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \ + TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' ruby + +static:: + $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \ + TARGET='myruby' INTERFACE='$(INTERFACE)' ruby_static + +clean:: + $(MAKE) -f $(TOP)/Makefile ruby_clean + +check: all diff --git a/Examples/ruby/variables/example.c b/Examples/ruby/variables/example.c new file mode 100644 index 0000000..aa4ffe9 --- /dev/null +++ b/Examples/ruby/variables/example.c @@ -0,0 +1,91 @@ +/* File : example.c */ + +/* I'm a file containing some C global variables */ + +/* Deal with Microsoft's attempt at deprecating C standard runtime functions */ +#if !defined(SWIG_NO_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) +# define _CRT_SECURE_NO_DEPRECATE +#endif + +#include <stdio.h> +#include <stdlib.h> +#include "example.h" + +int ivar = 0; +short svar = 0; +long lvar = 0; +unsigned int uivar = 0; +unsigned short usvar = 0; +unsigned long ulvar = 0; +signed char scvar = 0; +unsigned char ucvar = 0; +char cvar = 0; +float fvar = 0; +double dvar = 0; +char *strvar = 0; +const char cstrvar[] = "Goodbye"; +int *iptrvar = 0; +char name[256] = "Dave"; +char path[256] = "/home/beazley"; + + +/* Global variables involving a structure */ +Point *ptptr = 0; +Point pt = { 10, 20 }; + +/* A variable that we will make read-only in the interface */ +int status = 1; + +/* A debugging function to print out their values */ + +void print_vars() { + printf("ivar = %d\n", ivar); + printf("svar = %d\n", svar); + printf("lvar = %ld\n", lvar); + printf("uivar = %u\n", uivar); + printf("usvar = %u\n", usvar); + printf("ulvar = %lu\n", ulvar); + printf("scvar = %d\n", scvar); + printf("ucvar = %u\n", ucvar); + printf("fvar = %g\n", fvar); + printf("dvar = %g\n", dvar); + printf("cvar = %c\n", cvar); + printf("strvar = %s\n", strvar ? strvar : "(null)"); + printf("cstrvar = %s\n", cstrvar ? cstrvar : "(null)"); + printf("iptrvar = %p\n", iptrvar); + printf("name = %s\n", name); + printf("ptptr = %p (%d, %d)\n", ptptr, ptptr ? ptptr->x : 0, ptptr ? ptptr->y : 0); + printf("pt = (%d, %d)\n", pt.x, pt.y); + printf("status = %d\n", status); +} + +/* A function to create an integer (to test iptrvar) */ + +int *new_int(int value) { + int *ip = (int *) malloc(sizeof(int)); + *ip = value; + return ip; +} + +/* A function to create a point */ + +Point *new_Point(int x, int y) { + Point *p = (Point *) malloc(sizeof(Point)); + p->x = x; + p->y = y; + return p; +} + +char * Point_print(Point *p) { + static char buffer[256]; + if (p) { + sprintf(buffer,"(%d,%d)", p->x,p->y); + } else { + sprintf(buffer,"null"); + } + return buffer; +} + +void pt_print() { + printf("(%d, %d)\n", pt.x, pt.y); +} diff --git a/Examples/ruby/variables/example.h b/Examples/ruby/variables/example.h new file mode 100644 index 0000000..0f7e895 --- /dev/null +++ b/Examples/ruby/variables/example.h @@ -0,0 +1,6 @@ +/* File: example.h */ + +typedef struct { + int x,y; +} Point; + diff --git a/Examples/ruby/variables/example.i b/Examples/ruby/variables/example.i new file mode 100644 index 0000000..84a1509 --- /dev/null +++ b/Examples/ruby/variables/example.i @@ -0,0 +1,50 @@ +/* File : example.i */ +%module example +%{ +#include "example.h" +%} +#pragma SWIG nowarn=SWIGWARN_TYPEMAP_SWIGTYPELEAK + +/* Some global variable declarations */ +%inline %{ +extern int ivar; +extern short svar; +extern long lvar; +extern unsigned int uivar; +extern unsigned short usvar; +extern unsigned long ulvar; +extern signed char scvar; +extern unsigned char ucvar; +extern char cvar; +extern float fvar; +extern double dvar; +extern char *strvar; +extern const char cstrvar[]; +extern int *iptrvar; +extern char name[256]; + +extern Point *ptptr; +extern Point pt; +%} + + +/* Some read-only variables */ + +%immutable; + +%inline %{ +extern int status; +extern char path[256]; +%} + +%mutable; + +/* Some helper functions to make it easier to test */ +%inline %{ +extern void print_vars(); +extern int *new_int(int value); +extern Point *new_Point(int x, int y); +extern char *Point_print(Point *p); +extern void pt_print(); +%} + diff --git a/Examples/ruby/variables/index.html b/Examples/ruby/variables/index.html new file mode 100644 index 0000000..d83a87c --- /dev/null +++ b/Examples/ruby/variables/index.html @@ -0,0 +1,94 @@ +<html> +<head> +<title>SWIG:Examples:ruby:variables</title> +</head> + +<body bgcolor="#ffffff"> + +<tt>SWIG/Examples/ruby/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 Ruby variable (actually module method) 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 Ruby</h2> + +Before going any further, it is important to understand some important +differences between C and Ruby variables. In C, a variable is +simply a name that refers to a specific location in memory. For +example, when you declare a global variable '<tt>double a</tt>' you +know that somewhere in memory, 8 bytes have been set aside to hold a +<tt>double</tt> and that <tt>a</tt> is bound to this location for the +life of the program. In Ruby, variable creation is nothing more +than a naming operation. For example, when you say '<tt>a = 3</tt>', +'a' becomes a name that refers to some object '3'. Later on, if you say +'<tt>a = 7.5</tt>, the name 'a' is bound to an entirely different object +containing the value '7.5' (the contents of the original object are not +changed). The end result of this is that a variable in Ruby can refer +to a virtually unlimited number of different objects (memory locations) +over the lifetime of a program. + +<p> +Because of Ruby's somewhat unusual variable assignment semantics, it is not +possible to directly link a C global variable into an equivalent Ruby variable. +Instead, all C global variables are accessed as attributes of the module. +For example, if you had a global variable + +<blockquote> +<pre> +double foo; +</pre> +</blockquote> + +it will be accessed in the Ruby module as <tt>Example.foo</tt>. Click +<a href="runme.rb">here</a> to see a script that updates and prints +out the values of the variables using this technique. + +<h2>Key points</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 Ruby, the old +value is destroyed using <tt>free()</tt>. +<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 Ruby strings, but +when setting the value, the result is truncated to the maximum length of the array. Furthermore, the string is assumed to be null-terminated. +<li>When structures and classes are used as global variables, they are mapped into pointers. +Getting the "value" returns a pointer to the global variable. Setting the value of a structure results in a memory copy from a pointer to the global. +</ul> + +<h2>Creating read-only variables</h2> + +The <tt>%immutable</tt> and <tt>%mutable</tt> directives can be used to +specify a collection of read-only variables. For example: + +<blockquote> +<pre> +%immutable; +int status; +double blah; +... +%mutable; +</pre> +</blockquote> + +The <tt>%immutable</tt> directive remains in effect until it is explicitly disabled +using the <tt>%mutable</tt> directive. + +<h2>Comments</h2> +<ul> +<li>Management of global variables is one of the most problematic aspects +of C/C++ wrapping because the scripting interface and resulting memory management +is much trickier than simply creating a wrapper function. +</ul> + +</body> +</html> +<hr> diff --git a/Examples/ruby/variables/runme.rb b/Examples/ruby/variables/runme.rb new file mode 100644 index 0000000..38531c8 --- /dev/null +++ b/Examples/ruby/variables/runme.rb @@ -0,0 +1,77 @@ +# file: runme.rb + +require '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 + +puts "Variables (values printed from Ruby)" + +puts "ivar = #{Example.ivar}" +puts "svar = #{Example.svar}" +puts "lvar = #{Example.lvar}" +puts "uivar = #{Example.uivar}" +puts "usvar = #{Example.usvar}" +puts "ulvar = #{Example.ulvar}" +puts "scvar = #{Example.scvar}" +puts "ucvar = #{Example.ucvar}" +puts "fvar = #{Example.fvar}" +puts "dvar = #{Example.dvar}" +puts "cvar = #{Example.cvar}" +puts "strvar = #{Example.strvar}" +puts "cstrvar = #{Example.cstrvar}" +puts "iptrvar = #{Example.iptrvar}" +puts "name = #{Example.name}" +puts "ptptr = #{Example.ptptr} (#{Example.Point_print(Example.ptptr)})" +puts "pt = #{Example.pt} (#{Example.Point_print(Example.pt)})" + +puts "\nVariables (values printed from C)" + +Example.print_vars() + +puts "\nNow I'm going to try and modify some read only variables"; + +puts " Tring to set 'path'"; +begin + Example.path = "Whoa!" + puts "Hey, what's going on?!?! This shouldn't work" +rescue NameError + puts "Good." +end + +puts " Trying to set 'status'"; +begin + Example.status = 0 + puts "Hey, what's going on?!?! This shouldn't work" +rescue NameError + puts "Good." +end + + +puts "\nI'm going to try and update a structure variable.\n" + +Example.pt = Example.ptptr + +puts "The new value is" +Example.pt_print() +puts "You should see the value #{Example.Point_print(Example.ptptr)}" + + + |