rice 2.1.1 → 2.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|