update swig on windows

This commit is contained in:
Bassem Girgis
2019-08-04 21:38:19 -05:00
parent 8414b7136b
commit 76ad52be58
5943 changed files with 91790 additions and 71892 deletions

View File

@@ -0,0 +1,22 @@
# see top-level Makefile.in
class
constants
enum
#free_function
funcptr
funcptr2
functor
hashargs
import
import_template
mark_function
multimap
operator
overloading
pointer
reference
simple
std_vector
template
value
variables

View File

@@ -0,0 +1,23 @@
TOP = ../..
SWIGEXE = $(TOP)/../swig
SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib
CXXSRCS = example.cxx
TARGET = example
INTERFACE = example.i
LIBS = -lm
check: build
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' ruby_run
build:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' ruby_cpp
static:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='myruby' INTERFACE='$(INTERFACE)' ruby_cpp_static
clean:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' ruby_clean

View File

@@ -0,0 +1,28 @@
/* File : example.cxx */
#include "example.h"
#define M_PI 3.14159265358979323846
/* Move the shape to a new location */
void Shape::move(double dx, double dy) {
x += dx;
y += dy;
}
int Shape::nshapes = 0;
double Circle::area() {
return M_PI*radius*radius;
}
double Circle::perimeter() {
return 2*M_PI*radius;
}
double Square::area() {
return width*width;
}
double Square::perimeter() {
return 4*width;
}

View File

@@ -0,0 +1,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

View File

@@ -0,0 +1,34 @@
/* File : example.h */
class Shape {
public:
Shape() {
nshapes++;
}
virtual ~Shape() {
nshapes--;
}
double x, y;
void move(double dx, double dy);
virtual double area() = 0;
virtual double perimeter() = 0;
static int nshapes;
};
class Circle : public Shape {
private:
double radius;
public:
Circle(double r) : radius(r) { }
virtual double area();
virtual double perimeter();
};
class Square : public Shape {
private:
double width;
public:
Square(double w) : width(w) { }
virtual double area();
virtual double perimeter();
};

View File

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

View File

@@ -0,0 +1,156 @@
<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 wrapping a simple C++ class to give a Ruby class.
<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 the
Ruby interpreter, the corresponding C++ destructor is automatically invoked.
<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 provide 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.
<li>SWIG <b>does</b> know how to properly perform upcasting of objects in
an inheritance hierarchy except for multiple inheritance.
<li>C++ Namespaces - %nspace isn't yet supported for Ruby.
</ul>
<hr>
</body>
</html>

View File

@@ -0,0 +1,53 @@
# 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.
# Remove references to the object and force a garbage collection run.
c = s = o = nil
GC.start()
print "\n", Example::Shape.nshapes," shapes remain\n"
print "Goodbye\n"

View File

@@ -0,0 +1,22 @@
TOP = ../..
SWIGEXE = $(TOP)/../swig
SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib
SRCS =
TARGET = example
INTERFACE = example.i
check: build
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' ruby_run
build:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' ruby
static:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='myruby' INTERFACE='$(INTERFACE)' ruby_static
clean:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' ruby_clean

View File

@@ -0,0 +1,27 @@
/* File : example.i */
%module example
/* A few preprocessor macros */
#define ICONST 42
#define FCONST 2.1828
#define CCONST 'x'
#define CCONST2 '\n'
#define SCONST "Hello World"
#define SCONST2 "\"Hello World\""
/* This should work just fine */
#define EXPR ICONST + 3*(FCONST)
/* This shouldn't do anything */
#define EXTERN extern
/* Neither should this (BAR isn't defined) */
#define FOO (ICONST + BAR)
/* The following directives also produce constants */
%constant int Iconst = 37;
%constant double Fconst = 3.14;

View File

@@ -0,0 +1,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>

View File

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

View File

@@ -0,0 +1,23 @@
TOP = ../..
SWIGEXE = $(TOP)/../swig
SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib
CXXSRCS = example.cxx
TARGET = example
INTERFACE = example.i
LIBS = -lm
check: build
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' ruby_run
build:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' ruby_cpp
static:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='myruby' INTERFACE='$(INTERFACE)' ruby_cpp_static
clean:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' ruby_clean

View File

