From 1c3fec7f2a8dc74d6489ecf5517c4c84a31a337c Mon Sep 17 00:00:00 2001
From: Gonzalo Garramuno This chapter describes SWIG's support of Ruby. SWIG 1.3 is known to work with Ruby versions 1.6 and later.
Given the choice, you should use the latest stable version of Ruby. You
should also determine if your system supports shared libraries and
@@ -717,6 +1048,8 @@ the compilation process will vary. This chapter covers most SWIG features, but in less depth than
is found in earlier chapters. At the very least, make sure you also
read the "SWIG Basics"
@@ -725,40 +1058,56 @@ of Ruby. To build a Ruby module, run SWIG using the -ruby
option: If building a C++ extension, add the -c++
option: This creates a file example_wrap.c (example_wrap.cxx
if compiling a C++ extension) that contains all of the code needed to
build a Ruby extension module. To finish building the module, you need
@@ -766,45 +1115,63 @@ to compile this file and link it with the rest of your program. In order to compile the wrapper code, the compiler needs the ruby.h
header file. This file is usually contained in a directory such as The exact location may vary on your machine, but the above
location is typical. If you are not entirely sure where Ruby is
installed, you can run Ruby to find out. For example: Ruby extension modules are typically compiled into shared
libraries that the interpreter loads dynamically at runtime. Since the
exact commands for doing this vary from platform to platform, your best
@@ -813,64 +1180,98 @@ file from the Ruby distribution: Create a file called extconf.rb that
looks like the following: Type the following to build the extension: Of course, there is the problem that mkmf does not work
correctly on all platforms, e.g, HPUX. If you need to add your own make
rules to the file that extconf.rb produces, you
@@ -878,15 +1279,21 @@ can add this: to the end of the extconf.rb file. If
for some reason you don't want to use the standard approach, you'll
need to determine the correct compiler and linker flags for your build
@@ -895,16 +1302,22 @@ operating system would look something like this: For other platforms it may be necessary to compile with the -fPIC
option to generate position-independent code. If in doubt, consult the
manual pages for your compiler and linker to determine the correct set
@@ -913,15 +1326,21 @@ for additional information. Ruby module names must be capitalized,
but the convention for Ruby feature names is to use
lowercase names. So, for example, the Etc extension
@@ -929,15 +1348,21 @@ module is imported by requiring the etc feature: To stay consistent with this practice, you should always
specify a lowercase module name with SWIG's %module
directive. SWIG will automatically correct the resulting Ruby module
@@ -946,25 +1371,35 @@ begins with: will result in an extension module using the feature name
"example" and Ruby module name "Example". An alternative approach to dynamic linking is to rebuild the
Ruby interpreter with your extension module added to it. In the past,
this approach was sometimes necessary due to limitations in dynamic
@@ -974,6 +1409,8 @@ this approach unless there is really no other option. The usual procedure for adding a new module to Ruby involves
finding the Ruby source, adding an entry to the ext/Setup
file, adding your directory to the list of extensions in the file, and
@@ -981,30 +1418,42 @@ finally rebuilding Ruby. On most machines, C++ extension modules should be linked
using the C++ compiler. For example: If you've written an extconf.rb script
to automatically generate a Makefile for your C++
extension module, keep in mind that (as of this writing) Ruby still
@@ -1018,20 +1467,28 @@ extension, e.g. Building a SWIG extension to Ruby under Windows 95/NT is
roughly similar to the process used with Unix. Normally, you will want
to produce a DLL that can be loaded into the Ruby interpreter. For all
@@ -1041,16 +1498,22 @@ your code into a DLL by typing: The remainder of this section covers the process of compiling
SWIG-generated Ruby extensions with Microsoft Visual C++ 6 (i.e. within
the Developer Studio IDE, instead of using the command line tools). In
@@ -1060,30 +1523,42 @@ files. If you are developing your application within Microsoft
developer studio, SWIG can be invoked as a custom build option. The
process roughly follows these steps : Now, assuming all went well, SWIG will be automatically
invoked when you build your project. Any changes made to the interface
file will result in SWIG being automatically invoked to produce a new
@@ -1149,57 +1642,81 @@ example if you have this ruby file run.rb: Ensure the dll just built is in your path or current
directory, then run the Ruby script from the DOS/Command prompt: This section describes the basics of how SWIG maps C or C++
declarations in your SWIG interface files to Ruby constructs. The SWIG %module directive specifies
the name of the Ruby module. If you specify: then everything is wrapped into a Ruby module named Example
that is nested directly under the global module. You can specify a more
deeply nested module by specifying the fully-qualified module name in
@@ -1207,15 +1724,21 @@ quotes, e.g. An alternate method of specifying a nested module name is to
use the -prefix
option on the SWIG command line. The prefix that you specify with this
@@ -1225,71 +1748,101 @@ at the top of your SWIG interface file: will result in a nested module name of Foo::Bar::Spam,
but you can achieve the same
effect by specifying: and then running SWIG with the -prefix command
line option: Starting with SWIG 1.3.20, you can also choose to wrap
everything into the global module by specifying the -globalmodule
option on the SWIG command line, i.e. Note that this does not relieve you of the requirement of
specifying the SWIG module name with the %module
directive (or the -module command-line option) as
@@ -1297,6 +1850,8 @@ described earlier. When choosing a module name, do not use the same name as a
built-in Ruby command or standard module name, as the results may be
unpredictable. Similarly, if you're using the -globalmodule
@@ -1306,57 +1861,81 @@ Ruby's built-in names. Global functions are wrapped as Ruby module methods. For
example, given the SWIG interface file example.i:
and C source file example.c: SWIG will generate a method fact in the Example
module that can be used like so: C/C++ global variables are wrapped as a pair of singleton
methods for the module: one to get the value of the global variable and
one to set it. For example, the following SWIG interface file declares
@@ -1364,105 +1943,149 @@ two global variables: Now look at the Ruby interface: If you make an error in variable assignment, you will receive
an error message. For example: If a variable is declared as const, it
is wrapped as a read-only variable. Attempts to modify its value will
result in an error. To make ordinary variables read-only, you can also use the %immutable
directive. For example: The %immutable directive stays in
effect until it is explicitly disabled using %mutable.
C/C++ constants are wrapped as module constants initialized
to the appropriate value. To create a constant, use #define
or the %constant directive. For example: Remember to use the :: operator in Ruby to get at these
constant values, e.g. "Opaque" pointers to arbitrary C/C++ types (i.e. types that
aren't explicitly declared in your SWIG interface file) are wrapped as
data objects. So, for example, consider a SWIG interface file
@@ -1470,53 +2093,75 @@ containing only the declarations: For this case, the get_foo() method
returns an instance of an internally generated Ruby class: A NULL pointer is always represented by
the Ruby nil object. C/C++ structs are wrapped as Ruby classes, with accessor
methods (i.e. "getters" and "setters") for all of the struct members.
For example, this struct declaration: gets wrapped as a Vector class, with
Ruby instance methods x, x=,
y and y=. These methods can
@@ -1524,20 +2169,28 @@ be used to access structure data from Ruby as follows: Similar access is provided for unions and the public data
members of C++ classes. const members of a structure are
read-only. Data members can also be forced to be read-only using the %immutable
directive (in C++, private may also be used). For
@@ -1545,15 +2198,21 @@ example: When char * members of a structure are
wrapped, the contents are assumed to be dynamically allocated using malloc
or new (depending on whether or not SWIG is run
@@ -1564,33 +2223,47 @@ this is not the behavior you want, you will have to use a typemap
+
+
Array members are normally wrapped as read-only. For example,
this code: produces a single accessor function like this: If you want to set an array member, you will need to supply a
"memberin" typemap described in the section on typemaps.
As a special case, SWIG does generate code to set array members of type
@@ -1599,37 +2272,53 @@ structure). When structure members are wrapped, they are handled as
pointers. For example, generates accessor functions such as this: Like structs, C++ classes are wrapped by creating a new Ruby
class of the same name with accessor methods for the public class
member data. Additionally, public member functions for the class are
@@ -1639,108 +2328,154 @@ declaration: SWIG would create a List class with: In Ruby, these functions are used as follows: The SWIG type-checker is fully aware of C++ inheritance.
Therefore, if you have classes like this: those classes are wrapped into a hierarchy of Ruby classes
that reflect the same inheritance structure. All of the usual Ruby
utility methods work normally: Furthermore, if you have a function like this: then the function spam() accepts Parent*
or a pointer to any class derived from Parent. Until recently, the Ruby module for SWIG didn't support
multiple inheritance, and this is still the default behavior. This
doesn't mean that you can't wrap C++ classes which inherit from
@@ -1751,15 +2486,21 @@ interface file with a declaration like this: For this case, the resulting Ruby class (Derived)
will only consider Base1 as its superclass. It
won't inherit any of Base2's member functions or
@@ -1770,15 +2511,21 @@ you'll see a warning message like: Starting with SWIG 1.3.20, the Ruby module for SWIG provides
limited support for multiple inheritance. Because the approach for
dealing with multiple inheritance introduces some limitations, this is
@@ -1787,29 +2534,41 @@ command-line option: Using our previous example, if your SWIG interface file
contains a declaration like this: and you run SWIG with the -minherit
command-line option, then you will end up with a Ruby class Derived
that appears to "inherit" the member data and functions from both Base1
@@ -1822,15 +2581,21 @@ i.e. Observe that after the nested Impl
module for a class is defined, it is mixed-in to the class itself. Also
observe that the Derived::Impl module first
@@ -1839,21 +2604,29 @@ mixes-in its base classes' Impl modules, thus
+
+
The primary drawback is that, unlike the default mode of
operation, neither Base1 nor Base2
is a true superclass of Derived anymore: In most cases, this is not a serious problem since objects of
type Derived will otherwise behave as though they
inherit from both Base1 and Base2
@@ -1862,133 +2635,191 @@ Typing"). C++ overloaded functions, methods, and constructors are
mostly supported by SWIG. For example, if you have two functions like
this: You can use them in Ruby in a straightforward manner: Similarly, if you have a class like this, you can write Ruby code like this: Overloading support is not quite as flexible as in C++.
Sometimes there are methods that SWIG can't disambiguate. For example: or If declarations such as these appear, you will get a warning
message like this: To fix this, you either need to ignore or rename one of the
methods. For example: or SWIG resolves overloaded functions and methods using a
disambiguation scheme that ranks and sorts declarations according to a
set of type-precedence rules. The order in which declarations appear in
@@ -1997,36 +2828,50 @@ arises--in this case, the first declaration takes precedence. Please refer to the "SWIG
and C++" chapter for more information about overloading. For the most part, overloaded operators are handled
automatically by SWIG and do not require any special treatment on your
part. So if your class declares an overloaded addition operator, e.g. the resulting Ruby class will also support the addition (+)
method correctly. For cases where SWIG's built-in support is not sufficient, C++
operators can be wrapped using the %rename
directive (available on SWIG 1.3.10 and later releases). All you need
@@ -2035,39 +2880,55 @@ example: Now, in Ruby, you can do this: More details about wrapping C++ operators into Ruby operators
is discussed in the section
on operator overloading. SWIG is aware of C++ namespaces, but namespace names do not
appear in the module nor do namespaces result in a module that is
broken up into submodules or packages. For example, if you have a file
@@ -2075,43 +2936,61 @@ like this, it works in Ruby as follows: If your program has more than one namespace, name conflicts
(if any) can be resolved using %rename For
example: If you have more than one namespace and your want to keep
their symbols separate, consider wrapping them as separate SWIG
modules. For example, make the module name the same as the namespace
@@ -2121,11 +3000,15 @@ identical symbol names, well, then you get what you deserve. C++ templates don't present a huge problem for SWIG. However,
in order to create wrappers, you have to tell SWIG to create wrappers
for a particular template instantiation. To do this, you use the %template
@@ -2133,33 +3016,47 @@ directive. For example: In Ruby: On a related note, the standard SWIG library contains a
number of modules that provide typemaps for standard C++ library
classes (such as std::pair, std::string
@@ -2172,15 +3069,21 @@ wrapping has a function that expects a vector of floats: Rather than go through the hassle of writing an "in" typemap
to convert an array of Ruby numbers into a
std::vector<float>, you can just use the std_vector.i
@@ -2188,33 +3091,47 @@ module from the standard SWIG library: Ruby's STL wrappings provide additional methods to make them
behave more similarly to Ruby's native classes. Thus, you can do, for example: The SWIG Ruby module provides also the ability for all the STL
containers to carry around Ruby native objects (Fixnum, Classes, etc)
making them act almost like Ruby's own Array, Hash, etc. To
@@ -2224,124 +3141,180 @@ like: This vector can then contain any Ruby object, making them
almost identical to Ruby's own Array class. Obviously, there is a lot more to template wrapping than
shown in these examples. More details can be found in the SWIG and C++
chapter. Some containers in the STL allow you to modify their default
behavior by using so called functors or function objects.
Functors are often just a very simple struct with operator()
@@ -2351,6 +3324,8 @@ liking. The Ruby STL mappings allows you to modify those containers
that
support functors using Ruby procs or methods, instead.
@@ -2362,131 +3337,189 @@ and std::multimap. The functors in swig are called swig::UnaryFunction
and swig::BinaryFunction. As an example, if given this swig file: You can then use the set from Ruby with or without a proc
object as a predicate: The STL is well known by the use of iterators. There
+
+
+ The STL is well known for the use of iterators. There
are a number of iterators possible with different properties, but in
general there are two main categories: const iterators and non-const
iterators. The const iterators can access and not modify the
@@ -2495,31 +3528,47 @@ modify the values. The Ruby STL wrappings support both type of iterators by using
a proxy class in-between. This proxy class is swig::Iterator or
-swig::ConstIterator. They are both template
+swig::ConstIterator. Derived from them are template
classes that need to be initialized with the actual iterator for the
container you are wrapping and often times with the beginning and
-ending points of the iteration range.30 SWIG and Ruby
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
30.1 Preliminaries
+
+
30.1.1 Running SWIG
+
+
$ swig -ruby example.i
+
+
$ swig -c++ -ruby example.i
+
+
30.1.2 Getting the
right header files
+
+
/usr/lib/ruby/1.8/x86_64-linux-gnu/ruby.h
+
+
/usr/local/lib/ruby/1.6/i686-linux/ruby.h$ ruby -e 'puts $:.join("\n")'
+
+
/usr/local/lib/ruby/site_ruby/1.6 /usr/local/lib/ruby/site_ruby/1.6/i686-linux
/usr/local/lib/ruby/site_ruby /usr/local/lib/ruby/1.6 /usr/local/lib/ruby/1.6/i686-linux .
30.1.3 Compiling a
dynamic module
+
+
+
+
+
+
require 'mkmf'
+
+
create_makefile('example')$ ruby extconf.rb
+
+
$ make
$ make install
open("Makefile", "a") { |mf|
+
+
puts <<EOM
# Your make rules go here
EOM
}$ swig -ruby example.i
+
+
$ gcc -c example.c
$ gcc -c example_wrap.c -I/usr/local/lib/ruby/1.6/i686-linux
$ gcc -shared example.o example_wrap.o -o example.so
30.1.4 Using your
module
+
+
# The feature name begins with a lowercase letter...
+
+
require 'etc'
# ... but the module name begins with an uppercase letter
puts "Your login name: #{Etc.getlogin}"%module example
+
+
30.1.5 Static
linking
+
+
30.1.6 Compilation
of C++ extensions
+
+
$ swig -c++ -ruby example.i
+
+
$ g++ -c example.cxx
$ g++ -c example_wrap.cxx -I/usr/local/lib/ruby/1.6/i686-linux
$ g++ -shared example.o example_wrap.o -o example.so
require 'mkmf'
+
+
$libs = append_library($libs, "supc++")
create_makefile('example')30.2 Building Ruby
Extensions under Windows 95/NT
+
+
C:\swigtest> ruby extconf.rb
+
+
C:\swigtest> nmake
C:\swigtest> nmake install
30.2.1 Running
SWIG from Developer Studio
+
+
+
+
+
+
# file: run.rb
+
+
require 'Example'
# Call a c function
print "Foo = ", Example.Foo, "\n"C:\swigtest> ruby run.rb
+
+
Foo = 3.030.3 The
Ruby-to-C/C++ Mapping
+
+
30.3.1 Modules
+
+
%module example
+
+
%module "foo::bar::spam"
+
+
+
+
%module "foo::bar::spam"
+
+
+
+
%module spam
+
+
+
+
$ swig -ruby -prefix "foo::bar::" example.i
+
+
$ swig -ruby -globalmodule example.i
+
+
30.3.2 Functions
+
+
%module example
+
+
int fact(int n);int fact(int n) {
+
+
if (n == 0)
return 1;
return (n * fact(n-1));
}$ irb
+
+
irb(main):001:0> require 'example'
true
irb(main):002:0> Example.fact(4)
2430.3.3 Variable
Linking
+
+
// SWIG interface file with global variables
+
+
%module example
...
%inline %{
extern int variable1;
extern double Variable2;
%}
...$ irb
+
+
irb(main):001:0> require 'Example'
true
irb(main):002:0> Example.variable1 = 2
2
irb(main):003:0> Example.Variable2 = 4 * 10.3
41.2
irb(main):004:0> Example.Variable2
41.2irb(main):005:0> Example.Variable2 = "hello"
+
+
TypeError: no implicit conversion to float from string
from (irb):5:in `Variable2='
from (irb):5%immutable;
+
+
%inline %{
extern char *path;
%}
%mutable;30.3.4 Constants
+
+
#define PI 3.14159
+
+
#define VERSION "1.0"
%constant int FOO = 42;
%constant const char *path = "/usr/local";
const int BAR = 32;$ irb
+
+
irb(main):001:0> require 'Example'
true
irb(main):002:0> Example::PI
3.1415930.3.5 Pointers
+
+
Foo *get_foo();
+
+
void set_foo(Foo *foo);irb(main):001:0> foo = Example::get_foo()
+
+
#<SWIG::TYPE_p_Foo:0x402b1654>30.3.6 Structures
+
+
struct Vector {
+
+
double x, y;
};$ irb
+
+
irb(main):001:0> require 'Example'
true
irb(main):002:0> f = Example::Vector.new
#<Example::Vector:0x4020b268>
irb(main):003:0> f.x = 10
nil
irb(main):004:0> f.x
10.0struct Foo {
+
+
...
%immutable;
int x; /* Read-only members */
char *name;
%mutable;
...
};struct Foo {
+
+
int x[50];
};int *Foo_x_get(Foo *self) {
+
+
return self->x;
};struct Foo {
+
+
...
};
struct Bar {
Foo f;
};Foo *Bar_f_get(Bar *b) {
+
+
return &b->f;
}
void Bar_f_set(Bar *b, Foo *val) {
b->f = *val;
}30.3.7 C++ classes
+
+
class List {
+
+
public:
List();
~List();
int search(char *item);
void insert(char *item);
void remove(char *item);
char *get(int n);
int length;
static void print(List *l);
};
+
+
+
+
require 'Example'
+
+
l = Example::List.new
l.insert("Ale")
l.insert("Stout")
l.insert("Lager")
Example.print(l)
l.length()
----- produces the following output
Lager
Stout
Ale
330.3.8 C++
Inheritance
+
+
class Parent {
+
+
...
};
class Child : public Parent {
...
};irb(main):001:0> c = Child.new
+
+
#<Bar:0x4016efd4>
irb(main):002:0> c.instance_of? Child
true
irb(main):003:0> b.instance_of? Parent
false
irb(main):004:0> b.is_a? Child
true
irb(main):005:0> b.is_a? Parent
true
irb(main):006:0> Child < Parent
true
irb(main):007:0> Child > Parent
falsevoid spam(Parent *f);
+
+
class Derived : public Base1, public Base2
+
+
{
...
};example.i:5: Warning(802): Warning for Derived: Base Base2 ignored.
+
+
Multiple inheritance is not supported in Ruby.$ swig -c++ -ruby -minherit example.i
+
+
class Derived : public Base1, public Base2
+
+
{
...
};class Base1
+
+
module Impl
# Define Base1 methods here
end
include Impl
end
class Base2
module Impl
# Define Base2 methods here
end
include Impl
end
class Derived
module Impl
include Base1::Impl
include Base2::Impl
# Define Derived methods here
end
include Impl
endobj = Derived.new
+
+
obj.is_a? Base1 # this will return false...
obj.is_a? Base2 # ... and so will this30.3.9 C++
Overloaded Functions
+
+
void foo(int);
+
+
void foo(char *c);irb(main):001:0> foo(3) # foo(int)
+
+
irb(main):002:0> foo("Hello") # foo(char *c)class Foo {
+
+
public:
Foo();
Foo(const Foo &);
...
};irb(main):001:0> f = Foo.new # Create a Foo
+
+
irb(main):002:0> g = Foo.new(f) # Copy fvoid spam(int);
+
+
void spam(short);void foo(Bar *b);
+
+
void foo(Bar &b);example.i:12: Warning(509): Overloaded spam(short) is shadowed by spam(int)
+
+
at example.i:11.
%rename(spam_short) spam(short);
+
+
...
void spam(int);
void spam(short); // Accessed as spam_short%ignore spam(short);
+
+
...
void spam(int);
void spam(short); // Ignored30.3.10 C++
Operators
+
+
class Complex {
+
+
...
Complex operator+(Complex &);
...
};%rename(add_complex) operator+(Complex &, Complex &);
+
+
...
Complex operator+(Complex &, Complex &);a = Example::Complex.new(2, 3)
+
+
b = Example::Complex.new(4, -1)
c = Example.add_complex(a, b)30.3.11 C++
namespaces
+
+
%module example
+
+
namespace foo {
int fact(int n);
struct Vector {
double x,y,z;
};
};irb(main):001:0> require 'example'
+
+
true
irb(main):002:0> Example.fact(3)
6
irb(main):003:0> v = Example::Vector.new
#<Example::Vector:0x4016f4d4>
irb(main):004:0> v.x = 3.4
3.4
irb(main):004:0> v.y
0.0%rename(Bar_spam) Bar::spam;
+
+
namespace Foo {
int spam();
}
namespace Bar {
int spam();
}30.3.12 C++
templates
+
+
%module example
+
+
%{
#include "pair.h"
%}
template<class T1, class T2>
struct pair {
typedef T1 first_type;
typedef T2 second_type;
T1 first;
T2 second;
pair();
pair(const T1&, const T2&);
~pair();
};
%template(Pairii) pair<int,int>;irb(main):001:0> require 'example'
+
+
true
irb(main):002:0> p = Example::Pairii.new(3, 4)
#<Example:Pairii:0x4016f4df>
irb(main):003:0> p.first
3
irb(main):004:0> p.second
430.3.12.1 C++
Standard Template Library (STL)
+
+
%module example
+
+
float sum(const std::vector<float>& values);%module example
+
+
%include std_vector.i
float sum(const std::vector<float>& values);v = IntVector.new
+
+
v << 2
v << 3
v << 4
v.each { |x| puts x }
=> 2
3
4
v.delete_if { |x| x == 3 }
=> [2,4]
+
+
+
+
%{
+
+
std::vector< swig::GC_VALUE > NativeVector;
+
+
%}
+
+
+
+
%template(NativeVector) std::vector< swig::GC_VALUE >;
+
+
+
+
+
+
include NativeVector
+
+
+
+
v = NativeVector.new
+
+
v << 1
+
+
v <<
[1,2]
+
+
v <<
'hello'
+
+
+
+
class A; end
+
+
+
+
v <<
A.new
+
+
+
+
puts v
+
+
=>
[1, [1,2], 'hello', #<A:0x245325>]
+
+
30.3.12.1.2
C++
STL Functors
+
+
+
+
For C++ predicates (ie. functors that must return bool as a result) swig::UnaryPredicate
and swig::BinaryPredicate
are provided.
+
+
+
+
%include std_set.i
+
+
+
+
%typemap(IntSet) std::set< int, swig::BinaryPredicate
>;
+
+
include Intset
+
+
+
+
# Default sorting behavior defined in C++
+
+
a = IntSet.new
+
+
a << 1
+
+
a << 2
+
+
a << 3
+
+
a
+
+
=>
[1,2,3]
+
+
+
+
# Custom sorting behavior defined by a Ruby proc
+
+
b << 1
+
+
b << 2
+
+
b << 3
+
+
b
+
+
=>
[3,2,1] 30.3.12.1.3
C++ STL Iterators
-
The SWIG STL library already provides typemaps to all the standard containers to do this wrapping automatically for you, but if -you have your own STL-like class, you will need to write your own -typemap for them.
+you have your own STL-like iterator, you will need to write your own +typemap for them. For out typemaps, the special functions make_const_iterator and make_nonconst_iterator are provided. + +These can be used either like:
+ +The iterators support the next() and previous() functions -to both increment/decrement the iterator and return the current (old) -value, and the functions decr() -and incr() to -just change the iterator without returning anything. The -value of the iterator can be accessed with value(). - For non-const iterators, a set() function + + +
The iterators support a next() and previous() member function to +just change the iterator without returning anything. previous() +should obviously only be used for bidirectional iterators. You +can also advance the iterator multiple steps by using standard math +operations like +=.
+ +The +value the iterator points at can be accessed with value() -- this is equivalent to dereferencing it with *i. + For non-const iterators, a value=() function is also provided which allows you to change the value pointed by the -iterator.
+iterator. This is equivalent to the C++ construct of dereferencing and assignment, like *i = something. + + @@ -2527,27 +3576,41 @@ iterator. + +its iterator can then be used from Ruby like:
+ + +Its iterator can then be used from Ruby like:
+ + @@ -2556,66 +3619,112 @@ iterator. + + include DoublevectorIf you'd rather have STL classes without any iterators, you should define -DSWIG_NO_EXPORT_ITERATOR_METHODS when running swig.
+ + +In certain C++ programs, it is common to use classes that have been wrapped by so-called "smart pointers." Generally, this involves the use of a template class that implements operator->() @@ -2630,41 +3741,59 @@ like this:
+ +template<class T> class SmartPtr {
...
T *operator->();
...
}
+
+
Then, if you have a class like this,
+ +class Foo {
public:
int x;
int bar();
};
+
+
A smart pointer would be used in C++ as follows:
+ +SmartPtr<Foo> p = CreateFoo(); // Created somehow (not shown)+ +
...
p->x = 3; // Foo::x
int y = p->bar(); // Foo::bar
To wrap this in Ruby, simply tell SWIG about the SmartPtr class and the low-level Foo object. Make sure you instantiate SmartPtr using %template @@ -2672,48 +3801,68 @@ if necessary. For example:
+ +%module example+ +
...
%template(SmartPtrFoo) SmartPtr<Foo>;
...
Now, in Ruby, everything should just "work":
+ +irb(main):001:0> p = Example::CreateFoo() # Create a smart-pointer somehow+ +
#<Example::SmartPtrFoo:0x4016f4df>
irb(main):002:0> p.x = 3 # Foo::x
3
irb(main):003:0> p.bar() # Foo::bar
If you ever need to access the underlying pointer returned by operator->() itself, simply use the __deref__() method. For example:
+ +irb(main):004:0> f = p.__deref__() # Returns underlying Foo *+ +
SWIG's Ruby module supports cross-language polymorphism (a.k.a. the "directors" feature) similar to that for SWIG's Python module. Rather than duplicate the information presented in the Python chapter, this @@ -2722,11 +3871,15 @@ using this feature with Ruby.
+ +Whenever a C++ director class routes one of its virtual member function calls to a Ruby instance method, there's always the possibility that an exception will be raised in the Ruby code. By @@ -2738,15 +3891,21 @@ is raised. The following code should suffice in most cases:
+ +%feature("director:except") {
throw Swig::DirectorMethodException($error);
}
+
+
When this feature is activated, the call to the Ruby instance method is "wrapped" using the rb_rescue2() function from Ruby's C API. If any Ruby exception is raised, it will be @@ -2754,10 +3913,14 @@ caught here and a C++ exception is raised in its place.
+ +Ruby has several common naming conventions. Constants are generally in upper case, module and class names are in camel case and methods are @@ -2765,37 +3928,53 @@ in lower case with underscores. For example:
+ +Prior to version 1.3.28, SWIG did not support these Ruby conventions. The only modifications it made to names was to capitalize the first letter of constants (which includes module and class names).
+ +SWIG 1.3.28 introduces the new -autorename command line parameter. When this parameter is specified, SWIG will automatically change @@ -2804,20 +3983,28 @@ naming conventions. For example:
+ +$ swig -ruby -autorename example.i+ +
To disable renaming use the -noautorename command line option.
+ +Since this change significantly changes the wrapper code generated by SWIG, it is turned off by default in SWIG 1.3.28. However, it is @@ -2825,11 +4012,15 @@ planned to become the default option in future releases.
+ +It's a fairly common practice in the Ruby built-ins and standard library to provide aliases for method names. For example, Array#size is an alias for Array#length. If you would like @@ -2840,45 +4031,63 @@ For example:
+ +class MyArray {
public:
// Construct an empty array
MyArray();
// Return the size of this array
size_t length() const;
};
%extend MyArray {
// MyArray#size is an alias for MyArray#length
size_t size() const {
return $self->length();
}
}
+
+
A better solution is to use the %alias directive (unique to SWIG's Ruby module). The previous example could then be rewritten as:
+ +// MyArray#size is an alias for MyArray#length+ +
%alias MyArray::length "size";
class MyArray {
public:
// Construct an empty array
MyArray();
// Return the size of this array
size_t length() const;
};
Multiple aliases can be associated with a method by providing a comma-separated list of aliases to the %alias directive, e.g.
+ +%alias MyArray::length "amount,quantity,size";+ +
From an end-user's standpoint, there's no functional difference between these two approaches; i.e. they should get the same result from calling either MyArray#size or MyArray#length. @@ -2889,6 +4098,8 @@ example.
+ +Note that the %alias directive is implemented using SWIG's "features" mechanism and so the same name matching rules used for other kinds of features apply (see the chapter @@ -2897,11 +4108,15 @@ Features") for more details).
+ +Ruby methods that return a boolean value and end in a question mark are known as predicate methods. Examples of predicate methods in @@ -2914,6 +4129,8 @@ marked as predicate methods.
+ +One cumbersome solution to this problem is to rename the method (using SWIG's %rename directive) and provide a custom typemap that converts the function's actual return @@ -2922,43 +4139,61 @@ For example:
+ +%rename("is_it_safe?") is_it_safe();
%typemap(out) int is_it_safe
"$result = ($1 != 0) ? Qtrue : Qfalse;";
int is_it_safe();
+
+
A better solution is to use the %predicate directive (unique to SWIG's Ruby module) to designate a method as a predicate method. For the previous example, this would look like:
+ +%predicate is_it_safe();+ +
int is_it_safe();
This method would be invoked from Ruby code like this:
+ +irb(main):001:0> Example::is_it_safe?+ +
true
The %predicate directive is implemented using SWIG's "features" mechanism and so the same name matching rules used for other kinds of features apply (see the chapter on "Customization @@ -2966,10 +4201,14 @@ Features") for more details).
+ +Ruby methods that modify an object in-place and end in an exclamation mark are known as bang methods. An example of a bang method is Array#sort! which changes the ordering of @@ -2980,34 +4219,48 @@ methods that modify objects in place should be marked as bang methods.
+ +Bang methods can be marked using the %bang directive which is unique to the Ruby module and was introduced in SWIG 1.3.28. For example:
+ +%bang sort!(arr);+ +
int sort(int arr[]);
This method would be invoked from Ruby code like this:
+ +irb(main):001:0> Example::sort!(arr)+ +
The %bang directive is implemented using SWIG's "features" mechanism and so the same name matching rules used for other kinds of features apply (see the chapter on "Customization @@ -3015,25 +4268,35 @@ Features") for more details).
+ +Often times a C++ library will expose properties through getter and setter methods. For example:
+ +class Foo {
Foo() {}
int getValue() { return value_; }
void setValue(int value) { value_ = value; }
private:
int value_;
};
+
+
By default, SWIG will expose these methods to Ruby as get_value
and set_value. However, it more natural for these
methods to be exposed in Ruby as value and value=.
@@ -3041,182 +4304,260 @@ methods to be exposed in Ruby as value and value=.
+
+
irb(main):001:0> foo = Foo.new()
+
+
irb(main):002:0> foo.value = 5
irb(main):003:0> puts foo.value
This can be done by using the %rename directive:
+ +%rename("value") Foo::getValue();
%rename("value=") Foo::setValue(int value);
+
+
+ +
A common problem in some C programs is handling parameters passed as simple pointers. For example:
+ +void add(int x, int y, int *result) {
*result = x + y;
}
or
int sub(int *x, int *y) {
return *x-*y;
}
+
+
The easiest way to handle these situations is to use the typemaps.i file. For example:
+ +%module Example+ +
%include "typemaps.i"
void add(int, int, int *OUTPUT);
int sub(int *INPUT, int *INPUT);
In Ruby, this allows you to pass simple values. For example:
+ +a = Example.add(3,4)+ +
puts a
7
b = Example.sub(7,4)
puts b
3
Notice how the INPUT parameters allow integer values to be passed instead of pointers and how the OUTPUT parameter creates a return result.
+ +If you don't want to use the names INPUT or OUTPUT, use the %apply directive. For example:
+ +%module Example+ +
%include "typemaps.i"
%apply int *OUTPUT { int *result };
%apply int *INPUT { int *x, int *y};
void add(int x, int y, int *result);
int sub(int *x, int *y);
If a function mutates one of its parameters like this,
+ +void negate(int *x) {
*x = -(*x);
}
+
+
you can use INOUT like this:
+ +%include "typemaps.i"+ +
...
void negate(int *INOUT);
In Ruby, a mutated parameter shows up as a return value. For example:
+ +a = Example.negate(3)+ +
print a
-3
The most common use of these special typemap rules is to handle functions that return more than one value. For example, sometimes a function returns a result as well as a special error code:
+ +/* send message, return number of bytes sent, success code, and error_code */+ +
int send_message(char *text, int *success, int *error_code);
To wrap such a function, simply use the OUTPUT rule above. For example:
+ +%module example+ +
%include "typemaps.i"
...
int send_message(char *, int *OUTPUT, int *OUTPUT);
When used in Ruby, the function will return an array of multiple values.
+ +bytes, success, error_code = send_message("Hello World")
if not success
print "error #{error_code} : in send_message"
else
print "Sent", bytes
end
+
+
Another way to access multiple return values is to use the %apply rule. In the following example, the parameters rows and columns are related to SWIG as OUTPUT values through the use @@ -3224,38 +4565,54 @@ of %apply
+ +%module Example+ +
%include "typemaps.i"
%apply int *OUTPUT { int *rows, int *columns };
...
void get_dimensions(Matrix *m, int *rows, int*columns);
In Ruby:
+ +r, c = Example.get_dimensions(m)+ +
The SWIG %exception directive can be used to define a user-definable exception handler that can convert C/C++ errors into Ruby exceptions. The chapter on Customization @@ -3264,30 +4621,42 @@ class like the following :
+ +class DoubleArray {
private:
int n;
double *ptr;
public:
// Create a new array of fixed size
DoubleArray(int size) {
ptr = new double[size];
n = size;
}
// Destroy an array
~DoubleArray() {
delete ptr;
}
// Return the length of the array
int length() {
return n;
}
// Get an array item and perform bounds checking.
double getitem(int i) {
if ((i >= 0) && (i < n))
return ptr[i];
else
throw RangeError();
}
// Set an array item and perform bounds checking.
void setitem(int i, double val) {
if ((i >= 0) && (i < n))
ptr[i] = val;
else {
throw RangeError();
}
}
};
+
+
Since several methods in this class can throw an exception for an out-of-bounds access, you might want to catch this in the Ruby extension by writing the following in an interface file:
+ +%exception {
try {
$action
}
catch (const RangeError&) {
static VALUE cpperror = rb_define_class("CPPError", rb_eStandardError);
rb_raise(cpperror, "Range error.");
}
}
class DoubleArray {
...
};
+
+
The exception handling code is inserted directly into generated wrapper functions. When an exception handler is defined, errors can be caught and used to gracefully raise a Ruby exception @@ -3296,6 +4665,8 @@ error.
+ +As shown, the exception handling code will be added to every wrapper function. Because this is somewhat inefficient, you might consider refining the exception handler to only apply to specific @@ -3303,32 +4674,44 @@ methods like this:
+ +%exception getitem {
try {
$action
}
catch (const RangeError&) {
static VALUE cpperror = rb_define_class("CPPError", rb_eStandardError);
rb_raise(cpperror, "Range error in getitem.");
}
}
%exception setitem {
try {
$action
}
catch (const RangeError&) {
static VALUE cpperror = rb_define_class("CPPError", rb_eStandardError);
rb_raise(cpperror, "Range error in setitem.");
}
}
+
+
In this case, the exception handler is only attached to methods and functions named getitem and setitem.
+ +Since SWIG's exception handling is user-definable, you are not limited to C++ exception handling. See the chapter on Customization Features for more examples.
+ +One of the highlights of Ruby and most of its standard library is the use of blocks, which allow the easy creation of continuations and @@ -3337,592 +4720,896 @@ simplify the passing of many arguments to a class.
+ +In order to make your class constructor support blocks, you can take advantage of the %exception directive, which will get run after the C++ class' constructor was called.
+ +For example, this yields the class over after its
construction:
+
+
class Window+ +
{
public:
Window(int x, int y, int w, int h);
// .... other methods here ....
};
// Add support for yielding self in the Class' constructor.
%exception Window::Window {
$action
if (rb_block_given_p()) {
rb_yield(self);
}
}
Then, in ruby, it can be used like:
+ +For other methods, you can usually use a dummy parameter with a special in typemap, like:
+ +For more information on typemaps, see Typemaps.
+ +There are three ways to raise exceptions from C++ code to Ruby.
+ +The first way is to use SWIG_exception(int code, const char *msg). The following table shows the mappings from SWIG error codes to Ruby exceptions:
+ +|
+
+
SWIG_MemoryError
+
+
|
+
+
+
+
rb_eNoMemError
+
+
|
+
+
|
|
+
+
SWIG_IOError
+
+
|
+
+
+
+
rb_eIOError
+
+
|
+
+
|
|
+
+
SWIG_RuntimeError
+
+
|
+
+
+
+
rb_eRuntimeError
+
+
|
+
+
|
|
+
+
SWIG_IndexError
+
+
|
+
+
+
+
rb_eIndexError
+
+
|
+
+
|
|
+
+
SWIG_TypeError
+
+
|
+
+
+
+
rb_eTypeError
+
+
|
+
+
|
|
+
+
SWIG_DivisionByZero
+
+
|
+
+
+
+
rb_eZeroDivError
+
+
|
+
+
|
|
+
+
SWIG_OverflowError
+
+
|
+
+
+
+
rb_eRangeError
+
+
|
+
+
|
|
+
+
SWIG_SyntaxError
+
+
|
+
+
+
+
rb_eSyntaxError
+
+
|
+
+
|
|
+
+
SWIG_ValueError
+
+
|
+
+
+
+
rb_eArgError
+
+
|
+
+
|
|
+
+
SWIG_SystemError
+
+
|
+
+
+
+
rb_eFatal
+
+
|
+
+
|
|
+
+
SWIG_AttributeError
+
+
|
+
+
+
+
rb_eRuntimeError
+
+
|
+
+
|
|
+
+
SWIG_NullReferenceError
+
+
|
+
+
+
+
rb_eNullReferenceError*
+
+
|
+
+
|
|
+
+
SWIG_ObjectPreviouslyDeletedError
+
+
|
+
+
+
+
rb_eObjectPreviouslyDeleted*
+
+
|
+
+
|
|
+
+
SWIG_UnknownError
+
+
|
+
+
+
+
rb_eRuntimeError
+
+
|
+
+
|
|
+
+
* These error classes are created by
SWIG and are not built-in Ruby exception classes
+
+
|
+
+
||
| $input | + +Input object holding value to be converted. | + +|
| $symname | + +Name of function/method being wrapped | + +|
| $1...n | + +Argument being sent to the function | + +|
| $1_name | + +Name of the argument (if provided) | + +|
| $1_type | + +The actual C datatype matched by the typemap. | + +|
| $1_ltype | + +The assignable version of the C datatype matched by the typemap. | + +
| $result | + +Result object returned to target language. | + +|
| $symname | + +Name of function/method being wrapped | + +|
| $1...n | + +Argument being wrapped | + +|
| $1_name | + +Name of the argument (if provided) | + +|
| $1_type | + +The actual C datatype matched by the typemap. | + +|
| $1_ltype | + +The assignable version of the C datatype matched by the typemap. | + +
| $result | + +Result object returned to target language. | + +|
| $input | + +The original input object passed. | + +|
| $symname | + +Name of function/method being wrapped. | + +
| $result | + +Result object returned to target language. | + +|
| $symname | + +Name of function/method being wrapped | + +|
| $1...n | + +Argument being wrapped | + +|
| $1_name | + +Name of the argument (if provided) | + +|
| $1_type | + +The actual C datatype matched by the typemap. | + +|
| $1_ltype | + +The assignable version of the C datatype matched by the typemap. | + +|
| this | + +C++ this, referring to the class itself. | + +
| $symname | + +Name of function/method being wrapped | + +|
| $1...n | + +Argument being sent to the function | + +|
| $1_name | + +Name of the argument (if provided) | + +|
| $1_type | + +The actual C datatype matched by the typemap. | + +|
| $1_ltype | + +The assignable version of the C datatype matched by the typemap. | + +|
| this | + +C++ this, referring to the class itself. | + +
| $result | + +Result that the director function returns | + +|
| $symname | + +name of the function/method being wrapped | + +|
| $1...n | + +Argument being sent to the function | + +|
| $1_name | + +Name of the argument (if provided) | + +|
| $1_type | + +The actual C datatype matched by the typemap | + +|
| $1_ltype | + +The assignable version of the C datatype matched by the typemap | + +|
| this | + +C++ this, referring to the instance of the class itself | + +
| RUBY | +Swig | ++ |
|---|---|---|
| INT2NUM(long or int) | +SWIG_From_int(int x) | +int to Fixnum or Bignum | +
| INT2FIX(long or int) | ++ | int to Fixnum (faster than INT2NUM) | +
| CHR2FIX(char) | +SWIG_From_char(char x) | +char to Fixnum | +
| rb_str_new2(char*) | +SWIG_FromCharPtrAndSize(char*, size_t) | +char* to String | +
| rb_float_new(double) | +SWIG_From_double(double), +SWIG_From_float(float) |
+ float/double to Float | +
Here, while the Ruby versions return the value directly, the SWIG +versions do not, but return an status value to indicate success (SWIG_OK). While more akward to use, this allows you to write typemaps that report more helpful error messages, like:
+| int NUM2INT(Numeric) | +SWIG_AsVal_int(VALUE, int*) | +
| int FIX2INT(Numeric) | +SWIG_AsVal_int(VALUE, int*) | +
| unsigned int NUM2UINT(Numeric) | +SWIG_AsVal_unsigned_SS_int(VALUE, int*) | +
| unsigned int FIX2UINT(Numeric) | +SWIG_AsVal_unsigned_SS_int(VALUE, int*) | +
| long NUM2LONG(Numeric) | +SWIG_AsVal_long(VALUE, long*) | +
| long FIX2LONG(Numeric) | +SWIG_AsVal_long(VALUE, long*) | +
| unsigned long FIX2ULONG(Numeric) | +SWIG_AsVal_unsigned_SS_long(VALUE, unsigned long*) | +
| char NUM2CHR(Numeric or String) | +SWIG_AsVal_char(VALUE, int*) | +
| char * STR2CSTR(String) | +SWIG_AsCharPtrAndSize(VALUE, char*, size_t, int* alloc) | +
| char * rb_str2cstr(String, int*length) | ++ |
| double NUM2DBL(Numeric) | +(double) SWIG_AsVal_int(VALUE) or similar | +
int NUM2INT(Numeric)-
int FIX2INT(Numeric)
unsigned int NUM2UINT(Numeric)
unsigned int FIX2UINT(Numeric)
long NUM2LONG(Numeric)
long FIX2LONG(Numeric)
unsigned long FIX2ULONG(Numeric)
char NUM2CHR(Numeric or String)
char * STR2CSTR(String)
char * rb_str2cstr(String, int*length)
double NUM2DBL(Numeric)
RSTRING_LEN(str)
+ +RSTRING_PTR(str)
+ +RARRAY_LEN(arr)
+ +RARRAY(arr)->capa
+ +RARRAY_PTR(arr)
+ +void rb_raise(VALUE exception, const char *fmt, ...)
+ +void rb_fatal(const char *fmt, ...)
+ +void rb_bug(const char *fmt, ...)
+ +void rb_sys_fail(const char *msg)
+ +VALUE rb_rescue(VALUE (*body)(VALUE), VALUE args, VALUE(*rescue)(VALUE, VALUE), VALUE rargs)
+ +VALUE rb_ensure(VALUE(*body)(VALUE), VALUE args, VALUE(*ensure)(VALUE), VALUE eargs)
+ +VALUE rb_protect(VALUE (*body)(VALUE), VALUE args, int *result)
+ +void rb_notimplement()
+ +void rb_exit(int status)
+ +void rb_warn(const char *fmt, ...)
+ +void rb_warning(const char *fmt, ...)
+ +void rb_iter_break()
+ +VALUE rb_each(VALUE obj)
+ +VALUE rb_yield(VALUE arg)
+ +int rb_block_given_p()
+ +VALUE rb_iterate(VALUE (*method)(VALUE), VALUE args, VALUE (*block)(VALUE, VALUE), VALUE arg2)
+ +VALUE rb_catch(const char *tag, VALUE (*proc)(VALUE, VALUE), VALUE value)
+ +void rb_throw(const char *tag, VALUE value)
+ +This section includes a few examples of typemaps. For more examples, you might look at the examples in the Example/ruby directory.
+ +A common problem in many C programs is the processing of command line arguments, which are usually passed in an array of NULL terminated strings. The following SWIG interface file allows a Ruby @@ -6092,29 +8793,41 @@ Array instance to be used as a char ** object.
+ +%module argv+ +
// This tells SWIG to treat char ** as a special case
%typemap(in) char ** {
/* Get the length of the array */
int size = RARRAY($input)->len;
int i;
$1 = (char **) malloc((size+1)*sizeof(char *));
/* Get the first element in memory */
VALUE *ptr = RARRAY($input)->ptr;
for (i=0; i < size; i++, ptr++)
/* Convert Ruby Object String to char* */
$1[i]= STR2CSTR(*ptr);
$1[i]=NULL; /* End of list */
}
// This cleans up the char ** array created before
// the function call
%typemap(freearg) char ** {
free((char *) $1);
}
// Now a test function
%inline %{
int print_args(char **argv) {
int i = 0;
while (argv[i]) {
printf("argv[%d] = %s\n", i,argv[i]);
i++;
}
return i;
}
%}
When this module is compiled, the wrapped C function now operates as follows :
+ +require 'Argv'+ +
Argv.print_args(["Dave","Mike","Mary","Jane","John"])
argv[0] = Dave
argv[1] = Mike
argv[2] = Mary
argv[3] = Jane
argv[4] = John
In the example, two different typemaps are used. The "in" typemap is used to receive an input argument and convert it to a C array. Since dynamic memory allocation is used to allocate memory for @@ -6123,11 +8836,15 @@ after the execution of the C function.
+ +Ruby's solution to the "keyword arguments" capability of some other languages is to allow the programmer to pass in one or more key-value pairs as arguments to a function. All of those key-value @@ -6139,29 +8856,41 @@ about people's vital statistics:
+ +void setVitalStats(const char *person, int nattributes, const char **names, int *values);+ +
and you'd like to be able to call it from Ruby by passing in an arbitrary number of key-value pairs as inputs, e.g.
+ +setVitalStats("Fred",
'weight' => 270,
'age' => 42
)
+
+
To make this work, you need to write a typemap that expects a Ruby Hash as its input and somehow extracts the last three arguments (nattributes, names @@ -6170,15 +8899,21 @@ with the basics:
+ +%typemap(in) (int nattributes, const char **names, const int *values)+ +
(VALUE keys_arr, int i, VALUE key, VALUE val) {
}
This %typemap directive tells SWIG that we want to match any function declaration that has the specified types and names of arguments somewhere in the argument list. The fact that we @@ -6193,26 +8928,36 @@ will need.
+ +Since we expect the input argument to be a Hash, let's next add a check for that:
+ +%typemap(in) (int nattributes, const char **names, const int *values)+ +
(VALUE keys_arr, int i, VALUE key, VALUE val) {
Check_Type($input, T_HASH);
}
Check_Type() is just a macro (defined in the Ruby header files) that confirms that the input argument is of the correct type; if it isn't, an exception will be raised.
+ +The next task is to determine how many key-value pairs are present in the hash; we'll assign this number to the first typemap argument ($1). This is a little tricky since the @@ -6223,15 +8968,21 @@ value:
+ +%typemap(in) (int nattributes, const char **names, const int *values)+ +
(VALUE keys_arr, int i, VALUE key, VALUE val) {
Check_Type($input, T_HASH);
$1 = NUM2INT(rb_funcall($input, rb_intern("size"), 0, NULL));
}
So now we know the number of attributes. Next we need to initialize the second and third typemap arguments (i.e. the two C arrays) to NULL and set the stage for extracting @@ -6239,15 +8990,21 @@ the keys and values from the hash:
+ +%typemap(in) (int nattributes, const char **names, const int *values)+ +
(VALUE keys_arr, int i, VALUE key, VALUE val) {
Check_Type($input, T_HASH);
$1 = NUM2INT(rb_funcall($input, rb_intern("size"), 0, NULL));
$2 = NULL;
$3 = NULL;
if ($1 > 0) {
$2 = (char **) malloc($1*sizeof(char *));
$3 = (int *) malloc($1*sizeof(int));
}
}
There are a number of ways we could extract the keys and values from the input hash, but the simplest approach is to first call the hash's keys method (which returns a Ruby array @@ -6255,15 +9012,21 @@ of the keys) and then start looping over the elements in that array:
+ +%typemap(in) (int nattributes, const char **names, const int *values)+ +
(VALUE keys_arr, int i, VALUE key, VALUE val) {
Check_Type($input, T_HASH);
$1 = NUM2INT(rb_funcall($input, rb_intern("size"), 0, NULL));
$2 = NULL;
$3 = NULL;
if ($1 > 0) {
$2 = (char **) malloc($1*sizeof(char *));
$3 = (int *) malloc($1*sizeof(int));
keys_arr = rb_funcall($input, rb_intern("keys"), 0, NULL);
for (i = 0; i < $1; i++) {
}
}
}
Recall that keys_arr and i are local variables for this typemap. For each element in the keys_arr array, we want to get the key itself, as well as the value @@ -6271,44 +9034,62 @@ corresponding to that key in the hash:
+ +%typemap(in) (int nattributes, const char **names, const int *values)+ +
(VALUE keys_arr, int i, VALUE key, VALUE val) {
Check_Type($input, T_HASH);
$1 = NUM2INT(rb_funcall($input, rb_intern("size"), 0, NULL));
$2 = NULL;
$3 = NULL;
if ($1 > 0) {
$2 = (char **) malloc($1*sizeof(char *));
$3 = (int *) malloc($1*sizeof(int));
keys_arr = rb_funcall($input, rb_intern("keys"), 0, NULL);
for (i = 0; i < $1; i++) {
key = rb_ary_entry(keys_arr, i);
val = rb_hash_aref($input, key);
}
}
}
To be safe, we should again use the Check_Type() macro to confirm that the key is a String and the value is a Fixnum:
+ +%typemap(in) (int nattributes, const char **names, const int *values)+ +
(VALUE keys_arr, int i, VALUE key, VALUE val) {
Check_Type($input, T_HASH);
$1 = NUM2INT(rb_funcall($input, rb_intern("size"), 0, NULL));
$2 = NULL;
$3 = NULL;
if ($1 > 0) {
$2 = (char **) malloc($1*sizeof(char *));
$3 = (int *) malloc($1*sizeof(int));
keys_arr = rb_funcall($input, rb_intern("keys"), 0, NULL);
for (i = 0; i < $1; i++) {
key = rb_ary_entry(keys_arr, i);
val = rb_hash_aref($input, key);
Check_Type(key, T_STRING);
Check_Type(val, T_FIXNUM);
}
}
}
Finally, we can convert these Ruby objects into their C equivalents and store them in our local C arrays:
+ +%typemap(in) (int nattributes, const char **names, const int *values)+ +
(VALUE keys_arr, int i, VALUE key, VALUE val) {
Check_Type($input, T_HASH);
$1 = NUM2INT(rb_funcall($input, rb_intern("size"), 0, NULL));
$2 = NULL;
$3 = NULL;
if ($1 > 0) {
$2 = (char **) malloc($1*sizeof(char *));
$3 = (int *) malloc($1*sizeof(int));
keys_arr = rb_funcall($input, rb_intern("keys"), 0, NULL);
for (i = 0; i < $1; i++) {
key = rb_ary_entry(keys_arr, i);
val = rb_hash_aref($input, key);
Check_Type(key, T_STRING);
Check_Type(val, T_FIXNUM);
$2[i] = STR2CSTR(key);
$3[i] = NUM2INT(val);
}
}
}
We're not done yet. Since we used malloc() to dynamically allocate the memory used for the names and values arguments, we need to provide a @@ -6317,26 +9098,36 @@ memory leak. Fortunately, this typemap is a lot easier to write:
+ +%typemap(freearg) (int nattributes, const char **names, const int *values) {
free((void *) $2);
free((void *) $3);
}
+
+
All of the code for this example, as well as a sample Ruby program that uses the extension, can be found in the Examples/ruby/hashargs directory of the SWIG distribution.
+ +Occasionally, it might be necessary to convert pointer values that have been stored using the SWIG typed-pointer representation. Since there are several ways in which pointers can be represented, the @@ -6344,11 +9135,15 @@ following two functions are used to safely perform this conversion:
+ +int SWIG_ConvertPtr(VALUE obj, void **ptr, swig_type_info *ty, int flags)
+ +VALUE SWIG_NewPointerObj(void *ptr, swig_type_info *ty, int own)
+ +Both of these functions require the use of a special SWIG type-descriptor structure. This structure contains information about the mangled name of the datatype, type-equivalence information, as well @@ -6387,40 +9188,56 @@ structure is usually accessed as follows:
+ +Foo *foo;+ +
SWIG_ConvertPtr($input, (void **) &foo, SWIGTYPE_p_Foo, 1);
VALUE obj;
obj = SWIG_NewPointerObj(f, SWIGTYPE_p_Foo, 0);
In a typemap, the type descriptor should always be accessed using the special typemap variable $1_descriptor. For example:
+ +%typemap(in) Foo * {
SWIG_ConvertPtr($input, (void **) &$1, $1_descriptor, 1);
}
+
+
VALUE Data_Wrap_Struct(VALUE class, void (*mark)(void *), void (*free)(void *), void *ptr)
+ +VALUE Data_Make_Struct(VALUE class, c-type, void (*mark)(void *), void (*free)(void *), c-type *ptr)
+ +Data_Get_Struct(VALUE obj, c-type, c-type *ptr)
+ +Another use for macros and type maps is to create a Ruby array from a STL vector of pointers. In essence, copy of all the pointers in the vector into a Ruby array. The use of the macro is to make the @@ -6467,65 +9296,93 @@ typemaps for other STL structures:
+ +%define PTR_VECTOR_TO_RUBY_ARRAY(vectorclassname, classname)+ +
%typemap(out) vectorclassname &, const vectorclassname & {
VALUE arr = rb_ary_new2($1->size());
vectorclassname::iterator i = $1->begin(), iend = $1->end();
for ( ; i!=iend; i++ )
rb_ary_push(arr, Data_Wrap_Struct(c ## classname.klass, 0, 0, *i));
$result = arr;
}
%typemap(out) vectorclassname, const vectorclassname {
VALUE arr = rb_ary_new2($1.size());
vectorclassname::iterator i = $1.begin(), iend = $1.end();
for ( ; i!=iend; i++ )
rb_ary_push(arr, Data_Wrap_Struct(c ## classname.klass, 0, 0, *i));
$result = arr;
}
%enddef
Note, that the "c ## classname.klass" is used in the preprocessor step to determine the actual object from the class name.
+ +To use the macro with a class Foo, the following is used:
+ +PTR_VECTOR_TO_RUBY_ARRAY(vector<foo *="">, Foo)+ +
It is also possible to create a STL vector of Ruby objects:
+ +%define RUBY_ARRAY_TO_PTR_VECTOR(vectorclassname, classname)+ +
%typemap(in) vectorclassname &, const vectorclassname & {
Check_Type($input, T_ARRAY);
vectorclassname *vec = new vectorclassname;
int len = RARRAY($input)->len;
for (int i=0; i!=len; i++) {
VALUE inst = rb_ary_entry($input, i);
//The following _should_ work but doesn't on HPUX
// Check_Type(inst, T_DATA);
classname *element = NULL;
Data_Get_Struct(inst, classname, element);
vec->push_back(element);
}
$1 = vec;
}
%typemap(freearg) vectorclassname &, const vectorclassname & {
delete $1;
}
%enddef
It is also possible to create a Ruby array from a vector of static data types:
+ +%define VECTOR_TO_RUBY_ARRAY(vectorclassname, classname)+ +
%typemap(out) vectorclassname &, const vectorclassname & {
VALUE arr = rb_ary_new2($1->size());
vectorclassname::iterator i = $1->begin(), iend = $1->end();
for ( ; i!=iend; i++ )
rb_ary_push(arr, Data_Wrap_Struct(c ## classname.klass, 0, 0, &(*i)));
$result = arr;
}
%typemap(out) vectorclassname, const vectorclassname {
VALUE arr = rb_ary_new2($1.size());
vectorclassname::iterator i = $1.begin(), iend = $1.end();
for ( ; i!=iend; i++ )
rb_ary_push(arr, Data_Wrap_Struct(c ## classname.klass, 0, 0, &(*i)));
$result = arr;
}
%enddef
Using ri and rdoc web pages in Ruby libraries is a common practice. Given the way that SWIG generates the extensions by default, your users @@ -6547,6 +9408,8 @@ or .cxx file.
+ +The features described in this section make it easy for you to add rdoc strings to your modules, functions and methods that can then be @@ -6555,27 +9418,37 @@ Windows chm file and an .xml description.
+ +rdoc can then be run from a console or shell window on a swig generated file.
+ +For example, to generate html web pages from a C++ file, you'd do:
+ +To generate ri documentation from a c wrap file, you could do:
+ +Ruby allows a docstring at the beginning of the file before any other statements, and it is typically used to give a @@ -6598,15 +9475,21 @@ example: + +
%module(docstring="This is the example module's docstring") example+ +
When you have more than just a line or so then you can retain the easy readability of the %module directive by using a @@ -6615,20 +9498,28 @@ macro. For example: + +
%define DOCSTRING+ +
"The `XmlResource` class allows program resources defining menus,
layout of controls on a panel, etc. to be loaded from an XML file."
%enddef
%module(docstring=DOCSTRING) xrc
Since SWIG does know everything about the function it wraps, it is possible to generate an rdoc containing the parameter types, names @@ -6638,6 +9529,8 @@ systems of any language, it makes sense to take advantage of it. + +
SWIG's Ruby module provides support for the "autodoc" feature, which when attached to a node in the parse tree will cause an rdoc @@ -6651,11 +9544,15 @@ feature, described below. + +
When the "0" option is given then the types of the parameters will not be included in the autodoc string. For @@ -6665,35 +9562,49 @@ this function prototype: + +
%feature("autodoc", "0");
bool function_name(int x, int y, Foo* foo=NULL, Bar* bar=NULL);
+
+
Then Ruby code like this will be generated:
+ +function_name(x, y, foo=nil, bar=nil) -> bool+ +
...
When the "1" option is used then the parameter types will be used in the rdoc string. In addition, an attempt is made to @@ -6708,20 +9619,28 @@ this: + +
function_name(int x, int y, Foo foo=nil, Bar bar=nil) -> bool+ +
...
When the "2" option is used then the parameter types will not be @@ -6733,11 +9652,15 @@ this: + +
When the "3" option is used then the function will be documented using a combination of "1" and "2" above. Given the example above, @@ -6748,20 +9671,28 @@ this: + +
function_name(int x, int y, Foo foo=nil, Bar bar=nil) -> bool+ +
Parameters:
x - int
y - int
foo - Foo
bar - Bar
Finally, there are times when the automatically generated autodoc string will make no sense for a Ruby programmer, particularly when a @@ -6772,20 +9703,28 @@ generated string. For example: + +
%feature("autodoc", "GetPosition() -> (x, y)") GetPosition;
void GetPosition(int* OUTPUT, int* OUTPUT);
+
+
In addition to the autodoc strings described above, you can also attach any arbitrary descriptive text to a node in the parse tree with @@ -6796,675 +9735,1011 @@ docstring and they are output together.
+ +SWIG allows operator overloading with, by using the %extend or %rename commands in SWIG and the following operator names (derived from Python):
+ +| General | + +||
| __repr__ | + +inspect | + +|
| __str__ | + +to_s | + +|
| __cmp__ | + +<=> | + +|
| __hash__ | + +hash | + +|
| __nonzero__ | + +nonzero? | + +|
| + + | ||
| Callable | + +||
| __call__ | + +call | + +|
| + + | ||
| Collection | + +||
| __len__ | + +length | + +|
| __getitem__ | + +[] | + +|
| __setitem__ | + +[]= | + +|
| + + | ||
| Numeric | + +||
| __add__ | + ++ | + +|
| __sub__ | + +- | + ++ + |
| __mul__ | + +* | + +|
| __div__ | + +/ | + +|
| __mod__ | + +% | + +|
| __divmod__ | + +divmod | + +|
| __pow__ | + +** | + +|
| __lshift__ | + +<< | + +|
| __rshift__ | + +>> | + +|
| __and__ | + +& | + +|
| __xor__ | + +^ | + +|
| __or__ | + +| | + +|
| __neg__ | + +-@ | + ++ + |
| __pos__ | + ++@ | + +|
| __abs__ | + +abs | + +|
| __invert__ | + +~ | + +|
| __int__ | + +to_i | + +|
| __float__ | + +to_f | + +|
| __coerce__ | + +coerce | + +|
| + + | ||
| Additions in 1.3.13 | + +||
| __lt__ | + +< | + +|
| __le__ | + +<= | + +|
| __eq__ | + +== | + +|
| __gt__ | + +> | + +|
| __ge__ | + +>= | + +