rice 2.1.1 → 2.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Doxyfile +3 -15
- data/Makefile.am +2 -2
- data/Makefile.in +9 -9
- data/{README → README.md} +254 -257
- data/aclocal.m4 +20 -20
- data/rice/Data_Object_defn.hpp +3 -3
- data/rice/Makefile.in +2 -2
- data/rice/detail/Iterator.hpp +2 -2
- data/rice/detail/ruby_version_code.hpp +1 -1
- data/rice/to_from_ruby.ipp +1 -1
- data/ruby/Makefile.in +2 -2
- data/ruby/lib/Makefile.in +2 -2
- data/ruby/lib/version.rb +1 -1
- data/sample/Makefile.in +2 -2
- data/test/Makefile.in +2 -2
- data/test/ext/Makefile.in +2 -2
- data/test/test_Class.cpp +5 -3
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1e936aa5acd436894b69f08585e6a10d9c71bdb5
|
4
|
+
data.tar.gz: 29a7085b7d0c354ff552fbba9acb47fcd8cedbe0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 17de95b0229f2719c2f349c42ca72f8974345d6b0dd7935957a8e777fab57880408bbf7cf03ca4599525d5238f484e77b7e6894ace3d6dda63d254235b4e30cd
|
7
|
+
data.tar.gz: 3338b3a528e72a8cb5a429c289c72f567716383b6462a9476b01463097207d69b37c7e699b0c77966ada9e79c5af1f66b3f6ca64bdec9f0cecfb234cb53351ac
|
data/Doxyfile
CHANGED
@@ -733,7 +733,7 @@ WARN_LOGFILE =
|
|
733
733
|
# spaces.
|
734
734
|
# Note: If this tag is empty the current directory is searched.
|
735
735
|
|
736
|
-
INPUT = rice
|
736
|
+
INPUT = rice README.md
|
737
737
|
|
738
738
|
# This tag can be used to specify the character encoding of the source files
|
739
739
|
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
|
@@ -753,7 +753,7 @@ INPUT_ENCODING = UTF-8
|
|
753
753
|
# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf,
|
754
754
|
# *.qsf, *.as and *.js.
|
755
755
|
|
756
|
-
FILE_PATTERNS = *.hpp
|
756
|
+
FILE_PATTERNS = *.hpp
|
757
757
|
|
758
758
|
# The RECURSIVE tag can be used to specify whether or not subdirectories should
|
759
759
|
# be searched for input files as well.
|
@@ -869,7 +869,7 @@ FILTER_SOURCE_PATTERNS =
|
|
869
869
|
# (index.html). This can be useful if you have a project on for instance GitHub
|
870
870
|
# and want to reuse the introduction page also for the doxygen output.
|
871
871
|
|
872
|
-
USE_MDFILE_AS_MAINPAGE =
|
872
|
+
USE_MDFILE_AS_MAINPAGE = README.md
|
873
873
|
|
874
874
|
#---------------------------------------------------------------------------
|
875
875
|
# Configuration options related to source browsing
|
@@ -1779,18 +1779,6 @@ GENERATE_XML = NO
|
|
1779
1779
|
|
1780
1780
|
XML_OUTPUT = xml
|
1781
1781
|
|
1782
|
-
# The XML_SCHEMA tag can be used to specify a XML schema, which can be used by a
|
1783
|
-
# validating XML parser to check the syntax of the XML files.
|
1784
|
-
# This tag requires that the tag GENERATE_XML is set to YES.
|
1785
|
-
|
1786
|
-
XML_SCHEMA =
|
1787
|
-
|
1788
|
-
# The XML_DTD tag can be used to specify a XML DTD, which can be used by a
|
1789
|
-
# validating XML parser to check the syntax of the XML files.
|
1790
|
-
# This tag requires that the tag GENERATE_XML is set to YES.
|
1791
|
-
|
1792
|
-
XML_DTD =
|
1793
|
-
|
1794
1782
|
# If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program
|
1795
1783
|
# listings (including syntax highlighting and cross-referencing information) to
|
1796
1784
|
# the XML output. Note that enabling this will significantly increase the size
|
data/Makefile.am
CHANGED
@@ -20,7 +20,7 @@ EXTRA_DIST = \
|
|
20
20
|
doxygen.am \
|
21
21
|
doc
|
22
22
|
|
23
|
-
rice/README.doxygen: README
|
23
|
+
rice/README.doxygen: README.md
|
24
24
|
@echo Generating documentation
|
25
|
-
@$(RUBY) -e 'File.open("README") { |i| File.open("rice/README.doxygen", "w") { |o| o.puts "/*! #{i.gets}"; i.each_line { |l| o.puts " #{l}" if l !~ /^\\comment/ and l !~ /^vim:/ }; o.puts " */" } }'
|
25
|
+
@$(RUBY) -e 'File.open("README.md") { |i| File.open("rice/README.doxygen", "w") { |o| o.puts "/*! #{i.gets}"; i.each_line { |l| o.puts " #{l}" if l !~ /^\\comment/ and l !~ /^vim:/ }; o.puts " */" } }'.md
|
26
26
|
|
data/Makefile.in
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
# Makefile.in generated by automake 1.15 from Makefile.am.
|
1
|
+
# Makefile.in generated by automake 1.15.1 from Makefile.am.
|
2
2
|
# @configure_input@
|
3
3
|
|
4
|
-
# Copyright (C) 1994-
|
4
|
+
# Copyright (C) 1994-2017 Free Software Foundation, Inc.
|
5
5
|
|
6
6
|
# This Makefile.in is free software; the Free Software Foundation
|
7
7
|
# gives unlimited permission to copy and/or distribute it,
|
@@ -190,7 +190,7 @@ CSCOPE = cscope
|
|
190
190
|
DIST_SUBDIRS = $(SUBDIRS)
|
191
191
|
am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/doxygen.am \
|
192
192
|
$(top_srcdir)/rice/detail/ruby_version_code.hpp.in COPYING \
|
193
|
-
|
193
|
+
TODO config.guess config.sub depcomp install-sh missing
|
194
194
|
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
195
195
|
distdir = $(PACKAGE)-$(VERSION)
|
196
196
|
top_distdir = "$(distdir)"
|
@@ -616,7 +616,7 @@ distdir: $(DISTFILES)
|
|
616
616
|
! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
|
617
617
|
|| chmod -R a+r "$(distdir)"
|
618
618
|
dist-gzip: distdir
|
619
|
-
tardir="$(distdir)" && $(am__tar) | GZIP
|
619
|
+
tardir="$(distdir)" && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >"$(distdir)".tar.gz
|
620
620
|
$(am__post_remove_distdir)
|
621
621
|
|
622
622
|
dist-bzip2: distdir
|
@@ -642,7 +642,7 @@ dist-shar: distdir
|
|
642
642
|
@echo WARNING: "Support for shar distribution archives is" \
|
643
643
|
"deprecated." >&2
|
644
644
|
@echo WARNING: "It will be removed altogether in Automake 2.0" >&2
|
645
|
-
shar "$(distdir)" | GZIP
|
645
|
+
shar "$(distdir)" | eval GZIP= gzip $(GZIP_ENV) -c >"$(distdir)".shar.gz
|
646
646
|
$(am__post_remove_distdir)
|
647
647
|
|
648
648
|
dist-zip: distdir
|
@@ -660,7 +660,7 @@ dist dist-all:
|
|
660
660
|
distcheck: dist
|
661
661
|
case '$(DIST_ARCHIVES)' in \
|
662
662
|
*.tar.gz*) \
|
663
|
-
GZIP
|
663
|
+
eval GZIP= gzip $(GZIP_ENV) -dc "$(distdir)".tar.gz | $(am__untar) ;;\
|
664
664
|
*.tar.bz2*) \
|
665
665
|
bzip2 -dc "$(distdir)".tar.bz2 | $(am__untar) ;;\
|
666
666
|
*.tar.lz*) \
|
@@ -670,7 +670,7 @@ distcheck: dist
|
|
670
670
|
*.tar.Z*) \
|
671
671
|
uncompress -c "$(distdir)".tar.Z | $(am__untar) ;;\
|
672
672
|
*.shar.gz*) \
|
673
|
-
GZIP
|
673
|
+
eval GZIP= gzip $(GZIP_ENV) -dc "$(distdir)".shar.gz | unshar ;;\
|
674
674
|
*.zip*) \
|
675
675
|
unzip "$(distdir)".zip ;;\
|
676
676
|
esac
|
@@ -911,9 +911,9 @@ uninstall-am:
|
|
911
911
|
|
912
912
|
doc: doxygen-doc
|
913
913
|
|
914
|
-
rice/README.doxygen: README
|
914
|
+
rice/README.doxygen: README.md
|
915
915
|
@echo Generating documentation
|
916
|
-
@$(RUBY) -e 'File.open("README") { |i| File.open("rice/README.doxygen", "w") { |o| o.puts "/*! #{i.gets}"; i.each_line { |l| o.puts " #{l}" if l !~ /^\\comment/ and l !~ /^vim:/ }; o.puts " */" } }'
|
916
|
+
@$(RUBY) -e 'File.open("README.md") { |i| File.open("rice/README.doxygen", "w") { |o| o.puts "/*! #{i.gets}"; i.each_line { |l| o.puts " #{l}" if l !~ /^\\comment/ and l !~ /^vim:/ }; o.puts " */" } }'.md
|
917
917
|
|
918
918
|
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
919
919
|
# Otherwise a system limit (for SysV at least) may be exceeded.
|
data/{README → README.md}
RENAMED
@@ -1,7 +1,6 @@
|
|
1
|
-
|
1
|
+
# Rice - Ruby Interface for C++ Extensions {#mainpage}
|
2
2
|
|
3
|
-
|
4
|
-
\section intro Introduction
|
3
|
+
# Introduction {#intro}
|
5
4
|
|
6
5
|
Rice is a C++ interface to Ruby's C API. It provides a type-safe and
|
7
6
|
exception-safe interface in order to make embedding Ruby and writing
|
@@ -10,63 +9,65 @@ ways, but also attempts to provide an object-oriented interface to all
|
|
10
9
|
of the Ruby C API.
|
11
10
|
|
12
11
|
What Rice gives you:
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
12
|
+
- A simple C++-based syntax for wrapping and defining classes
|
13
|
+
- Automatic conversion of exceptions between C++ and Ruby
|
14
|
+
- Smart pointers for handling garbage collection
|
15
|
+
- Wrappers for most builtin types to simplify calling code
|
17
16
|
|
18
|
-
|
17
|
+
# Project Details {#project}
|
19
18
|
|
20
19
|
The source is hosted on github: http://github.com/jasonroelofs/rice
|
21
20
|
|
22
21
|
Bug tracking: http://github.com/jasonroelofs/rice/issues
|
23
22
|
|
24
|
-
|
23
|
+
API documentation: http://jasonroelofs.github.io/rice
|
24
|
+
|
25
|
+
# Installation {#installation}
|
25
26
|
|
26
|
-
|
27
|
+
~~~
|
27
28
|
gem install rice
|
28
|
-
|
29
|
+
~~~
|
29
30
|
|
30
31
|
Building it locally from a clone of the repository is as follows:
|
31
32
|
|
32
|
-
|
33
|
+
~~~
|
33
34
|
./bootstrap
|
34
35
|
ruby extconf.rb
|
35
36
|
make
|
36
|
-
|
37
|
+
~~~
|
37
38
|
|
38
39
|
Rice is known to work on *nix and OSX. Windows is not currently
|
39
40
|
supported.
|
40
41
|
|
41
|
-
|
42
|
+
# Tutorial {#tutorial}
|
42
43
|
|
43
|
-
|
44
|
+
## Getting started {#getting_started}
|
44
45
|
|
45
46
|
Writing an extension with Rice is very similar to writing an extension
|
46
47
|
with the C API.
|
47
48
|
|
48
49
|
The first step is to create an extconf.rb file:
|
49
50
|
|
50
|
-
|
51
|
+
~~~{.cpp}
|
51
52
|
require 'mkmf-rice'
|
52
53
|
create_makefile('test')
|
53
|
-
|
54
|
+
~~~
|
54
55
|
|
55
|
-
Note that we use mkmf-rice instead of mkmf
|
56
|
+
Note that we use `mkmf-rice` instead of `mkmf`. This will ensure that the
|
56
57
|
extension will be linked with standard C++ library along with the Rice
|
57
58
|
library, and allow access to the Rice header files.
|
58
59
|
|
59
60
|
Next we create our extension and save it to test.cpp:
|
60
61
|
|
61
|
-
|
62
|
+
~~~{.cpp}
|
62
63
|
extern "C"
|
63
64
|
void Init_test()
|
64
65
|
{
|
65
66
|
}
|
66
|
-
|
67
|
+
~~~
|
67
68
|
|
68
69
|
Note the extern "C" line above. This tells the compiler that the
|
69
|
-
function Init_test should have C linkage and calling convention. This
|
70
|
+
function `Init_test` should have C linkage and calling convention. This
|
70
71
|
turns off name mangling so that the Ruby interpreter will be able to
|
71
72
|
find the function (remember that Ruby is written in C, not C++).
|
72
73
|
|
@@ -75,11 +76,11 @@ particularly useful. The next step is to define a class so we can add
|
|
75
76
|
methods to it.
|
76
77
|
|
77
78
|
|
78
|
-
|
79
|
+
## Defining clases {#classes}
|
79
80
|
|
80
81
|
Defining a class in Rice is easy:
|
81
82
|
|
82
|
-
|
83
|
+
~~~{.cpp}
|
83
84
|
#include "rice/Class.hpp"
|
84
85
|
|
85
86
|
using namespace Rice;
|
@@ -89,12 +90,12 @@ Defining a class in Rice is easy:
|
|
89
90
|
{
|
90
91
|
Class rb_cTest = define_class("Test");
|
91
92
|
}
|
92
|
-
|
93
|
+
~~~
|
93
94
|
|
94
|
-
This will create a class called Test that inherits from Object
|
95
|
+
This will create a class called `Test` that inherits from `Object`. If we
|
95
96
|
wanted to inherit from a different class, we could easily do so:
|
96
97
|
|
97
|
-
|
98
|
+
~~~{.cpp}
|
98
99
|
#include "rice/Class.hpp"
|
99
100
|
|
100
101
|
using namespace Rice;
|
@@ -104,34 +105,34 @@ wanted to inherit from a different class, we could easily do so:
|
|
104
105
|
{
|
105
106
|
Class rb_cMySocket = define_class("MySocket", rb_cIO);
|
106
107
|
}
|
107
|
-
|
108
|
+
~~~
|
108
109
|
|
109
|
-
Note the prefix rb_c on the name of the class.
|
110
|
-
that the Ruby interpreter and many extensions tend to use.
|
111
|
-
that this is a class and not some other type of object.
|
110
|
+
Note the prefix rb_c on the name of the class. This is a convention
|
111
|
+
that the Ruby interpreter and many extensions tend to use. It signifies
|
112
|
+
that this is a class and not some other type of object. Some other
|
112
113
|
naming conventions that are commonly used:
|
113
114
|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
115
|
+
- rb_c variable name prefix for a Class
|
116
|
+
- rb_m variable name prefix for a Module
|
117
|
+
- rb_e variable name prefix for an Exception type
|
118
|
+
- rb_ function prefix for a function in the Ruby C API
|
119
|
+
- rb_f_ function prefix to differentiate between an API function that
|
119
120
|
takes Ruby objects as arguments and one that takes C argument types
|
120
|
-
|
121
|
-
|
121
|
+
- rb_*_s_ indicates the function is a singleton function
|
122
|
+
- *_m suffix to indicate the function takes variable number of
|
122
123
|
arguments
|
123
124
|
|
124
125
|
|
125
|
-
Also note that we don't include "ruby.h" directly.
|
126
|
+
Also note that we don't include "ruby.h" directly. Rice has a wrapper
|
126
127
|
for ruby.h that handles some compatibility issues across platforms and
|
127
|
-
Ruby versions.
|
128
|
+
Ruby versions. Always include Rice headers before including anything
|
128
129
|
that might include "ruby.h".
|
129
130
|
|
130
|
-
|
131
|
+
## Defining methods {#methods}
|
131
132
|
|
132
133
|
Now let's add a method to our class:
|
133
134
|
|
134
|
-
|
135
|
+
~~~{.cpp}
|
135
136
|
#include "rice/Class.hpp"
|
136
137
|
#include "rice/String.hpp"
|
137
138
|
|
@@ -150,15 +151,15 @@ Now let's add a method to our class:
|
|
150
151
|
define_class("Test")
|
151
152
|
.define_method("hello", &test_hello);
|
152
153
|
}
|
153
|
-
|
154
|
+
~~~
|
154
155
|
|
155
|
-
Here we add a method Test#hello that simply returns the string
|
156
|
+
Here we add a method `%Test#hello` that simply returns the string
|
156
157
|
"Hello, World". The method takes self as an implicit parameter, but
|
157
158
|
isn't used, so we comment it out to prevent a compiler warning.
|
158
159
|
|
159
|
-
We could also add an
|
160
|
+
We could also add an `#initialize` method to our class:
|
160
161
|
|
161
|
-
|
162
|
+
~~~{.cpp}
|
162
163
|
#include "rice/Class.hpp"
|
163
164
|
#include "rice/String.hpp"
|
164
165
|
|
@@ -180,21 +181,21 @@ We could also add an #initialize method to our class:
|
|
180
181
|
{
|
181
182
|
Class rb_cTest =
|
182
183
|
define_class("Test")
|
183
|
-
.define_method("initialize", &test_initialize)
|
184
|
+
.define_method("initialize", &test_initialize)
|
184
185
|
.define_method("hello", &test_hello);
|
185
186
|
}
|
186
|
-
|
187
|
+
~~~
|
187
188
|
|
188
|
-
The initialize method sets an instance variable
|
189
|
-
The number is automatically converted to a Fixnum before doing the
|
189
|
+
The `initialize` method sets an instance variable `@foo` to the value 42.
|
190
|
+
The number is automatically converted to a `Fixnum` before doing the
|
190
191
|
assignment.
|
191
192
|
|
192
|
-
Note that we're chaining calls on the Class object. Most member
|
193
|
-
functions in Module and Class return a reference to self, so we can
|
193
|
+
Note that we're chaining calls on the `Class` object. Most member
|
194
|
+
functions in `Module` and `Class` return a reference to self, so we can
|
194
195
|
chain as many calls as we want to define as many methods as we want.
|
195
196
|
|
196
197
|
|
197
|
-
|
198
|
+
## Wrapping C++ Types {#data_types}
|
198
199
|
|
199
200
|
It's useful to be able to define Ruby classes in a C++ style rather than
|
200
201
|
using the Ruby API directly, but the real power Rice is in wrapping
|
@@ -202,19 +203,19 @@ already-defined C++ types.
|
|
202
203
|
|
203
204
|
Let's assume we have the following C++ class that we want to wrap:
|
204
205
|
|
205
|
-
|
206
|
+
~~~{.cpp}
|
206
207
|
class Test
|
207
208
|
{
|
208
209
|
public:
|
209
210
|
Test();
|
210
211
|
std::string hello();
|
211
212
|
};
|
212
|
-
|
213
|
+
~~~
|
213
214
|
|
214
215
|
This is a C++ version of the Ruby class we just created in the previous
|
215
|
-
section.
|
216
|
+
section. To wrap it:
|
216
217
|
|
217
|
-
|
218
|
+
~~~{.cpp}
|
218
219
|
#include "rice/Data_Type.hpp"
|
219
220
|
#include "rice/Constructor.hpp"
|
220
221
|
|
@@ -228,57 +229,57 @@ section. To wrap it:
|
|
228
229
|
.define_constructor(Constructor<Test>())
|
229
230
|
.define_method("hello", &Test::hello);
|
230
231
|
}
|
231
|
-
|
232
|
+
~~~
|
232
233
|
|
233
|
-
This example is similar to the one before, but we use Data_Type
|
234
|
-
instead of Class and the template version of define_class() instead of
|
235
|
-
the non-template version.
|
236
|
-
between the Ruby class Test and the C++ class Test such that Rice passes
|
237
|
-
member function pointers to define_method()
|
234
|
+
This example is similar to the one before, but we use `Data_Type<>`
|
235
|
+
instead of `Class` and the template version of define_class() instead of
|
236
|
+
the non-template version. This creates a binding in the Rice library
|
237
|
+
between the Ruby class `Test` and the C++ class Test such that Rice passes
|
238
|
+
member function pointers to `define_method()`.
|
238
239
|
|
239
240
|
It is possible to write the conversion functions ourself (as we'll see
|
240
241
|
below), but Rice does all the dirty work for us.
|
241
242
|
|
242
243
|
|
243
|
-
|
244
|
+
## Type conversions {#conversions}
|
244
245
|
|
245
246
|
Let's look again at our example class:
|
246
247
|
|
247
|
-
|
248
|
+
~~~{.cpp}
|
248
249
|
class Test
|
249
250
|
{
|
250
251
|
public:
|
251
252
|
Test();
|
252
253
|
std::string hello();
|
253
254
|
};
|
254
|
-
|
255
|
+
~~~
|
255
256
|
|
256
257
|
When we wrote our class, we never wrote a single line of code to convert
|
257
|
-
the std::string returned by hello() into a Ruby type.
|
258
|
+
the `std::string` returned by `hello()` into a Ruby type. Neverthless, the
|
258
259
|
conversion works, and when we write:
|
259
260
|
|
260
|
-
|
261
|
+
~~~{.cpp}
|
261
262
|
test = Test.new
|
262
263
|
puts test.hello
|
263
|
-
|
264
|
+
~~~
|
264
265
|
|
265
266
|
We get the expected result.
|
266
267
|
|
267
268
|
Rice has two template conversion functions to convert between C++ and
|
268
269
|
Ruby types:
|
269
270
|
|
270
|
-
|
271
|
+
~~~{.cpp}
|
271
272
|
template<typename T>
|
272
273
|
T from_ruby(Object x);
|
273
274
|
|
274
275
|
template<typename T>
|
275
276
|
Object to_ruby(T const & x);
|
276
|
-
|
277
|
+
~~~
|
277
278
|
|
278
279
|
Rice has included by default specializations for many of the builtin
|
279
|
-
types.
|
280
|
+
types. To define your own conversion, you can write a specialization:
|
280
281
|
|
281
|
-
|
282
|
+
~~~{.cpp}
|
282
283
|
template<>
|
283
284
|
Foo from_ruby<Foo>(Object x)
|
284
285
|
{
|
@@ -290,17 +291,17 @@ types. To define your own conversion, you can write a specialization:
|
|
290
291
|
{
|
291
292
|
// ...
|
292
293
|
}
|
293
|
-
|
294
|
+
~~~
|
294
295
|
|
295
296
|
The implementation of these functions would, of course, depend on the
|
296
|
-
implementation of Foo
|
297
|
+
implementation of `Foo`.
|
297
298
|
|
298
299
|
|
299
|
-
|
300
|
+
## Conversions for wrapped C++ types {#data_conversions}
|
300
301
|
|
301
|
-
Take another look at the wrapper we wrote for the Test class:
|
302
|
+
Take another look at the wrapper we wrote for the `Test` class:
|
302
303
|
|
303
|
-
|
304
|
+
~~~{.cpp}
|
304
305
|
extern "C"
|
305
306
|
void Init_test()
|
306
307
|
{
|
@@ -309,62 +310,62 @@ Take another look at the wrapper we wrote for the Test class:
|
|
309
310
|
.define_constructor(Constructor<Test>())
|
310
311
|
.define_method("hello", &Test::hello);
|
311
312
|
}
|
312
|
-
|
313
|
+
~~~
|
313
314
|
|
314
|
-
When we called define_class<Test
|
315
|
+
When we called `define_class<Test>`, it created a Class for us and
|
315
316
|
automatically registered the new Class with the type system, so that the
|
316
317
|
calls:
|
317
318
|
|
318
|
-
|
319
|
+
~~~{.cpp}
|
319
320
|
Data_Object<Foo> obj(new Foo);
|
320
321
|
Foo * f = from_ruby<Foo *>(obj);
|
321
322
|
Foo const * f = from_ruby<Foo const *>(obj);
|
322
|
-
|
323
|
+
~~~
|
323
324
|
|
324
|
-
|
325
|
+
works as expected.
|
325
326
|
|
326
|
-
The Data_Object class is a wrapper for the Data_Wrap_Struct and the
|
327
|
-
Data_Get_Struct macros in C extensions. It can be used to wrap or
|
328
|
-
unwrap any class that has been assigned to a Data_Type
|
329
|
-
from Object
|
330
|
-
also call on a Data_Object
|
327
|
+
The `Data_Object` class is a wrapper for the `Data_Wrap_Struct` and the
|
328
|
+
`Data_Get_Struct` macros in C extensions. It can be used to wrap or
|
329
|
+
unwrap any class that has been assigned to a `Data_Type`. It inherits
|
330
|
+
from `Object`, so any member functions we can call on an `Object` we can
|
331
|
+
also call on a `Data_Object`:
|
331
332
|
|
332
|
-
|
333
|
+
~~~{.cpp}
|
333
334
|
Object object_id = obj.call("object_id");
|
334
335
|
std::cout << object_id << std::endl;
|
335
|
-
|
336
|
+
~~~
|
336
337
|
|
337
|
-
The Data_Object class can be used to wrap a newly-created object:
|
338
|
+
The `Data_Object` class can be used to wrap a newly-created object:
|
338
339
|
|
339
|
-
|
340
|
+
~~~{.cpp}
|
340
341
|
Data_Object<Foo> foo(new Foo);
|
341
|
-
|
342
|
+
~~~
|
342
343
|
|
343
344
|
or to unwrap an already-created object:
|
344
345
|
|
345
|
-
|
346
|
+
~~~{.cpp}
|
346
347
|
VALUE obj = ...;
|
347
348
|
Data_Object<Foo> foo(obj);
|
348
|
-
|
349
|
+
~~~
|
349
350
|
|
350
|
-
A Data_Object functions like a smart pointer:
|
351
|
+
A `Data_Object` functions like a smart pointer:
|
351
352
|
|
352
|
-
|
353
|
+
~~~{.cpp}
|
353
354
|
Data_Object<Foo> foo(obj);
|
354
355
|
foo->foo();
|
355
356
|
std::cout << *foo << std::endl;
|
356
|
-
|
357
|
+
~~~
|
357
358
|
|
358
|
-
Like a VALUE or an Object
|
359
|
-
by the garbage collector as long as the Data_Object is on the stack.
|
359
|
+
Like a `VALUE` or an `Object`, data stored in a `Data_Object` will be marked
|
360
|
+
by the garbage collector as long as the `Data_Object` is on the stack.
|
360
361
|
|
361
362
|
|
362
|
-
|
363
|
+
## Exceptions {#exception}
|
363
364
|
|
364
365
|
Suppose we added a member function to our example class that throws an
|
365
366
|
exception:
|
366
367
|
|
367
|
-
|
368
|
+
~~~{.cpp}
|
368
369
|
class MyException
|
369
370
|
: public std::exception
|
370
371
|
{
|
@@ -377,11 +378,11 @@ exception:
|
|
377
378
|
std::string hello();
|
378
379
|
void error();
|
379
380
|
};
|
380
|
-
|
381
|
+
~~~
|
381
382
|
|
382
383
|
If we were to wrap this function:
|
383
384
|
|
384
|
-
|
385
|
+
~~~{.cpp}
|
385
386
|
extern "C"
|
386
387
|
void Init_test()
|
387
388
|
{
|
@@ -391,14 +392,14 @@ If we were to wrap this function:
|
|
391
392
|
.define_method("hello", &Test::hello)
|
392
393
|
.define_method("error", &Test::error);
|
393
394
|
}
|
394
|
-
|
395
|
+
~~~
|
395
396
|
|
396
397
|
and call it from inside Ruby:
|
397
398
|
|
398
|
-
|
399
|
+
~~~{.cpp}
|
399
400
|
test = Test.new
|
400
401
|
test.error()
|
401
|
-
|
402
|
+
~~~
|
402
403
|
|
403
404
|
we would get an exception. Rice will automatically convert any
|
404
405
|
C++ exception it catches into a Ruby exception. But what if we wanted
|
@@ -406,7 +407,7 @@ to use a custom error message when we convert the exception, or what if
|
|
406
407
|
we wanted to convert to a different type of exception? We can write
|
407
408
|
this:
|
408
409
|
|
409
|
-
|
410
|
+
~~~{.cpp}
|
410
411
|
extern "C"
|
411
412
|
void Init_test()
|
412
413
|
{
|
@@ -417,70 +418,70 @@ this:
|
|
417
418
|
.define_method("hello", &Test::hello)
|
418
419
|
.define_method("error", &Test::error);
|
419
420
|
}
|
420
|
-
|
421
|
+
~~~
|
421
422
|
|
422
|
-
The handle_my_exception function need only rethrow the exception as a
|
423
|
-
Rice::Exception
|
423
|
+
The `handle_my_exception` function need only rethrow the exception as a
|
424
|
+
`Rice::Exception`:
|
424
425
|
|
425
|
-
|
426
|
+
~~~{.cpp}
|
426
427
|
void handle_my_exception(MyException const & ex)
|
427
428
|
{
|
428
429
|
throw Exception(rb_eRuntimeError, "Goodnight, moon");
|
429
430
|
}
|
430
|
-
|
431
|
+
~~~
|
431
432
|
|
432
433
|
And what if we want to call Ruby code from C++? These exceptions are
|
433
434
|
also converted:
|
434
435
|
|
435
|
-
|
436
|
+
~~~{.cpp}
|
436
437
|
Object o;
|
437
438
|
o.call("some_function_that_raises", 42);
|
438
439
|
|
439
440
|
protect(rb_raise, rb_eRuntimeError, "some exception msg");
|
440
|
-
|
441
|
+
~~~
|
441
442
|
|
442
443
|
Internally whenever Rice catches a C++ or a Ruby exception, it converts
|
443
|
-
it to an Exception object. This object will later be re-raised as a
|
444
|
+
it to an `Exception` object. This object will later be re-raised as a
|
444
445
|
Ruby exception when control is returned to the Ruby VM.
|
445
446
|
|
446
|
-
Rice uses a similar class called Jump_Tag to handle symbols thrown by
|
447
|
-
Ruby's throw
|
447
|
+
Rice uses a similar class called `Jump_Tag` to handle symbols thrown by
|
448
|
+
Ruby's `throw`/`catch` or other non-local jumps from inside the Ruby VM.
|
448
449
|
|
449
450
|
|
450
|
-
|
451
|
+
## Builtin Types {#builtin}
|
451
452
|
|
452
453
|
You've seen this example:
|
453
454
|
|
454
|
-
|
455
|
+
~~~{.cpp}
|
455
456
|
Object object_id = obj.call("object_id");
|
456
457
|
std::cout << object_id << std::endl;
|
457
|
-
|
458
|
+
~~~
|
458
459
|
|
459
460
|
Rice mimics the Ruby class hierarchy as closely as it can.
|
460
461
|
In fact, the above code also works for Classes:
|
461
462
|
|
462
|
-
|
463
|
+
~~~{.cpp}
|
463
464
|
Class rb_cTest = define_class<Test>("Test");
|
464
465
|
Object object_id = rb_cTest.call("object_id");
|
465
466
|
std::cout << object_id << std::endl;
|
466
|
-
|
467
|
+
~~~
|
467
468
|
|
468
469
|
Rice provides builtin wrappers for many builtin Ruby types, including:
|
469
470
|
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
The Array and Hash types can even be iterated over the same way one
|
471
|
+
- Object
|
472
|
+
- Module
|
473
|
+
- Class
|
474
|
+
- String
|
475
|
+
- Array
|
476
|
+
- Hash
|
477
|
+
- Struct
|
478
|
+
- Symbol
|
479
|
+
- Exception
|
480
|
+
|
481
|
+
The `Array` and `Hash` types can even be iterated over the same way one
|
481
482
|
would iterate over an STL container:
|
482
483
|
|
483
|
-
|
484
|
+
~~~{.cpp}
|
484
485
|
Array a;
|
485
486
|
a.push(to_ruby(42));
|
486
487
|
a.push(to_ruby(43));
|
@@ -491,21 +492,21 @@ would iterate over an STL container:
|
|
491
492
|
{
|
492
493
|
std::cout << *it << std::endl;
|
493
494
|
}
|
494
|
-
|
495
|
+
~~~
|
495
496
|
|
496
|
-
STL algorithms should also work as expected on Array and Hash containers.
|
497
|
+
STL algorithms should also work as expected on `Array` and `Hash` containers.
|
497
498
|
|
498
499
|
|
499
|
-
|
500
|
+
## Inheritance {#inheritance}
|
500
501
|
|
501
|
-
Inheritance is a tricky problem to solve in extensions.
|
502
|
+
Inheritance is a tricky problem to solve in extensions. This is because
|
502
503
|
wrapper functions for base classes typically don't know how to accept
|
503
|
-
pointers to derived classes.
|
504
|
+
pointers to derived classes. It is possible to write this logic, but
|
504
505
|
the code is nontrivial.
|
505
506
|
|
506
507
|
Forunately Rice handles this gracefully:
|
507
508
|
|
508
|
-
|
509
|
+
~~~{.cpp}
|
509
510
|
class Base
|
510
511
|
{
|
511
512
|
public:
|
@@ -526,15 +527,15 @@ Forunately Rice handles this gracefully:
|
|
526
527
|
Data_Type<Derived> rb_cDerived =
|
527
528
|
define_class<Derived, Base>("Derived");
|
528
529
|
}
|
529
|
-
|
530
|
+
~~~
|
530
531
|
|
531
|
-
The second template parameter to define_class indicates that Derived
|
532
|
-
inherits from Base
|
532
|
+
The second template parameter to define_class indicates that `Derived`
|
533
|
+
inherits from `Base`.
|
533
534
|
|
534
535
|
Rice does not support multiple inheritance.
|
535
536
|
|
536
537
|
|
537
|
-
|
538
|
+
## Overloaded functions {#overloading}
|
538
539
|
|
539
540
|
If you try to create a member function pointer to an overloaded
|
540
541
|
function, you will get an error. So how do we wrap classes that have
|
@@ -542,17 +543,17 @@ overloaded functions?
|
|
542
543
|
|
543
544
|
Consider a class that uses this idiom for accessors:
|
544
545
|
|
545
|
-
|
546
|
+
~~~{.cpp}
|
546
547
|
class Container
|
547
548
|
{
|
548
549
|
size_t capacity(); // Get the capacity
|
549
550
|
void capacity(size_t cap); // Set the capacity
|
550
551
|
};
|
551
|
-
|
552
|
+
~~~
|
552
553
|
|
553
|
-
We can wrap this class by using
|
554
|
+
We can wrap this class by using `typedef`s:
|
554
555
|
|
555
|
-
|
556
|
+
~~~{.cpp}
|
556
557
|
extern "C"
|
557
558
|
void Init_Container()
|
558
559
|
{
|
@@ -564,45 +565,43 @@ We can wrap this class by using typedefs:
|
|
564
565
|
.define_method("capacity", get_capacity(&Container::capacity))
|
565
566
|
.define_method("capacity=", set_capacity(&Container::capacity))
|
566
567
|
}
|
567
|
-
|
568
|
+
~~~
|
568
569
|
|
569
570
|
|
570
|
-
|
571
|
+
## User-defined type conversions {#user_defined_conversions}
|
571
572
|
|
572
|
-
Rice provides default conversions for many built-in types.
|
573
|
-
however, the default conversion is not what is expected.
|
573
|
+
Rice provides default conversions for many built-in types. Sometimes,
|
574
|
+
however, the default conversion is not what is expected. For
|
574
575
|
example, consider a function:
|
575
576
|
|
576
|
-
|
577
|
+
~~~{.cpp}
|
577
578
|
void foo(char * x);
|
578
|
-
|
579
|
+
~~~
|
579
580
|
|
580
|
-
Is x a pointer to a single character or a pointer to the first character
|
581
|
+
Is `x` a pointer to a single character or a pointer to the first character
|
581
582
|
of a null-terminated string or a pointer to the first character of an
|
582
583
|
array of char?
|
583
584
|
|
584
585
|
Because the second case is the most common use case (a pointer to the
|
585
586
|
first character of a C string), Rice provides a default conversion that
|
586
|
-
treats a char
|
587
|
+
treats a `char *` as a C string. But suppose the above function takes a
|
587
588
|
pointer to a char instead?
|
588
589
|
|
589
590
|
If we write this:
|
590
591
|
|
591
|
-
|
592
|
-
|
593
|
-
\code
|
592
|
+
~~~{.cpp}
|
594
593
|
extern "C"
|
595
594
|
void Init_test()
|
596
595
|
{
|
597
596
|
define_global_function("foo", &foo);
|
598
597
|
}
|
599
|
-
|
598
|
+
~~~
|
600
599
|
|
601
600
|
It will likely have the wrong behavior.
|
602
601
|
|
603
602
|
To avoid this problem, it is necessary to write a wrapper function:
|
604
603
|
|
605
|
-
|
604
|
+
~~~{.cpp}
|
606
605
|
Object wrap_foo(Object o)
|
607
606
|
{
|
608
607
|
char c = from_ruby<char>(o);
|
@@ -615,30 +614,30 @@ To avoid this problem, it is necessary to write a wrapper function:
|
|
615
614
|
{
|
616
615
|
define_global_function("foo", &wrap_foo);
|
617
616
|
}
|
618
|
-
|
617
|
+
~~~
|
619
618
|
|
620
|
-
Note that the out parameter is returned from wrap_foo
|
619
|
+
Note that the out parameter is returned from `wrap_foo`, as Ruby does not
|
621
620
|
have pass-by-variable-reference (it uses pass-by-object-reference).
|
622
621
|
|
623
622
|
|
624
|
-
|
623
|
+
## Default Arguments {#default_arguments}
|
625
624
|
|
626
|
-
Going back to our initial C++ class example, lets say that hello() now
|
625
|
+
Going back to our initial C++ class example, lets say that `hello()` now
|
627
626
|
takes more arguments, one of which has a default value:
|
628
627
|
|
629
|
-
|
628
|
+
~~~{.cpp}
|
630
629
|
class Test
|
631
630
|
{
|
632
631
|
public:
|
633
632
|
Test();
|
634
633
|
std::string hello(std::string first, std::string second = "world");
|
635
634
|
};
|
636
|
-
|
635
|
+
~~~
|
637
636
|
|
638
637
|
As default parameter information is not available through templates,
|
639
|
-
it is necessary to define this in Rice explicitly using Rice::Arg
|
638
|
+
it is necessary to define this in Rice explicitly using `Rice::Arg`:
|
640
639
|
|
641
|
-
|
640
|
+
~~~{.cpp}
|
642
641
|
#include "rice/Data_Type.hpp"
|
643
642
|
#include "rice/Constructor.hpp"
|
644
643
|
|
@@ -655,70 +654,70 @@ it is necessary to define this in Rice explicitly using Rice::Arg:
|
|
655
654
|
(Arg("hello"), Arg("second") = "world")
|
656
655
|
);
|
657
656
|
}
|
658
|
-
|
657
|
+
~~~
|
659
658
|
|
660
|
-
The syntax here is simply Arg(nameOfParameter)[ = defaultValue]
|
661
|
-
parameter is not important here (a readability tool), but the value set via operator
|
659
|
+
The syntax here is simply `Arg(nameOfParameter)[ = defaultValue]`. The name of the
|
660
|
+
parameter is not important here (a readability tool), but the value set via `operator=`
|
662
661
|
must match the type of the parameter. As such it may be necessary to
|
663
662
|
explicitly cast the default value.
|
664
663
|
|
665
|
-
|
664
|
+
~~~{.cpp}
|
666
665
|
.define_method("hello",
|
667
666
|
&Test::hello,
|
668
667
|
(Arg("hello"), Arg("second") = (std::string)"world")
|
669
668
|
);
|
670
|
-
|
669
|
+
~~~
|
671
670
|
|
672
|
-
These Rice::Arg objects must be in the correct order and must be
|
671
|
+
These `Rice::Arg` objects must be in the correct order and must be
|
673
672
|
surrounded with parentheses if more than one exists.
|
674
673
|
|
675
674
|
Now, Ruby will now know about the default arguments, and this wrapper
|
676
675
|
can be used as expected:
|
677
676
|
|
678
|
-
|
677
|
+
~~~{.cpp}
|
679
678
|
t = Test.new
|
680
679
|
t.hello("hello")
|
681
680
|
t.hello("goodnight", "moon")
|
682
|
-
|
681
|
+
~~~
|
683
682
|
|
684
683
|
This also works with Constructors:
|
685
684
|
|
686
|
-
|
685
|
+
~~~{.cpp}
|
687
686
|
.define_constructor(Constructor<SomeClass, int, int>(),
|
688
687
|
( Arg("arg1") = 1, Arg("otherArg") = 12 );
|
689
|
-
|
688
|
+
~~~
|
690
689
|
|
691
|
-
|
690
|
+
## Director {#director}
|
692
691
|
|
693
692
|
As polymorphism is the most important tennant of Object Oriented Programming,
|
694
693
|
it is important that Rice supports polymorphic calls travelling between C++
|
695
694
|
and Ruby seemlessly. Super calls from Ruby subclasses back into C++ already work,
|
696
695
|
but enabling the other direction requires some extra effort. Rice
|
697
|
-
|
698
|
-
Rice::Data_Type::define_director to expose this functionality.
|
696
|
+
supplies the the `Rice::Director` class and
|
697
|
+
`Rice::Data_Type::define_director` to expose this functionality.
|
699
698
|
|
700
|
-
Like SWIG_Director
|
701
|
-
to properly send execution up or down the object
|
699
|
+
Like `SWIG_Director`, `Rice::Director` is a class that is used to build a proxy class
|
700
|
+
to properly send execution up or down the object hierarchy for that class. Take
|
702
701
|
the following class:
|
703
702
|
|
704
|
-
|
703
|
+
~~~{.cpp}
|
705
704
|
class VirtualBase {
|
706
705
|
public:
|
707
706
|
VirtualBase();
|
708
707
|
virtual int doWork();
|
709
708
|
virtual int processWorker() = 0;
|
710
709
|
};
|
711
|
-
|
710
|
+
~~~
|
712
711
|
|
713
712
|
Due to the abstract nature of this class, it will not work at all with Rice
|
714
713
|
in its current form. Any attempt to do so will cause a compilation error due to
|
715
714
|
this class not being constructable. Even without the pure virtual function, any
|
716
|
-
call to VirtualBase::doWork will stop at the C++ level and will not pass down into
|
715
|
+
call to `VirtualBase::doWork` will stop at the C++ level and will not pass down into
|
717
716
|
any Ruby subclasses.
|
718
717
|
|
719
|
-
To properly wrap both of these methods, use a Rice::Director subclass as a proxy:
|
718
|
+
To properly wrap both of these methods, use a `Rice::Director` subclass as a proxy:
|
720
719
|
|
721
|
-
|
720
|
+
~~~{.cpp}
|
722
721
|
#include "rice/Director.hpp"
|
723
722
|
|
724
723
|
class VirtualBaseProxy : public VirtualBase, public Rice::Director {
|
@@ -741,27 +740,27 @@ To properly wrap both of these methods, use a Rice::Director subclass as a proxy
|
|
741
740
|
raisePureVirtual();
|
742
741
|
}
|
743
742
|
};
|
744
|
-
|
743
|
+
~~~
|
745
744
|
|
746
745
|
There is a lot going on here, so we'll go through each part.
|
747
746
|
|
748
|
-
|
747
|
+
~~~{.cpp}
|
749
748
|
class VirtualBaseProxy : public Virtualbase, public Rice::Director {
|
750
|
-
|
749
|
+
~~~
|
751
750
|
|
752
|
-
First, the class needs to subclass both the virtual class in question and Rice::Director
|
751
|
+
First, the class needs to subclass both the virtual class in question and `Rice::Director`.
|
753
752
|
|
754
|
-
|
753
|
+
~~~{.cpp}
|
755
754
|
public:
|
756
755
|
VirtualBaseProxy(Object self) : Rice::Director(self) { }
|
757
|
-
|
756
|
+
~~~
|
758
757
|
|
759
|
-
For Rice::Director to work its magic, every instance of this class needs to
|
758
|
+
For `Rice::Director` to work its magic, every instance of this class needs to
|
760
759
|
have a handle to the Ruby instance. The constructor
|
761
|
-
must take a Rice::Object as the first argument and pass it up into
|
762
|
-
Rice::Director
|
760
|
+
must take a `Rice::Object` as the first argument and pass it up into
|
761
|
+
`Rice::Director`. The code here is the minimum required for a `Rice::Director` proxy.
|
763
762
|
|
764
|
-
|
763
|
+
~~~{.cpp}
|
765
764
|
virtual int doWork() {
|
766
765
|
return from_ruby<int>( getSelf().call("do_work") );
|
767
766
|
}
|
@@ -769,33 +768,33 @@ Rice::Director. The code here is the minimum required for a Rice::Director proxy
|
|
769
768
|
int default_doWork() {
|
770
769
|
return VirtualBase::doWork();
|
771
770
|
}
|
772
|
-
|
771
|
+
~~~
|
773
772
|
|
774
773
|
Here the directory proxy overrides the methods for Ruby exposure and
|
775
|
-
implements the required actions to pass flow around the
|
774
|
+
implements the required actions to pass flow around the hierarchy
|
776
775
|
appropriately. The pattern shown here is that the actual override will
|
777
776
|
call down into Ruby, handling any type conversions, while a
|
778
|
-
default_methodName method handles calling up into C++ and will be the
|
777
|
+
`default_methodName` method handles calling up into C++ and will be the
|
779
778
|
method wrapped into Rice.
|
780
779
|
|
781
|
-
The default_doWork method will be used as Rice's hookup of calling back up the
|
782
|
-
|
783
|
-
up the class
|
780
|
+
The `default_doWork` method will be used as Rice's hookup of calling back up the
|
781
|
+
hierarchy (wrapping is below). This method needs to do one of two things: call
|
782
|
+
up the class hierarchy, as seen here, or call `raisePureVirtual()` as seen in the
|
784
783
|
processWorker example:
|
785
784
|
|
786
|
-
|
785
|
+
~~~{.cpp}
|
787
786
|
int default_processWorker() {
|
788
787
|
raisePureVirtual();
|
789
788
|
}
|
790
|
-
|
789
|
+
~~~
|
791
790
|
|
792
|
-
The method raisePureVirtual() exists to allow wrapping a pure virtual method into Ruby
|
793
|
-
(and ensuring compliation is possible) but making sure any users of this extension are
|
791
|
+
The method `raisePureVirtual()` exists to allow wrapping a pure virtual method into Ruby
|
792
|
+
(and ensuring compliation is possible) but making sure any users of this extension are
|
794
793
|
informed quickly that there's nothing callable in the C++ side of the library.
|
795
794
|
|
796
795
|
Once the proxy class is built, it's time to wrap it into Ruby:
|
797
796
|
|
798
|
-
|
797
|
+
~~~{.cpp}
|
799
798
|
extern "C"
|
800
799
|
void Init_virtual() {
|
801
800
|
define_class<VirtualBase>("VirtualBase")
|
@@ -804,28 +803,28 @@ void Init_virtual() {
|
|
804
803
|
.define_method("do_work", &VirtualBaseProxy::default_doWork)
|
805
804
|
.define_method("process_worker", &VirtualBaseProxy::default_processWorker);
|
806
805
|
}
|
807
|
-
|
806
|
+
~~~
|
808
807
|
|
809
808
|
The wrapping is the same as is described earlier in this document. Expose the class
|
810
|
-
VirtualBase
|
811
|
-
Rice::Data_Type::define_director
|
809
|
+
`VirtualBase`, and register `VirtualBaseProxy` as a director proxy of `VirtualBase` with
|
810
|
+
`Rice::Data_Type::define_director`, then `define methods` pointing to the proxy object as necessary.
|
812
811
|
|
813
|
-
You must use the Rice::Director proxy class in the Constructor line, this allows proper
|
812
|
+
You must use the `Rice::Director` proxy class in the Constructor line, this allows proper
|
814
813
|
object construction / destruction of the types in question.
|
815
814
|
|
816
|
-
|
815
|
+
## Implicit Casting {#implicit_cast}
|
817
816
|
|
818
817
|
There are times when a library exposes classes that, while unrelated, are
|
819
818
|
built to be interchangeable across the library. One example of this is found in
|
820
819
|
the Open Source 3d rendering engine <a
|
821
820
|
href="http://www.ogre3d.org/">OGRE</a>: Ogre::Degree and Ogre::Radian.
|
822
|
-
When a given method takes a Radian, you're free to pass in a Degree, and vice versa.
|
821
|
+
When a given method takes a Radian, you're free to pass in a Degree, and vice versa.
|
823
822
|
|
824
823
|
Rice cannot automatically figure out if this kind of functionality is
|
825
824
|
possible in a given library but it does provide an API for defining
|
826
|
-
these relationships: Rice::define_implicit_cast<From, To>()
|
825
|
+
these relationships: `Rice::define_implicit_cast<From, To>()`.
|
827
826
|
|
828
|
-
|
827
|
+
~~~{.cpp}
|
829
828
|
class Degree { ... };
|
830
829
|
class Radian { ... };
|
831
830
|
|
@@ -839,45 +838,45 @@ void Init_implicit() {
|
|
839
838
|
define_implicit_cast<Degree, Radian>();
|
840
839
|
define_implicit_cast<Radian, Degree>();
|
841
840
|
}
|
842
|
-
|
841
|
+
~~~
|
843
842
|
|
844
|
-
Using Rice::define_implicit_cast has the following requirements:
|
843
|
+
Using `Rice::define_implicit_cast` has the following requirements:
|
845
844
|
|
846
|
-
|
847
|
-
|
848
|
-
|
845
|
+
- The two types must be bound in Rice before defining the cast.
|
846
|
+
- The classes must have constructors that take the other type.
|
847
|
+
- This feature cannot be used with fundamental types.
|
849
848
|
|
850
849
|
To see a full example of this feature, please check out
|
851
850
|
test/test_Data_Type.cpp.
|
852
851
|
|
853
|
-
|
852
|
+
# Motivation {#motivation}
|
854
853
|
|
855
854
|
There are a number of common problems when writing C or C++ extensions
|
856
855
|
for Ruby:
|
857
856
|
|
858
|
-
|
857
|
+
- Type safety. It is easy to mix-up integral types such as ID and
|
859
858
|
VALUE. Some of the functions in the Ruby API are not consistent with
|
860
859
|
which types they take (e.g. rb_const_defined takes an ID and
|
861
860
|
rb_mod_remove_const takes a Symbol).
|
862
861
|
|
863
|
-
|
862
|
+
- DRY principle. Specifying the number of arguments that each wrapped
|
864
863
|
function takes is easy to get wrong. Adding a new argument to the
|
865
864
|
function means that the number of arguments passed to rb_define_method
|
866
865
|
must also be updated.
|
867
866
|
|
868
|
-
|
867
|
+
- Type conversion. There are many different functions to convert data
|
869
868
|
to and from ruby types. Many of them have different semantics or
|
870
869
|
different forms. For example, to convert a string, one might use the
|
871
870
|
StringValue macro, but to convert a fixnum, one might use FIX2INT.
|
872
871
|
Unwrapping previously wrapped C data uses yet another form.
|
873
872
|
|
874
|
-
|
873
|
+
- Exception safety. It is imperative that C++ exceptions never make
|
875
874
|
their way into C code, and it is also imperative that a Ruby exception
|
876
875
|
never escape while there are objects on the stack with nontrivial
|
877
876
|
destructors. Rules for when it is okay to use which exceptions are
|
878
877
|
difficult to get right, especially as code is maintained through time.
|
879
878
|
|
880
|
-
|
879
|
+
- Thread safety. Because the Ruby interpreter is not threads-safe,
|
881
880
|
the Ruby interpreter must not be run from more than one thread.
|
882
881
|
Because of tricks the GC and scheduler play with the C stack, it's not
|
883
882
|
enough to ensure that only one thread runs the interpreter at any
|
@@ -887,17 +886,17 @@ because Ruby copies the stack when it switches threads, C++ code must
|
|
887
886
|
be careful not to access objects in one Ruby thread that were created
|
888
887
|
on the stack in another Ruby thread.
|
889
888
|
|
890
|
-
|
889
|
+
- C-based API. The Ruby API is not always convenient for accessing
|
891
890
|
Ruby data structurs such as Hash and Array, especially when writing C++
|
892
891
|
code, as the interface for these containers is not consistent with
|
893
892
|
standard containers.
|
894
893
|
|
895
|
-
|
894
|
+
- Calling convention. Function pointers passed into the Ruby API must
|
896
895
|
follow the C calling convention. This means that it is not possible to
|
897
896
|
pass a pointer to a template function or static member function (that
|
898
897
|
is, it will work on some platforms, but isn't portable).
|
899
898
|
|
900
|
-
|
899
|
+
- Inheritance. When wrapping C++ objects, it is easy to store a
|
901
900
|
pointer to a derived class, but then methods in the base class must have
|
902
901
|
knowledge of the derived class in order to unwrap the object. It is
|
903
902
|
possible to always store a pointer to the base class and then
|
@@ -906,12 +905,12 @@ can be slow and cumbersome, and it isn't likely to work with multiple
|
|
906
905
|
inheritance. A system that properly handles inheritance for all corner
|
907
906
|
cases is nontrivial.
|
908
907
|
|
909
|
-
|
908
|
+
- Multiple inheritance. C++ supports true multiple inheritance, but
|
910
909
|
the Ruby object model uses single inheritance with mixins. When
|
911
910
|
wrapping a library whose public interface uses multiple inheritance,
|
912
911
|
care must be taken in constructing the mapping.
|
913
912
|
|
914
|
-
|
913
|
+
- GC safety. All live Ruby objects must be marked during the garbage
|
915
914
|
collector's mark phase, otherwise they will be prematurely destroyed.
|
916
915
|
The general rule is that object references stored on the heap should be
|
917
916
|
either registered with rb_gc_register_address or marked by a data
|
@@ -919,66 +918,66 @@ object's mark function; object references stored on the stack will be
|
|
919
918
|
automatically marked, provided the Ruby interpreter was properly
|
920
919
|
initialized at startup.
|
921
920
|
|
922
|
-
|
921
|
+
- Callbacks. C implements callbacks via function pointers, while ruby
|
923
922
|
typically implements callbacks via procs. Writing an adapter function
|
924
923
|
to call the proc is not difficult, but there is much opportunity for
|
925
924
|
error (particularly with exception-safety).
|
926
925
|
|
927
|
-
|
926
|
+
- Data serialization. By default data objects defined at the C layer
|
928
927
|
are not marshalable. The user must explicitly define functions to
|
929
928
|
marshal the data member-by-member.
|
930
929
|
|
931
930
|
Rice addresses these issues in many ways:
|
932
931
|
|
933
|
-
|
932
|
+
- Type safety. Rice provides encapsulation for all builtin types,
|
934
933
|
such as Object, Identifier, Class, Module, and String. It
|
935
934
|
automatically checks the dynamic type of an object before constructing
|
936
935
|
an instance of a wrapper.
|
937
936
|
|
938
|
-
|
937
|
+
- DRY principle. Rice uses introspection through the use of templates
|
939
938
|
and function overloading to automatically determine the number and types
|
940
939
|
of arguments to functions. Default arguments must still be handled
|
941
940
|
explicitly, however.
|
942
941
|
|
943
|
-
|
942
|
+
- Type conversions. Rice provides cast-style to_ruby<> and
|
944
943
|
from_ruby<> template functions to simplify explicit type conversions.
|
945
944
|
Automatic type conversions for parameters and return values are
|
946
945
|
generated for all wrapped functions.
|
947
946
|
|
948
|
-
|
947
|
+
- Exception safety. Rice automatically converts common exceptions and
|
949
948
|
provides a mechanism for converting user-defined exception types. Rice
|
950
949
|
also provides convenience functions for converting exceptions when
|
951
950
|
calling back into ruby code.
|
952
951
|
|
953
|
-
|
952
|
+
- Thread safety. Rice provides no mechanisms for dealing with thread
|
954
953
|
safety. Many common thread safety issues should be alleviated by YARV,
|
955
954
|
which supports POSIX threads.
|
956
955
|
|
957
|
-
|
956
|
+
- C++-based API. Rice provides an object-oriented C++-style API to
|
958
957
|
most common functions in the Ruby C API.
|
959
958
|
|
960
|
-
|
959
|
+
- Calling convention. Rice automatically uses C calling convention
|
961
960
|
for all function pointers passed into the Ruby API.
|
962
961
|
|
963
|
-
|
962
|
+
- Inheritance. Rice provides automatic conversion to the base class
|
964
963
|
type when a wrapped member function is called on the base class.
|
965
964
|
|
966
|
-
|
965
|
+
- Multiple inheritance. Rice provides no mechanism for multiple
|
967
966
|
inheritance. Multiple inheritance can be simulated via mixins, though
|
968
967
|
this is not yet as easy as it could be.
|
969
968
|
|
970
|
-
|
969
|
+
- GC safety. Rice provides a handful of convenience classes for
|
971
970
|
interacting with the garbage collector. There are still basic rules
|
972
971
|
which must be followed to ensure that objects get properly destroyed.
|
973
972
|
|
974
|
-
|
973
|
+
- Callbacks. Rice provides a handful of convenience classes for
|
975
974
|
dealing with callbacks.
|
976
975
|
|
977
|
-
|
976
|
+
- Data serialization. Rice provides no mechanism for data
|
978
977
|
serialization, but it is likely this may be added in a future release.
|
979
978
|
|
980
979
|
|
981
|
-
|
980
|
+
# What Rice is Not {#what_not}
|
982
981
|
|
983
982
|
There are a number projects which server similar functions to Rice. Two
|
984
983
|
such popular projects are SWIG and Boost.Python. Rice has some
|
@@ -1008,7 +1007,7 @@ the C++ level. Thirdly, Rice uses Ruby as a code generator; I find this
|
|
1008
1007
|
to be much more readable than using the Boost preprocessor library.
|
1009
1008
|
|
1010
1009
|
|
1011
|
-
|
1010
|
+
# History {#history}
|
1012
1011
|
|
1013
1012
|
Rice originated as Excruby, a project to interface with C++-based trading
|
1014
1013
|
software at Automated Trading Desk in Mount Pleasant, South Carolina.
|
@@ -1031,19 +1030,19 @@ the lower-level wrappers, but as an implementation detail; the public
|
|
1031
1030
|
interface is truly a high-level abstraction around the Ruby C API.
|
1032
1031
|
|
1033
1032
|
|
1034
|
-
|
1033
|
+
# The GC {#gc}
|
1035
1034
|
|
1036
|
-
|
1035
|
+
- Objects are not automatically registered with the garbage collector.
|
1037
1036
|
|
1038
|
-
|
1037
|
+
- If an Object is on the stack, it does not need to be registered with
|
1039
1038
|
the garbage collector.
|
1040
1039
|
|
1041
|
-
|
1040
|
+
- If an Object is allocated on the heap or if it is a member of an
|
1042
1041
|
object that might be allocated on the heap, use an
|
1043
1042
|
Rice::Address_Registration_Guard to register the object with the garbage
|
1044
1043
|
collector.
|
1045
1044
|
|
1046
|
-
|
1045
|
+
- If a reference counted object is being wrapped, or if another type
|
1047
1046
|
of smart pointer is wrapped, ensure that only one mechanism is used to
|
1048
1047
|
destroy the object. In general, the smart pointer manages the
|
1049
1048
|
allocation of the object, and Ruby should hold only a reference to the
|
@@ -1051,5 +1050,3 @@ smart pointer. When the garbage collector determines that it is time to
|
|
1051
1050
|
clean up the object, the smart pointer will be destroyed, decrementing
|
1052
1051
|
the reference count; when the reference count drops to 0, underlying
|
1053
1052
|
object will be destroyed.
|
1054
|
-
|
1055
|
-
vim:ft=cpp:tw=72:ts=2:sw=2:fo=cqrtn:noci:si
|