@@ -0,0 +1,37 @@
/* File : example.c */
#include "example.h"
#include <stdio.h>
void Foo::enum_test(speed s) {
if (s == IMPULSE) {
printf("IMPULSE speed\n");
} else if (s == WARP) {
printf("WARP speed\n");
} else if (s == LUDICROUS) {
printf("LUDICROUS speed\n");
} else {
printf("Unknown speed\n");
}
}
void enum_test(color c, Foo::speed s) {
if (c == RED) {
printf("color = RED, ");
} else if (c == BLUE) {
printf("color = BLUE, ");
} else if (c == GREEN) {
printf("color = GREEN, ");
} else {
printf("color = Unknown color!, ");
}
if (s == Foo::IMPULSE) {
printf("speed = IMPULSE speed\n");
} else if (s == Foo::WARP) {
printf("speed = WARP speed\n");
} else if (s == Foo::LUDICROUS) {
printf("speed = LUDICROUS speed\n");
} else {
printf("speed = Unknown speed!\n");
}
}

View File

@@ -0,0 +1,13 @@
/* File : example.h */
enum color { RED, BLUE, GREEN };
class Foo {
public:
Foo() { }
enum speed { IMPULSE, WARP, LUDICROUS };
void enum_test(speed s);
};
void enum_test(color c, Foo::speed s);

View File

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

View File

@@ -0,0 +1,35 @@
<html>
<head>
<title>SWIG:Examples: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>

View File

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

View File

@@ -0,0 +1,23 @@
TOP = ../..
SWIGEXE = $(TOP)/../swig
SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib
CXXSRCS =
TARGET = example
INTERFACE = example.i
LIBS = -lm
check: build
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' ruby_run
build:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' ruby_cpp
static:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='myruby' INTERFACE='$(INTERFACE)' ruby_cpp_static
clean:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' ruby_clean

View File

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

View File

@@ -0,0 +1,47 @@
/* 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(FullError) *::enqueue;
%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>;

View File

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

View File

@@ -0,0 +1,23 @@
TOP = ../..
SWIGEXE = $(TOP)/../swig
SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib
CXXSRCS = example.cxx
TARGET = example
INTERFACE = example.i
LIBS = -lm
check: build
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' ruby_run
build:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' ruby_cpp
static:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='myruby' INTERFACE='$(INTERFACE)' ruby_cpp_static
clean:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' ruby_clean

View File

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

View File

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

View File

@@ -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_*/

View File

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

View File

@@ -0,0 +1,51 @@
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
# Not working - needs checking/fixing
# 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
# Let's stress the GC a bit, a single pass might not be enough.
10.times {
GC.start
puts tiger2.get_name
}
rescue ObjectPreviouslyDeleted => error
ok = true
end
raise(RuntimeError, "Incorrect exception raised - should be ObjectPreviouslyDeleted") unless ok

View File

@@ -0,0 +1,22 @@
TOP = ../..
SWIGEXE = $(TOP)/../swig
SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib
SRCS = example.c
TARGET = example
INTERFACE = example.i
check: build
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' ruby_run
build:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' ruby
static:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='myruby' INTERFACE='$(INTERFACE)' ruby_static
clean:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' ruby_clean

View File

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

View File

@@ -0,0 +1,9 @@
/* file: example.h */
extern int do_op(int,int, int (*op)(int,int));
extern int add(int,int);
extern int sub(int,int);
extern int mul(int,int);
extern int (*funcvar)(int,int);

View File

@@ -0,0 +1,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;

View File

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

View File

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

View File

@@ -0,0 +1,22 @@
TOP = ../..
SWIGEXE = $(TOP)/../swig
SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib
SRCS = example.c
TARGET = example
INTERFACE = example.i
check: build
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' ruby_run
build:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' ruby
static:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='myruby' INTERFACE='$(INTERFACE)' ruby_static
clean:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' ruby_clean

View File

@@ -0,0 +1,19 @@
/* File : example.c */
int do_op(int a, int b, int (*op)(int,int)) {
return (*op)(a,b);
}
int add(int a, int b) {
return a+b;
}
int sub(int a, int b) {
return a-b;
}
int mul(int a, int b) {
return a*b;
}
int (*funcvar)(int,int) = add;

View File

@@ -0,0 +1,9 @@
/* file: example.h */
extern int do_op(int,int, int (*op)(int,int));
extern int add(int,int);
extern int sub(int,int);
extern int mul(int,int);
extern int (*funcvar)(int,int);

