Add Ruby support contributed by Masaki Fukushima.

git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@518 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
Thien-Thi Nguyen 2000-07-05 18:58:49 +00:00
commit 4d989f6796
39 changed files with 3754 additions and 10 deletions

View file

@ -4,8 +4,8 @@ GIFPlot
To illustrate various SWIG features, the following examples involve
building an interface to a small, but somewhat useful graphics library
for creating 2D and 3D images in the form of GIF files. The Perl,
Python, and Tcl directories contain various examples specific to those
languages.
Python, Tcl, and Ruby directories contain various examples specific to
those languages.
This library was originally developed as part of the SPaSM molecular
dynamics project at Los Alamos National Laboratory. However, due to
@ -36,8 +36,8 @@ On Windows, you can probably just do this:
Running the Examples
====================
Once the library has been built, go the Perl, Python, or Tcl directory to see
various SWIG examples. Each example should have a README file with a
Once the library has been built, go the Perl, Python, Tcl, or Ruby directory
to see various SWIG examples. Each example should have a README file with a
description.
The examples are compiled using the makefile located in the top level "Examples"

View file

@ -0,0 +1,23 @@
TOP = ../../..
SWIG = $(TOP)/../swig
SWIGOPT = -I../../Include
SRCS =
TARGET = gifplot
INTERFACE = gifplot.i
LIBS = -L../.. -lgifplot
INCLUDE = -I../../Include
all::
$(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \
INCLUDE='$(INCLUDE)' LIBS='$(LIBS)' SWIGOPT='$(SWIGOPT)' \
TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' ruby
static::
$(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \
INCLUDE='$(INCLUDE)' LIBS='$(LIBS)' SWIGOPT='$(SWIGOPT)' \
TARGET='myruby' INTERFACE='$(INTERFACE)' ruby_static
clean::
rm -f *_wrap* *.o *~ *.so myruby .~* core *.gif

View file

@ -0,0 +1,8 @@
This example runs the entire gifplot.h header file through SWIG without
any changes. The script 'runme.rb' does something a little more
interesting. You'll have to go look at the header file to get a complete
listing of the functions.

View file

@ -0,0 +1,15 @@
/* Oh what the heck, let's just grab the whole darn header file
and see what happens. */
%module gifplot
%{
/* Note: You still need this part because the %include directive
merely causes SWIG to interpret the contents of a file. It doesn't
include the right include headers for the resulting C code */
#include "gifplot.h"
%}
%include gifplot.h

View file

@ -0,0 +1,66 @@
# Plot a 3D function
require 'gifplot'
include Gifplot
include Math
# Here is the function to plot
def func(x,y)
return 5*cos(2*sqrt(x*x+y*y))*exp(-0.3*sqrt(x*x+y*y))
end
# Here are some plotting parameters
XMIN = -5.0
XMAX = 5.0
YMIN = -5.0
YMAX = 5.0
ZMIN = -5.0
ZMAX = 5.0
# Grid resolution
NXPOINTS = 60
NYPOINTS = 60
cmap = new_ColorMap("cmap")
frame = new_FrameBuffer(500,500)
FrameBuffer_clear(frame,BLACK)
P3 = new_Plot3D(frame,XMIN,YMIN,ZMIN,XMAX,YMAX,ZMAX)
Plot3D_lookat(P3,2*[XMAX-XMIN,YMAX-YMIN,ZMAX-ZMIN].max)
Plot3D_autoperspective(P3,40)
Plot3D_rotu(P3,60)
Plot3D_rotr(P3,30)
Plot3D_rotd(P3,10)
def drawsolid()
Plot3D_clear(P3,BLACK)
Plot3D_start(P3)
dx = 1.0*(XMAX-XMIN)/NXPOINTS
dy = 1.0*(YMAX-YMIN)/NYPOINTS
cscale = 240.0/(ZMAX-ZMIN)
x = XMIN
for i in 0...NXPOINTS
y = YMIN
for j in 0...NYPOINTS
z1 = func(x,y)
z2 = func(x+dx,y)
z3 = func(x+dx,y+dy)
z4 = func(x,y+dy)
c1 = cscale*(z1-ZMIN)
c2 = cscale*(z2-ZMIN)
c3 = cscale*(z3-ZMIN)
c4 = cscale*(z4-ZMIN)
c = (c1+c2+c3+c4)/4
c = 0 if (c < 0)
c = 239 if c > 239
Plot3D_solidquad(P3,x,y,z1,x+dx,y,z2,x+dx,y+dy,z3,x,y+dy,z4,c+16)
y = y + dy
end
x = x + dx
end
end
puts "Making a nice 3D plot..."
drawsolid()
FrameBuffer_writeGIF(frame,cmap,"image.gif")
puts "Wrote image.gif"

View file

@ -0,0 +1,23 @@
TOP = ../../..
SWIG = $(TOP)/../swig
SWIGOPT =
SRCS =
TARGET = simple
INTERFACE = simple.i
LIBS = -L../.. -lgifplot
INCLUDE = -I../../Include
all::
$(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \
INCLUDE='$(INCLUDE)' LIBS='$(LIBS)' SWIGOPT='$(SWIGOPT)' \
TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' ruby
static::
$(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \
INCLUDE='$(INCLUDE)' LIBS='$(LIBS)' SWIGOPT='$(SWIGOPT)' \
TARGET='myruby' INTERFACE='$(INTERFACE)' ruby_static
clean::
rm -f *_wrap* *.o *~ *.so myruby .~* core *.gif

View file

@ -0,0 +1,5 @@
This is a very minimalistic example in which just a few functions
and constants from library are wrapped and used to draw some simple
shapes. The script 'runme.rb' runs the example.

View file

@ -0,0 +1,27 @@
# Draw some simple shapes
puts "Drawing some basic shapes"
require 'simple'
cmap = Simple.new_ColorMap()
f = Simple.new_FrameBuffer(400,400)
# Clear the picture
Simple.FrameBuffer_clear(f,Simple::BLACK)
# Make a red box
Simple.FrameBuffer_box(f,40,40,200,200,Simple::RED)
# Make a blue circle
Simple.FrameBuffer_circle(f,200,200,40,Simple::BLUE)
# Make green line
Simple.FrameBuffer_line(f,10,390,390,200, Simple::GREEN)
# Write an image out to disk
Simple.FrameBuffer_writeGIF(f,cmap,"image.gif")
puts "Wrote image.gif"
Simple.delete_FrameBuffer(f)
Simple.delete_ColorMap(cmap)

View file

@ -0,0 +1,38 @@
/* This example shows a very simple interface wrapping a few
primitive declarations */
%module simple
%{
#include "gifplot.h"
%}
typedef unsigned char Pixel;
/* Here are a few useful functions */
ColorMap *new_ColorMap(char *filename = 0);
void delete_ColorMap(ColorMap *cmap);
FrameBuffer *new_FrameBuffer(unsigned int width, unsigned int height);
void delete_FrameBuffer(FrameBuffer *frame);
void FrameBuffer_clear(FrameBuffer *frame, Pixel color);
void FrameBuffer_line(FrameBuffer *frame, int x1, int y1, int x2, int y2, Pixel color);
void FrameBuffer_box(FrameBuffer *frame, int x1, int y1, int x2, int y2, Pixel color);
void FrameBuffer_circle(FrameBuffer *frame, int x1, int y1, int radius, Pixel color);
int FrameBuffer_writeGIF(FrameBuffer *f, ColorMap *c, char *filename);
/* And some useful constants */
#define BLACK 0
#define WHITE 1
#define RED 2
#define GREEN 3
#define BLUE 4
#define YELLOW 5
#define CYAN 6
#define MAGENTA 7

View file

@ -337,6 +337,52 @@ mzscheme: $(SRCS)
mzc --cc $(ISRCS) $(SRCS)
mzc --ld $(TARGET)$(SO) $(OBJS) $(IOBJS)
##################################################################
##### RUBY ######
##################################################################
# Make sure these locate your Ruby installation
RUBY_INCLUDE= -DHAVE_CONFIG_H @RUBYINCLUDE@
# ----------------------------------------------------------------
# Build a C dynamically loadable module
# ----------------------------------------------------------------
ruby: $(SRCS)
$(SWIG) -ruby $(SWIGOPT) $(INTERFACE)
$(CC) -c $(CCSHARED) $(CFLAGS) $(ISRCS) $(SRCS) $(INCLUDE) $(RUBY_INCLUDE)
$(LDSHARED) $(OBJS) $(IOBJS) $(LIBS) -o $(TARGET)$(SO)
# -----------------------------------------------------------------
# Build a C++ dynamically loadable module
# -----------------------------------------------------------------
ruby_cpp: $(SRCS)
$(SWIG) -c++ -ruby $(SWIGOPT) $(INTERFACE)
$(CXX) -c $(CCSHARED) $(CFLAGS) $(ISRCS) $(SRCS) $(INCLUDE) $(RUBY_INCLUDE)
$(CXXSHARED) $(OBJS) $(IOBJS) $(LIBS) $(CPP_DLLIBS) -o $(TARGET)$(SO)
# -----------------------------------------------------------------
# Build statically linked Ruby interpreter
#
# These should only be used in conjunction with the %include embed.i
# library file
# -----------------------------------------------------------------
RUBY_LIB = @RUBYLIB@
RUBY_LIBOPTS = @RUBYLINK@ @LIBS@ $(SYSLIBS)
ruby_static: $(SRCS)
$(SWIG) -ruby -lembed.i $(SWIGOPT) $(INTERFACE)
$(CC) $(CFLAGS) @LINKFORSHARED@ $(ISRCS) $(SRCS) $(INCLUDE) \
$(RUBY_INCLUDE) $(LIBS) -L$(RUBY_LIB) $(RUBY_LIBOPTS) -o $(TARGET)
ruby_static_cpp: $(SRCS)
$(SWIG) -c++ -ruby -lembed.i $(SWIGOPT) $(INTERFACE)
$(CXX) $(CFLAGS) $(ISRCS) $(SRCS) $(INCLUDE) \
$(RUBY_INCLUDE) $(LIBS) -L$(RUBY_LIB) $(RUBY_LIBOPTS) -o $(TARGET)
##################################################################
##### SWIG ######
##################################################################

View file

@ -1,6 +1,6 @@
SWIG Examples
The "perl5", "python", "tcl", "guile", "java", and "mzscheme"
The "perl5", "python", "tcl", "guile", "java", "mzscheme", and "ruby"
directories contain a very simple example. The "GIFPlot" contains a
more complicated example that illustrates some of SWIG's more advanced
capabilities.

View file

@ -43,6 +43,7 @@ language:
<li><a href="guile/index.html">Guile</a>
<li><a href="java/index.html">Java</a>
<li><a href="mzscheme/index.html">Mzscheme</a>
<li><a href="ruby/index.html">Ruby</a>
</ul>
<h2>Real Life</h2>

View file

@ -0,0 +1,18 @@
TOP = ../..
SWIG = $(TOP)/../swig
SRCS =
TARGET = example
INTERFACE = example.i
all::
$(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \
TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' ruby
static::
$(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \
TARGET='myruby' INTERFACE='$(INTERFACE)' ruby_static
clean::
rm -f *_wrap* *.o *~ *.so myruby .~* core

View file

@ -0,0 +1,24 @@
/* File : example.i */
%module example
/* A few preprocessor macros */
#define ICONST 42
#define FCONST 2.1828
#define CCONST 'x'
#define SCONST "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 statements also produce constants */
const int iconst = 37;
const double fconst = 3.14;

View file

@ -0,0 +1,66 @@
<html>
<head>
<title>SWIG:Examples:ruby:constants</title>
</head>
<body bgcolor="#ffffff">
<tt>SWIG/Examples/ruby/constants/</tt>
<hr>
<H2>Wrapping C Constants</H2>
<tt>$Header$</tt><br>
<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,23 @@
# file: run.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 "SCONST = ", Example::SCONST, " (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,85 @@
<head>
<title>SWIG:Examples:ruby</title>
</head>
<body bgcolor="#ffffff">
<H1>SWIG Ruby Examples</H1>
<tt>$Header$</tt><br>
<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.
</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>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
sending a message to <a href="mailto:swig-dev@cs.uchicago.edu">swig-dev@cs.uchicago.edu</a>.
</body>
</html>

View file

@ -0,0 +1,18 @@
TOP = ../..
SWIG = $(TOP)/../swig
SRCS = example.c
TARGET = example
INTERFACE = example.i
all::
$(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \
TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' ruby
static::
$(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \
TARGET='myruby' INTERFACE='$(INTERFACE)' ruby_static
clean::
rm -f *_wrap* *.o *~ *.so myruby .~* core

View file

@ -0,0 +1,18 @@
/* File : example.c */
/* A global variable */
double Foo = 3.0;
/* Compute the greatest common divisor of positive integers */
int gcd(int x, int y) {
int g;
g = y;
while (x > 0) {
g = x;
x = y % x;
y = g;
}
return g;
}

View file

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

View file

@ -0,0 +1,99 @@
<html>
<head>
<title>SWIG:Examples:ruby:simple</title>
</head>
<body bgcolor="#ffffff">
<tt>SWIG/Examples/ruby/simple/</tt>
<hr>
<H2>Simple Ruby Example</H2>
<tt>$Header$</tt><br>
<p>
This example illustrates how you can hook Ruby to a very simple C program containing
a function and a global variable.
<h2>The C Code</h2>
Suppose you have the following C code:
<blockquote>
<pre>
/* File : example.c */
/* A global variable */
double Foo = 3.0;
/* Compute the greatest common divisor of positive integers */
int gcd(int x, int y) {
int g;
g = y;
while (x > 0) {
g = x;
x = y % x;
y = g;
}
return g;
}
</pre>
</blockquote>
<h2>The SWIG interface</h2>
Here is a simple SWIG interface file:
<blockquote>
<pre>
/* File: example.i */
%module example
extern int gcd(int x, int y);
extern double Foo;
</pre>
</blockquote>
<h2>Compilation</h2>
<ol>
<li><tt>swig -ruby <a href="example.i">example.i</a></tt>
<p>
<li>Compile <tt><a href="example_wrap.c">example_wrap.c</a></tt> and <tt><a href="example.c">example.c</a></tt>
to create the extension <tt>example.so</tt>.
</ol>
<h2>Using the extension</h2>
Click <a href="run.rb">here</a> to see a script that calls our C functions from Ruby.
<h2>Key points</h2>
<ul>
<li>Use the <tt>require</tt> function to load your extension library from Ruby. For example:
<blockquote>
<pre>
require 'example'
</pre>
</blockquote>
<li>C functions work just like Ruby functions. For example:
<blockquote>
<pre>
g = Example.gcd(42,105)
</pre>
</blockquote>
<li>C global variables are accessed through module method. For example:
<blockquote>
<pre>
a = Example.Foo
</pre>
</blockquote>
</ul>
<hr>
</body>
</html>

View file

@ -0,0 +1,21 @@
# file: run.rb
require 'example'
# Call our gcd() function
x = 42
y = 105
g = Example.gcd(x,y)
printf "The gcd of %d and %d is %d\n",x,y,g
# Manipulate the Foo global variable
# Output its current value
print "Foo = ", Example.Foo, "\n"
# Change its value
Example.Foo = 3.1415926
# See if the change took effect
print "Foo = ", Example.Foo, "\n"