View File

@@ -0,0 +1,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);

View File

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

View File

@@ -0,0 +1,22 @@
TOP = ../..
SWIGEXE = $(TOP)/../swig
SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib
TARGET = example
INTERFACE = example.i
LIBS = -lm
check: build
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' ruby_run
build:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' ruby_cpp
static:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='myruby' INTERFACE='$(INTERFACE)' ruby_cpp_static
clean:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' ruby_clean

View File

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

View File

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

View File

@@ -0,0 +1,24 @@
TOP = ../..
SWIGEXE = $(TOP)/../swig
SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib
SRCS =
TARGET = example
INTERFACE = example.i
LIBS = -lm
SWIGOPT =
check: build
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' ruby_run
build:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' ruby
static:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='myruby' INTERFACE='$(INTERFACE)' ruby_static
clean:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' ruby_clean

View File

@@ -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, Qnil));
$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, Qnil);
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] = StringValuePtr(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]);
}
}
%}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,65 @@
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
###############################################################################
Project: "bar"=.\bar.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Project: "base"=.\base.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Project: "foo"=.\foo.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Project: "spam"=.\spam.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################

View File

@@ -0,0 +1,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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,11 @@
%module bar
%{
#include "bar.h"
%}
%import base.i
%include "bar.h"
%template(IntBar) Bar<int>;

View File

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

View File

@@ -0,0 +1,7 @@
%module base
%{
#include "base.h"
%}
%include base.h
%template(IntBase) Base<int>;

View File

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

View File

@@ -0,0 +1,10 @@
%module foo
%{
#include "foo.h"
%}
%import base.i
%include "foo.h"
%template(IntFoo) Foo<int>;

View File

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

View File

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

View File

@@ -0,0 +1,10 @@
%module spam
%{
#include "spam.h"
%}
%import bar.i
%include "spam.h"
%template(IntSpam) Spam<int>;

View File

@@ -0,0 +1,94 @@
<html>
<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>

View File

@@ -0,0 +1,23 @@
TOP = ../..
SWIGEXE = $(TOP)/../swig
SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib
CXXSRCS = example.cxx
TARGET = example
INTERFACE = example.i
LIBS = -lm
check: build
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' ruby_run
build:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' ruby_cpp
static:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='myruby' INTERFACE='$(INTERFACE)' ruby_cpp_static
clean:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' ruby_clean

View File

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

View File

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

View File

@@ -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_*/

View File

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

View File

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

View File

@@ -0,0 +1,22 @@
TOP = ../..
SWIGEXE = $(TOP)/../swig
SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib
SRCS = example.c
TARGET = example
INTERFACE = example.i
check: build
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' ruby_run
build:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' ruby
static:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='myruby' INTERFACE='$(INTERFACE)' ruby_static
clean:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' ruby_clean

View File

@@ -0,0 +1,53 @@
/* File : example.c */
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
/* Compute the greatest common divisor of positive integers */
int gcd(int x, int y) {
int g;
g = y;
while (x > 0) {
g = x;
x = y % x;
y = g;
}
return g;
}
int gcdmain(int argc, char *argv[]) {
int x,y;
if (argc != 3) {
printf("usage: gcd x y\n");
return -1;
}
x = atoi(argv[1]);
y = atoi(argv[2]);
printf("gcd(%d,%d) = %d\n", x,y,gcd(x,y));
return 0;
}
int count(char *bytes, int len, char c) {
int i;
int count = 0;
for (i = 0; i < len; i++) {
if (bytes[i] == c) count++;
}
return count;
}
void capitalize(char *str, int len) {
int i;
for (i = 0; i < len; i++) {
str[i] = (char)toupper(str[i]);
}
}
void circle(double x, double y) {
double a = x*x + y*y;
if (a > 1.0) {
printf("Bad points %g, %g\n", x,y);
} else {
printf("Good points %g, %g\n", x,y);
}
}

View File

@@ -0,0 +1,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

View File

@@ -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_LEN($input);
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] = StringValuePtr(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 = StringValuePtr($input);
$2 = RSTRING_LEN($input);
}
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 = StringValuePtr($input);
$2 = RSTRING_LEN($input);
$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);

View File

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

View File

@@ -0,0 +1,24 @@
TOP = ../..
SWIGEXE = $(TOP)/../swig
SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib
CXXSRCS =
TARGET = example
INTERFACE = example.i
LIBS = -lm
SWIGOPT =
check: build
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' ruby_run
build:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' ruby_cpp
static:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='myruby' INTERFACE='$(INTERFACE)' ruby_cpp_static
clean:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' ruby_clean

View File

@@ -0,0 +1,36 @@
/* File : example.h */
#include <math.h>
class Complex {
private:
double rpart, ipart;
public:
Complex(double r = 0, double i = 0) : rpart(r), ipart(i) { }
Complex(const Complex &c) : rpart(c.rpart), ipart(c.ipart) { }
Complex &operator=(const Complex &c) {
rpart = c.rpart;
ipart = c.ipart;
return *this;
}
Complex operator+(const Complex &c) const {
return Complex(rpart+c.rpart, ipart+c.ipart);
}
Complex operator-(const Complex &c) const {
return Complex(rpart-c.rpart, ipart-c.ipart);
}
Complex operator*(const Complex &c) const {
return Complex(rpart*c.rpart - ipart*c.ipart,
rpart*c.ipart + c.rpart*ipart);
}
Complex operator-() const {
return Complex(-rpart, -ipart);
}
double re() const { return rpart; }
double im() const { return ipart; }
};

View File

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

View File

@@ -0,0 +1,25 @@
# Operator overloading example
require 'example'
include Example
a = Example::Complex.new(2, 3)
b = Example::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 = Example::Complex.new(a-c)
e = a - c
puts "e = #{e}"
# Big expression
f = ((a+b)*(c+b*e)) + (-a)
puts "f = #{f}"

View File

@@ -0,0 +1,23 @@
TOP = ../..
SWIGEXE = $(TOP)/../swig
SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib
CXXSRCS = example.cxx
TARGET = example
INTERFACE = example.i
LIBS = -lm
check: build
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' ruby_run
build:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' ruby_cpp
static:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='myruby' INTERFACE='$(INTERFACE)' ruby_cpp_static
clean:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' ruby_clean

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,22 @@
TOP = ../..
SWIGEXE = $(TOP)/../swig
SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib
SRCS = example.c
TARGET = example
INTERFACE = example.i
check: build
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' ruby_run
build:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' ruby
static:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='myruby' INTERFACE='$(INTERFACE)' ruby_static
clean:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' ruby_clean

View File

@@ -0,0 +1,16 @@
/* File : example.c */
void add(int *x, int *y, int *result) {
*result = *x + *y;
}
void sub(int *x, int *y, int *result) {
*result = *x - *y;
}
int divide(int n, int d, int *r) {
int q;
q = n/d;
*r = n - q*d;
return q;
}

View File

@@ -0,0 +1,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);

View File

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

View File

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

View File

@@ -0,0 +1,23 @@
TOP = ../..
SWIGEXE = $(TOP)/../swig
SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib
CXXSRCS = example.cxx
TARGET = example
INTERFACE = example.i
LIBS = -lm
check: build
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' ruby_run
build:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' ruby_cpp
static:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \
TARGET='myruby' INTERFACE='$(INTERFACE)' ruby_cpp_static
clean:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' ruby_clean

View File

@@ -0,0 +1,46 @@
/* File : example.cxx */
/* Deal with Microsoft's attempt at deprecating C standard runtime functions */
#if !defined(SWIG_NO_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER)
# define _CRT_SECURE_NO_DEPRECATE
#endif
#include "example.h"
#include <stdio.h>
#include <stdlib.h>
Vector operator+(const Vector &a, const Vector &b) {
Vector r;
r.x = a.x + b.x;
r.y = a.y + b.y;
r.z = a.z + b.z;
return r;
}
char *Vector::print() {
static char temp[512];
sprintf(temp,"Vector %p (%g,%g,%g)", (void *)this, x,y,z);
return temp;
}
VectorArray::VectorArray(int size) {
items = new Vector[size];
maxsize = size;
}
VectorArray::~VectorArray() {
delete [] items;
}
Vector &VectorArray::operator[](int index) {
if ((index < 0) || (index >= maxsize)) {
printf("Panic! Array index out of bounds.\n");
exit(1);
}
return items[index];
}
int VectorArray::size() {
return maxsize;
}

Some files were not shown because too many files have changed in this diff Show More