rice 3.0.0 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (237) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +121 -0
  3. data/CONTRIBUTORS.md +19 -0
  4. data/Gemfile +3 -0
  5. data/README.md +44 -1025
  6. data/Rakefile +95 -12
  7. data/include/rice/rice.hpp +7766 -0
  8. data/lib/mkmf-rice.rb +127 -0
  9. data/lib/version.rb +3 -0
  10. data/rice/Address_Registration_Guard.ipp +75 -32
  11. data/rice/Address_Registration_Guard_defn.hpp +60 -56
  12. data/rice/Arg.hpp +80 -4
  13. data/rice/Arg.ipp +51 -0
  14. data/rice/Constructor.hpp +12 -14
  15. data/rice/Data_Object.ipp +234 -107
  16. data/rice/Data_Object_defn.hpp +77 -117
  17. data/rice/Data_Type.hpp +1 -2
  18. data/rice/Data_Type.ipp +251 -295
  19. data/rice/Data_Type_defn.hpp +175 -243
  20. data/rice/Director.hpp +11 -6
  21. data/rice/Enum.hpp +54 -104
  22. data/rice/Enum.ipp +104 -230
  23. data/rice/Exception.hpp +2 -8
  24. data/rice/Exception.ipp +65 -0
  25. data/rice/Exception_defn.hpp +46 -47
  26. data/rice/Identifier.hpp +28 -28
  27. data/rice/Identifier.ipp +23 -27
  28. data/rice/Return.hpp +39 -0
  29. data/rice/Return.ipp +33 -0
  30. data/rice/detail/Exception_Handler.ipp +22 -62
  31. data/rice/detail/Exception_Handler_defn.hpp +76 -91
  32. data/rice/detail/Iterator.hpp +18 -88
  33. data/rice/detail/Iterator.ipp +47 -0
  34. data/rice/detail/Jump_Tag.hpp +21 -0
  35. data/rice/detail/MethodInfo.hpp +44 -0
  36. data/rice/detail/MethodInfo.ipp +78 -0
  37. data/rice/detail/NativeAttribute.hpp +53 -0
  38. data/rice/detail/NativeAttribute.ipp +83 -0
  39. data/rice/detail/NativeFunction.hpp +69 -0
  40. data/rice/detail/NativeFunction.ipp +248 -0
  41. data/rice/detail/RubyFunction.hpp +39 -0
  42. data/rice/detail/RubyFunction.ipp +92 -0
  43. data/rice/detail/Type.hpp +29 -0
  44. data/rice/detail/Type.ipp +138 -0
  45. data/rice/detail/TypeRegistry.hpp +50 -0
  46. data/rice/detail/TypeRegistry.ipp +106 -0
  47. data/rice/detail/Wrapper.hpp +51 -0
  48. data/rice/detail/Wrapper.ipp +151 -0
  49. data/rice/detail/default_allocation_func.hpp +8 -19
  50. data/rice/detail/default_allocation_func.ipp +9 -8
  51. data/rice/detail/from_ruby.hpp +2 -37
  52. data/rice/detail/from_ruby.ipp +1020 -46
  53. data/rice/detail/from_ruby_defn.hpp +38 -0
  54. data/rice/detail/function_traits.hpp +124 -0
  55. data/rice/detail/method_data.hpp +23 -15
  56. data/rice/detail/method_data.ipp +53 -0
  57. data/rice/detail/rice_traits.hpp +116 -0
  58. data/rice/detail/ruby.hpp +9 -46
  59. data/rice/detail/to_ruby.hpp +3 -17
  60. data/rice/detail/to_ruby.ipp +409 -31
  61. data/rice/detail/to_ruby_defn.hpp +48 -0
  62. data/rice/forward_declares.ipp +82 -0
  63. data/rice/global_function.hpp +16 -20
  64. data/rice/global_function.ipp +8 -17
  65. data/rice/rice.hpp +59 -0
  66. data/rice/ruby_mark.hpp +5 -3
  67. data/rice/ruby_try_catch.hpp +4 -4
  68. data/rice/stl.hpp +11 -0
  69. data/sample/callbacks/extconf.rb +3 -0
  70. data/sample/callbacks/sample_callbacks.cpp +10 -13
  71. data/sample/enum/extconf.rb +3 -0
  72. data/sample/enum/sample_enum.cpp +3 -17
  73. data/sample/enum/test.rb +2 -2
  74. data/sample/inheritance/animals.cpp +8 -24
  75. data/sample/inheritance/extconf.rb +3 -0
  76. data/sample/inheritance/test.rb +1 -1
  77. data/sample/map/extconf.rb +3 -0
  78. data/sample/map/map.cpp +10 -18
  79. data/sample/map/test.rb +1 -1
  80. data/test/embed_ruby.cpp +18 -5
  81. data/test/ext/t1/extconf.rb +3 -0
  82. data/test/ext/t1/t1.cpp +1 -3
  83. data/test/ext/t2/extconf.rb +3 -0
  84. data/test/ext/t2/t2.cpp +1 -1
  85. data/test/extconf.rb +23 -0
  86. data/test/ruby/test_callbacks_sample.rb +28 -0
  87. data/test/ruby/test_multiple_extensions.rb +18 -0
  88. data/test/ruby/test_multiple_extensions_same_class.rb +14 -0
  89. data/test/ruby/test_multiple_extensions_with_inheritance.rb +20 -0
  90. data/test/test_Address_Registration_Guard.cpp +23 -10
  91. data/test/test_Array.cpp +129 -73
  92. data/test/test_Attribute.cpp +147 -0
  93. data/test/test_Builtin_Object.cpp +34 -14
  94. data/test/test_Class.cpp +149 -275
  95. data/test/test_Constructor.cpp +10 -9
  96. data/test/test_Data_Object.cpp +133 -192
  97. data/test/test_Data_Type.cpp +322 -252
  98. data/test/test_Director.cpp +54 -41
  99. data/test/test_Enum.cpp +228 -103
  100. data/test/test_Exception.cpp +5 -6
  101. data/test/test_Hash.cpp +31 -30
  102. data/test/test_Identifier.cpp +4 -5
  103. data/test/test_Inheritance.cpp +221 -0
  104. data/test/test_Iterator.cpp +161 -0
  105. data/test/test_Jump_Tag.cpp +1 -1
  106. data/test/test_Keep_Alive.cpp +161 -0
  107. data/test/test_Memory_Management.cpp +2 -4
  108. data/test/test_Module.cpp +167 -110
  109. data/test/test_Object.cpp +41 -21
  110. data/test/test_Ownership.cpp +275 -0
  111. data/test/test_Self.cpp +205 -0
  112. data/test/test_Stl_Optional.cpp +90 -0
  113. data/test/test_Stl_Pair.cpp +144 -0
  114. data/test/test_Stl_SmartPointer.cpp +200 -0
  115. data/test/test_Stl_String.cpp +74 -0
  116. data/test/test_Stl_Vector.cpp +652 -0
  117. data/test/test_String.cpp +1 -2
  118. data/test/test_Struct.cpp +29 -39
  119. data/test/test_Symbol.cpp +1 -2
  120. data/test/test_To_From_Ruby.cpp +249 -285
  121. data/test/test_global_functions.cpp +39 -19
  122. data/test/unittest.hpp +0 -4
  123. metadata +63 -139
  124. data/Doxyfile +0 -2268
  125. data/Makefile.am +0 -26
  126. data/Makefile.in +0 -931
  127. data/README.mingw +0 -8
  128. data/aclocal.m4 +0 -1085
  129. data/ax_cxx_compile_stdcxx.m4 +0 -951
  130. data/bootstrap +0 -8
  131. data/config.guess +0 -1421
  132. data/config.sub +0 -1807
  133. data/configure +0 -7792
  134. data/configure.ac +0 -55
  135. data/depcomp +0 -791
  136. data/doxygen.ac +0 -314
  137. data/doxygen.am +0 -186
  138. data/extconf.rb +0 -70
  139. data/install-sh +0 -501
  140. data/missing +0 -215
  141. data/post-autoconf.rb +0 -22
  142. data/post-automake.rb +0 -28
  143. data/rice/Address_Registration_Guard.cpp +0 -22
  144. data/rice/Arg_impl.hpp +0 -129
  145. data/rice/Arg_operators.cpp +0 -21
  146. data/rice/Arg_operators.hpp +0 -19
  147. data/rice/Array.hpp +0 -214
  148. data/rice/Array.ipp +0 -256
  149. data/rice/Builtin_Object.hpp +0 -8
  150. data/rice/Builtin_Object.ipp +0 -50
  151. data/rice/Builtin_Object_defn.hpp +0 -50
  152. data/rice/Class.cpp +0 -57
  153. data/rice/Class.hpp +0 -8
  154. data/rice/Class.ipp +0 -6
  155. data/rice/Class_defn.hpp +0 -84
  156. data/rice/Data_Type.cpp +0 -54
  157. data/rice/Data_Type_fwd.hpp +0 -12
  158. data/rice/Director.cpp +0 -13
  159. data/rice/Exception.cpp +0 -54
  160. data/rice/Exception_Base.hpp +0 -8
  161. data/rice/Exception_Base.ipp +0 -13
  162. data/rice/Exception_Base_defn.hpp +0 -27
  163. data/rice/Hash.hpp +0 -230
  164. data/rice/Hash.ipp +0 -329
  165. data/rice/Identifier.cpp +0 -8
  166. data/rice/Jump_Tag.hpp +0 -24
  167. data/rice/Makefile.am +0 -121
  168. data/rice/Makefile.in +0 -884
  169. data/rice/Module.cpp +0 -84
  170. data/rice/Module.hpp +0 -8
  171. data/rice/Module.ipp +0 -6
  172. data/rice/Module_defn.hpp +0 -88
  173. data/rice/Module_impl.hpp +0 -281
  174. data/rice/Module_impl.ipp +0 -345
  175. data/rice/Object.cpp +0 -169
  176. data/rice/Object.hpp +0 -8
  177. data/rice/Object.ipp +0 -33
  178. data/rice/Object_defn.hpp +0 -214
  179. data/rice/Require_Guard.hpp +0 -21
  180. data/rice/String.cpp +0 -89
  181. data/rice/String.hpp +0 -91
  182. data/rice/Struct.cpp +0 -117
  183. data/rice/Struct.hpp +0 -162
  184. data/rice/Struct.ipp +0 -26
  185. data/rice/Symbol.cpp +0 -25
  186. data/rice/Symbol.hpp +0 -66
  187. data/rice/Symbol.ipp +0 -44
  188. data/rice/config.hpp +0 -47
  189. data/rice/config.hpp.in +0 -46
  190. data/rice/detail/Arguments.hpp +0 -118
  191. data/rice/detail/Auto_Function_Wrapper.hpp +0 -898
  192. data/rice/detail/Auto_Function_Wrapper.ipp +0 -3181
  193. data/rice/detail/Auto_Member_Function_Wrapper.hpp +0 -897
  194. data/rice/detail/Auto_Member_Function_Wrapper.ipp +0 -2501
  195. data/rice/detail/Caster.hpp +0 -103
  196. data/rice/detail/Not_Copyable.hpp +0 -25
  197. data/rice/detail/Wrapped_Function.hpp +0 -33
  198. data/rice/detail/cfp.hpp +0 -24
  199. data/rice/detail/cfp.ipp +0 -51
  200. data/rice/detail/check_ruby_type.cpp +0 -27
  201. data/rice/detail/check_ruby_type.hpp +0 -23
  202. data/rice/detail/creation_funcs.hpp +0 -37
  203. data/rice/detail/creation_funcs.ipp +0 -36
  204. data/rice/detail/define_method_and_auto_wrap.hpp +0 -31
  205. data/rice/detail/define_method_and_auto_wrap.ipp +0 -30
  206. data/rice/detail/demangle.cpp +0 -56
  207. data/rice/detail/demangle.hpp +0 -19
  208. data/rice/detail/env.hpp +0 -11
  209. data/rice/detail/method_data.cpp +0 -92
  210. data/rice/detail/node.hpp +0 -13
  211. data/rice/detail/protect.cpp +0 -29
  212. data/rice/detail/protect.hpp +0 -34
  213. data/rice/detail/ruby_version_code.hpp +0 -6
  214. data/rice/detail/ruby_version_code.hpp.in +0 -6
  215. data/rice/detail/st.hpp +0 -22
  216. data/rice/detail/win32.hpp +0 -16
  217. data/rice/detail/wrap_function.hpp +0 -66
  218. data/rice/protect.hpp +0 -38
  219. data/rice/protect.ipp +0 -1134
  220. data/rice/rubypp.rb +0 -97
  221. data/rice/to_from_ruby.hpp +0 -8
  222. data/rice/to_from_ruby.ipp +0 -418
  223. data/rice/to_from_ruby_defn.hpp +0 -70
  224. data/ruby.ac +0 -135
  225. data/ruby/Makefile.am +0 -1
  226. data/ruby/Makefile.in +0 -628
  227. data/ruby/lib/Makefile.am +0 -3
  228. data/ruby/lib/Makefile.in +0 -506
  229. data/ruby/lib/mkmf-rice.rb.in +0 -217
  230. data/ruby/lib/version.rb +0 -3
  231. data/sample/Makefile.am +0 -53
  232. data/sample/Makefile.in +0 -495
  233. data/test/Makefile.am +0 -73
  234. data/test/Makefile.in +0 -1219
  235. data/test/ext/Makefile.am +0 -41
  236. data/test/ext/Makefile.in +0 -483
  237. data/test/test_rice.rb +0 -45
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b94a556a35a6622bc3a5e9ca9f124020b0d22fffa319df33e3aa0bb35bae4d56
4
- data.tar.gz: bcd79c325fb7cc04396720a8d987d55ba197079743971f012ca71ceeb16de2df
3
+ metadata.gz: d56aeba2a339abc203b192244a3acc552a28aeeba1f87b6a49da38d257ef54bb
4
+ data.tar.gz: 73fc9c71575f1773080fc77951802c3afd6adbceac3f73357a9741fc87d8ff03
5
5
  SHA512:
6
- metadata.gz: a6122026933d06b8866e486fcd954f6e55a148caab22fe95072cbf5ff6937936d2900e0374b6e276fb14c476c1413833cbd05e536757aea13f7ee431ac163a27
7
- data.tar.gz: a7202f164e6cf63259bc3d2b8aa90a7306e53f88305f1c558a4ebd6d1d60b22e7eacf8466667b0fd3ce8123002e44a62a3896f9e4ecb69b3b412f09b23bf64af
6
+ metadata.gz: e3adf97953881b6047ee1bd55f1e3dcb42dbcf2d8d431813355949d41937742a4a3574e317db304c3fe6bfbda766f8a29ecb098cff43e9e7e46c48214ab92d53
7
+ data.tar.gz: ff3917608dd7abdca6430554c99a78b7166abdde8d808778c455ddc12de974af0fbeb3702cdfa7a02830386978e39f507b4506d4cdba4ad865da9e28f980237e
data/CHANGELOG.md ADDED
@@ -0,0 +1,121 @@
1
+ ## 4.0
2
+
3
+ Rice 4.0 is a significant change from 3.0 and has multiple backwards-incompatible
4
+ changes. Rice 4.0 no longer requires pre-compilation and is now a header-only library,
5
+ delivered as a combined header file.
6
+
7
+ For migrating from 3 to 4, see [the migration guide](https://jasonroelofs.com/rice/4.x/migration.html).
8
+
9
+ There are a ton of changes, but some of the most important ones:
10
+
11
+ * Header only! `#include <rice/rice.hpp>`
12
+ * Requires C++17 or later
13
+ * Brand new, expanded documentation
14
+ * [Built-in STL support](https://jasonroelofs.com/rice/4.x/stl/stl.html)
15
+ * And so much more. See the documentation for more details.
16
+
17
+ ## 3.0
18
+
19
+ * Now requires a compiler supporting for C++14 or later
20
+ * Drop support for Ruby 2.4. Supported versions are now 2.5 through 3.0.
21
+ * Fix build issue on macOS Big Sur
22
+ * Fix a data corruption issue with `Rice::Exception::what`.
23
+ * Move CI from Travis to GitHub Actions. Now also able to verify Windows builds!
24
+
25
+ ## 2.2.0
26
+
27
+ * Deprecate support for Rubies older than 2.4
28
+ * Provide a few more built-in to_ruby/from_ruby conversions
29
+ * Fix compilation error when building under Ruby 2.7.0
30
+
31
+ ## 2.1.3
32
+
33
+ * Don't lock down HAVE_CXX11 on the Rice build itself.
34
+
35
+ ## 2.1.2
36
+
37
+ * Fix defining custom `begin` and `end` methods on an `Iterator`
38
+
39
+ ## 2.1.1
40
+
41
+ * Support Ruby 2.4
42
+ * Re-enable Rice::Enum#hash to support putting Enums in Hashes
43
+
44
+ ## 2.1.0
45
+
46
+ * Fix compliation issues related to g++ and Ruby 2.3.0
47
+ To do this, I had to remove Array::to_c_array which was exposing the internals of a
48
+ Ruby RArray type to the system. This is not something that we should support going forward
49
+ as these internals are going to change.
50
+
51
+ # 2.0.0
52
+
53
+ * Deprecated all versions of Ruby < 2.0
54
+ * Removed Rice::VM.
55
+ Unsure if this class is even used anywhere and it felt strange to be
56
+ able to load up a Ruby interpreter inside of Ruby. If you need it, it's
57
+ two files that I can easily make available in a gist.
58
+ * Improve build process across architectures and future changes.
59
+ Included some extra warnings for XCode updates on Mac OS X.
60
+ * Confirmed that Rice definitely does not work on static Ruby builds,
61
+ but that seems to be more because newer Ruby versions don't have good static builds.
62
+ Thanks to @Kagetsuki for his help tracking down what's going on here.
63
+
64
+ ## 1.7.0
65
+
66
+ * Ruby 2.2 support
67
+ Potential breaking changes. Ruby 2.2 removed RHash as a public accessible struct
68
+ and as such I changed all of the Builtin_Objects to work directly off of RObject
69
+ instead of the specifics (RArray, RStruct, RString, etc). If you've been using these
70
+ objects directly I recommend using either the Rice API or Ruby's CAPI instead for
71
+ future compatibility.
72
+
73
+ ## 1.6.3
74
+
75
+ * Fix complication issue on some 64-bit *nix systems
76
+
77
+ ## 1.6.2
78
+
79
+ * Oops! Missed new file in the gemspec
80
+
81
+ ## 1.6.1
82
+
83
+ * Support C++x11 uniqe_ptr over auto_ptr
84
+ * Fix some warnings
85
+
86
+ ## 1.6.0
87
+
88
+ * Ruby 2.1 support -- Thanks Chai Zhenhua
89
+ * Methods and Constructors have correct method access specifiers [#57]
90
+ * Clean up some 64-bit compiler warnings
91
+
92
+ ## 1.5.3
93
+
94
+ * Fix signed / unsigned compiler warning with Hash#each
95
+ * Fix compilation on clang 5 (Xcode 5)
96
+
97
+ ## 1.5.2
98
+
99
+ * Update build system to remove deprecation warnings and allow easier building
100
+ * Fix String to work as a parameter in a wrapped method (#59)
101
+ * Update documentation a bit
102
+
103
+ ## 1.5.1
104
+
105
+ * Doc string fix
106
+
107
+ ## 1.5.0
108
+
109
+ * Ruby 2.0 compatability
110
+ * Bug fixes
111
+
112
+ ## 1.4.3
113
+
114
+ * Various build configuration fixes
115
+
116
+ ## 1.4.0
117
+
118
+ * Fully compatible with Ruby 1.9.2
119
+ * Constructor supports default arguments
120
+ * Ability to define implicit casting through define_implicit_cast
121
+ * Fixed a few memory-related issues
data/CONTRIBUTORS.md ADDED
@@ -0,0 +1,19 @@
1
+ Contributors
2
+ ============
3
+
4
+ I'd like to thank the following people for their help in making Rice what it is today.
5
+
6
+ * [Paul Brannon (cout)](https://github.com/cout) for initially building and releasing this library as open source.
7
+ * [Sylvain Joyeux (doudou)](https://github.com/doudou) for [PR #23](https://github.com/jasonroelofs/rice/pull/23) and [PR #68](https://github.com/jasonroelofs/rice/pull/68)
8
+ * [Pat McNally (patmcnally)](https://github.com/patmcnally) for [PR #38](https://github.com/jasonroelofs/rice/pull/38)
9
+ * [Victor Costan (pwnall)](https://github.com/pwnall) for [PR #54](https://github.com/jasonroelofs/rice/pull/54)
10
+ * [Zachary Salzbank (zsalzbank)](https://github.com/zsalzbank) for [PR #55](https://github.com/jasonroelofs/rice/pull/55)
11
+ * [Chai Zhenhua (chaizhenhua)](https://github.com/jasonroelofs/rice/pull/58) for [PR #58](https://github.com/jasonroelofs/rice/pull/58)
12
+ * [Alexander Rüedlinger (lexruee)](https://github.com/lexruee) for [PR #81](https://github.com/jasonroelofs/rice/pull/81)
13
+ * [ryannevell](https://github.com/ryannevell) for [PR #98](https://github.com/jasonroelofs/rice/pull/98)
14
+ * [Samu Voutilainen (smarre)](https://github.com/Smarre) for [PR #102](https://github.com/jasonroelofs/rice/pull/102)
15
+ * [Harald Sitter (apachelogger)](https://github.com/apachelogger) for [PR #104](https://github.com/jasonroelofs/rice/pull/104)
16
+ * [nobu](https://github.com/nobu) for [PR #122](https://github.com/jasonroelofs/rice/pull/122)
17
+ * [Charlie Savage (cfis)](https://github.com/cfis) for multiple improvements and modernizations: [#130](https://github.com/jasonroelofs/rice/pull/130), [#131](https://github.com/jasonroelofs/rice/pull/131), [#133](https://github.com/jasonroelofs/rice/pull/133), [#134](https://github.com/jasonroelofs/rice/pull/134), [#136](https://github.com/jasonroelofs/rice/pull/136), [#137](https://github.com/jasonroelofs/rice/pull/137), [#140](https://github.com/jasonroelofs/rice/pull/140), [#141](https://github.com/jasonroelofs/rice/pull/141) and many others, including the work to make Rice header-only.
18
+ * [Atsushi Tatsuma (yoshoku)](https://github.com/yoshoku) for [#135](https://github.com/jasonroelofs/rice/pull/135)
19
+ * [Andrew Kane (ankane)](https://github.com/ankane) for helping [test Rice 4](https://github.com/jasonroelofs/rice/issues/149).
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
data/README.md CHANGED
@@ -1,20 +1,32 @@
1
- # Rice - Ruby Interface for C++ Extensions {#mainpage}
1
+ # Rice - Ruby Interface for C++ Extensions
2
2
 
3
- # Introduction {#intro}
3
+ # Introduction
4
4
 
5
- Rice is a C++ interface to Ruby's C API. It provides a type-safe and
6
- exception-safe interface in order to make embedding Ruby and writing
7
- Ruby extensions with C++ easier. It is similar to Boost.Python or pybind11
8
- in many ways, but also attempts to provide an object-oriented interface to all
9
- of the Ruby C API.
5
+ Rice is a C++ header-only library that serves dual purposes. First, it makes it much
6
+ easier to create Ruby bindings for existing C++ libraries. Second, it provides an
7
+ object oriented interface to Ruby's C API that makes it easy to embed Ruby and write
8
+ Ruby extensions in C++.
9
+
10
+ Rice is similar to Boost.Python and pybind11 in that it minimizes boilerplate code needed
11
+ to interface with C++. It does this by automatically determining type information allowing
12
+ Ruby object to be converted to C++ and vice versa.
10
13
 
11
14
  What Rice gives you:
12
15
  - A simple C++-based syntax for wrapping and defining classes
13
- - Automatic conversion of exceptions between C++ and Ruby
16
+ - Automatic type conversions between C++ and Ruby
17
+ - Automatic exception conversions between C++ and Ruby
14
18
  - Smart pointers for handling garbage collection
15
19
  - Wrappers for most builtin types to simplify calling code
16
20
 
17
- # Project Details {#project}
21
+ # Version Differences 3.x vs 4.x and later
22
+
23
+ This documentation and the `master` branch are for Rice 4.x and later, which is the
24
+ header-only version of this library. Use the `3.x` branch for the docs and code for that
25
+ line of releases.
26
+
27
+ The docs for the 3.x line of Rice is at https://jasonroelofs.com/rice/3.x.
28
+
29
+ # Project Details
18
30
 
19
31
  The source is hosted on GitHub: http://github.com/jasonroelofs/rice
20
32
 
@@ -22,1029 +34,36 @@ Bug tracking: http://github.com/jasonroelofs/rice/issues
22
34
 
23
35
  API documentation: http://jasonroelofs.github.io/rice
24
36
 
25
- # Installation {#installation}
37
+ # Installation
26
38
 
27
- ~~~
39
+ ```bash
28
40
  gem install rice
29
- ~~~
30
-
31
- Building it locally from a clone of the repository is as follows:
32
-
33
- ~~~
34
- ./bootstrap
35
- ruby extconf.rb
36
- make
37
- ~~~
38
-
39
- Rice is known to work on *nix, OSX, and Windows.
40
-
41
- Rice requires a C++ compiler with support for C++14 or later.
42
-
43
- # Tutorial {#tutorial}
44
-
45
- ## Getting started {#getting_started}
46
-
47
- Writing an extension with Rice is very similar to writing an extension
48
- with the C API.
49
-
50
- The first step is to create an extconf.rb file:
51
-
52
- ~~~{.cpp}
53
- require 'mkmf-rice'
54
- create_makefile('test')
55
- ~~~
56
-
57
- Note that we use `mkmf-rice` instead of `mkmf`. This will ensure that the
58
- extension will be linked with standard C++ library along with the Rice
59
- library, and allow access to the Rice header files.
60
-
61
- Next we create our extension and save it to test.cpp:
62
-
63
- ~~~{.cpp}
64
- extern "C"
65
- void Init_test()
66
- {
67
- }
68
- ~~~
69
-
70
- Note the extern "C" line above. This tells the compiler that the
71
- function `Init_test` should have C linkage and calling convention. This
72
- turns off name mangling so that the Ruby interpreter will be able to
73
- find the function (remember that Ruby is written in C, not C++).
74
-
75
- So far we haven't put anything into the extension, so it isn't
76
- particularly useful. The next step is to define a class so we can add
77
- methods to it.
78
-
79
-
80
- ## Defining clases {#classes}
81
-
82
- Defining a class in Rice is a single call:
83
-
84
- ~~~{.cpp}
85
- #include "rice/Class.hpp"
86
-
87
- using namespace Rice;
88
-
89
- extern "C"
90
- void Init_test()
91
- {
92
- Class rb_cTest = define_class("Test");
93
- }
94
- ~~~
95
-
96
- This will create a class called `Test` that inherits from `Object`. If we
97
- wanted to inherit from a different class, we do so with the second parameter:
98
-
99
- ~~~{.cpp}
100
- #include "rice/Class.hpp"
101
-
102
- using namespace Rice;
103
-
104
- extern "C"
105
- void Init_test()
106
- {
107
- Class rb_cMySocket = define_class("MySocket", rb_cIO);
108
- }
109
- ~~~
110
-
111
- Note the prefix rb_c on the name of the class. This is a convention
112
- that the Ruby interpreter and many extensions tend to use. It signifies
113
- that this is a class and not some other type of object. Some other
114
- naming conventions that are commonly used:
115
-
116
- - rb_c variable name prefix for a Class
117
- - rb_m variable name prefix for a Module
118
- - rb_e variable name prefix for an Exception type
119
- - rb_ function prefix for a function in the Ruby C API
120
- - rb_f_ function prefix to differentiate between an API function that
121
- takes Ruby objects as arguments and one that takes C argument types
122
- - rb_*_s_ indicates the function is a singleton function
123
- - *_m suffix to indicate the function takes variable number of
124
- arguments
125
-
126
-
127
- Also note that we don't include "ruby.h" directly. Rice has a wrapper
128
- for ruby.h that handles some compatibility issues across platforms and
129
- Ruby versions. Always include Rice headers before including anything
130
- that might include "ruby.h".
131
-
132
- ## Defining methods {#methods}
133
-
134
- Now let's add a method to our class:
135
-
136
- ~~~{.cpp}
137
- #include "rice/Class.hpp"
138
- #include "rice/String.hpp"
139
-
140
- using namespace Rice;
141
-
142
- Object test_hello(Object /* self */)
143
- {
144
- String str("hello, world");
145
- return str;
146
- }
147
-
148
- extern "C"
149
- void Init_test()
150
- {
151
- Class rb_cTest =
152
- define_class("Test")
153
- .define_method("hello", &test_hello);
154
- }
155
- ~~~
156
-
157
- Here we add a method `%Test#hello` that returns the string
158
- "Hello, World". The method takes self as an implicit parameter, but
159
- isn't used, so we comment it out to prevent a compiler warning.
160
-
161
- We could also add an `#initialize` method to our class:
162
-
163
- ~~~{.cpp}
164
- #include "rice/Class.hpp"
165
- #include "rice/String.hpp"
166
-
167
- using namespace Rice;
168
-
169
- Object test_initialize(Object self)
170
- {
171
- self.iv_set("@foo", 42);
172
- }
173
-
174
- Object test_hello(Object /* self */)
175
- {
176
- String str("hello, world");
177
- return str;
178
- }
179
-
180
- extern "C"
181
- void Init_test()
182
- {
183
- Class rb_cTest =
184
- define_class("Test")
185
- .define_method("initialize", &test_initialize)
186
- .define_method("hello", &test_hello);
187
- }
188
- ~~~
189
-
190
- The `initialize` method sets an instance variable `@foo` to the value 42.
191
- The number is automatically converted to a `Fixnum` before doing the
192
- assignment.
193
-
194
- Note that we're chaining calls on the `Class` object. Most member
195
- functions in `Module` and `Class` return a reference to `self`, so we can
196
- chain as many calls as we want to define as many methods as we want.
197
-
198
-
199
- ## Wrapping C++ Types {#data_types}
200
-
201
- It's useful to be able to define Ruby classes in a C++ style rather than
202
- using the Ruby API directly, but the real power Rice is in wrapping
203
- already-defined C++ types.
204
-
205
- Let's assume we have the following C++ class that we want to wrap:
206
-
207
- ~~~{.cpp}
208
- class Test
209
- {
210
- public:
211
- Test();
212
- std::string hello();
213
- };
214
- ~~~
215
-
216
- This is a C++ version of the Ruby class we just created in the previous
217
- section. To wrap it:
218
-
219
- ~~~{.cpp}
220
- #include "rice/Data_Type.hpp"
221
- #include "rice/Constructor.hpp"
222
-
223
- using namespace Rice;
224
-
225
- extern "C"
226
- void Init_test()
227
- {
228
- Data_Type<Test> rb_cTest =
229
- define_class<Test>("Test")
230
- .define_constructor(Constructor<Test>())
231
- .define_method("hello", &Test::hello);
232
- }
233
- ~~~
234
-
235
- This example is similar to the one before, but we use `Data_Type<>`
236
- instead of `Class` and the template version of define_class() instead of
237
- the non-template version. This creates a binding in the Rice library
238
- between the Ruby class `Test` and the C++ class Test such that Rice passes
239
- member function pointers to `define_method()`.
240
-
241
- It is possible to write the conversion functions ourself (as we'll see
242
- below), but Rice does all the dirty work for us.
243
-
244
-
245
- ## Type conversions {#conversions}
246
-
247
- Let's look again at our example class:
248
-
249
- ~~~{.cpp}
250
- class Test
251
- {
252
- public:
253
- Test();
254
- std::string hello();
255
- };
256
- ~~~
257
-
258
- When we wrote our class, we never wrote a single line of code to convert
259
- the `std::string` returned by `hello()` into a Ruby type. Neverthless, the
260
- conversion works, and when we write:
261
-
262
- ~~~{.cpp}
263
- test = Test.new
264
- puts test.hello
265
- ~~~
266
-
267
- We get the expected result.
268
-
269
- Rice has two template conversion functions to convert between C++ and
270
- Ruby types:
271
-
272
- ~~~{.cpp}
273
- template<typename T>
274
- T from_ruby(Object x);
275
-
276
- template<typename T>
277
- Object to_ruby(T const & x);
278
- ~~~
279
-
280
- Rice includes default specializations for many of the builtin
281
- types. To define your own conversion, write a template specialization:
282
-
283
- ~~~{.cpp}
284
- template<>
285
- Foo from_ruby<Foo>(Object x)
286
- {
287
- // ...
288
- }
289
-
290
- template<>
291
- Object to_ruby<Foo>(Foo const & x)
292
- {
293
- // ...
294
- }
295
- ~~~
296
-
297
- The implementation of these functions would, of course, depend on the
298
- implementation of `Foo`.
299
-
300
-
301
- ## Conversions for wrapped C++ types {#data_conversions}
302
-
303
- Take another look at the wrapper we wrote for the `Test` class:
304
-
305
- ~~~{.cpp}
306
- extern "C"
307
- void Init_test()
308
- {
309
- Data_Type<Test> rb_cTest =
310
- define_class<Test>("Test")
311
- .define_constructor(Constructor<Test>())
312
- .define_method("hello", &Test::hello);
313
- }
314
- ~~~
315
-
316
- When we called `define_class<Test>`, it created a Class for us and
317
- automatically registered the new Class with the type system, so that the
318
- calls:
319
-
320
- ~~~{.cpp}
321
- Data_Object<Foo> obj(new Foo);
322
- Foo * f = from_ruby<Foo *>(obj);
323
- Foo const * f = from_ruby<Foo const *>(obj);
324
- ~~~
325
-
326
- works as expected.
327
-
328
- The `Data_Object` class is a wrapper for the `Data_Wrap_Struct` and the
329
- `Data_Get_Struct` macros in C extensions. It can be used to wrap or
330
- unwrap any class that has been assigned to a `Data_Type`. It inherits
331
- from `Object`, so any member functions we can call on an `Object` we can
332
- also call on a `Data_Object`:
333
-
334
- ~~~{.cpp}
335
- Object object_id = obj.call("object_id");
336
- std::cout << object_id << std::endl;
337
- ~~~
338
-
339
- The `Data_Object` class can be used to wrap a newly-created object:
340
-
341
- ~~~{.cpp}
342
- Data_Object<Foo> foo(new Foo);
343
- ~~~
344
-
345
- or to unwrap an already-created object:
346
-
347
- ~~~{.cpp}
348
- VALUE obj = ...;
349
- Data_Object<Foo> foo(obj);
350
- ~~~
351
-
352
- A `Data_Object` functions like a smart pointer:
353
-
354
- ~~~{.cpp}
355
- Data_Object<Foo> foo(obj);
356
- foo->foo();
357
- std::cout << *foo << std::endl;
358
- ~~~
359
-
360
- Like a `VALUE` or an `Object`, data stored in a `Data_Object` will be marked
361
- by the garbage collector as long as the `Data_Object` is on the stack.
362
-
363
-
364
- ## Exceptions {#exception}
365
-
366
- Suppose we added a member function to our example class that throws an
367
- exception:
368
-
369
- ~~~{.cpp}
370
- class MyException
371
- : public std::exception
372
- {
373
- };
374
-
375
- class Test
376
- {
377
- public:
378
- Test();
379
- std::string hello();
380
- void error();
381
- };
382
- ~~~
383
-
384
- If we were to wrap this function:
385
-
386
- ~~~{.cpp}
387
- extern "C"
388
- void Init_test()
389
- {
390
- Data_Type<Test> rb_cTest =
391
- define_class<Test>("Test")
392
- .define_constructor(Constructor<Test>())
393
- .define_method("hello", &Test::hello)
394
- .define_method("error", &Test::error);
395
- }
396
- ~~~
397
-
398
- and call it from inside Ruby:
399
-
400
- ~~~{.cpp}
401
- test = Test.new
402
- test.error()
403
- ~~~
404
-
405
- we would get an exception. Rice will automatically convert any
406
- C++ exception it catches into a Ruby exception. But what if we wanted
407
- to use a custom error message when we convert the exception, or what if
408
- we wanted to convert to a different type of exception? We can write
409
- an exception handler like so:
410
-
411
- ~~~{.cpp}
412
- extern "C"
413
- void Init_test()
414
- {
415
- Data_Type<Test> rb_cTest =
416
- define_class<Test>("Test")
417
- .add_handler<MyException>(handle_my_exception)
418
- .define_constructor(Constructor<Test>())
419
- .define_method("hello", &Test::hello)
420
- .define_method("error", &Test::error);
421
- }
422
- ~~~
423
-
424
- The `handle_my_exception` function need only rethrow the exception as a
425
- `Rice::Exception`:
426
-
427
- ~~~{.cpp}
428
- void handle_my_exception(MyException const & ex)
429
- {
430
- throw Exception(rb_eRuntimeError, "Goodnight, moon");
431
- }
432
- ~~~
433
-
434
- And what if we want to call Ruby code from C++? These exceptions are
435
- also converted:
436
-
437
- ~~~{.cpp}
438
- Object o;
439
- o.call("some_function_that_raises", 42);
440
-
441
- protect(rb_raise, rb_eRuntimeError, "some exception msg");
442
- ~~~
443
-
444
- Internally whenever Rice catches a C++ or a Ruby exception, it converts
445
- it to an `Exception` object. This object will later be re-raised as a
446
- Ruby exception when control is returned to the Ruby VM.
447
-
448
- Rice uses a similar class called `Jump_Tag` to handle symbols thrown by
449
- Ruby's `throw`/`catch` or other non-local jumps from inside the Ruby VM.
450
-
451
-
452
- ## Builtin Types {#builtin}
453
-
454
- You've seen this example:
455
-
456
- ~~~{.cpp}
457
- Object object_id = obj.call("object_id");
458
- std::cout << object_id << std::endl;
459
- ~~~
460
-
461
- Rice mimics the Ruby class hierarchy as closely as it can.
462
- In fact, the above code also works for Classes:
463
-
464
- ~~~{.cpp}
465
- Class rb_cTest = define_class<Test>("Test");
466
- Object object_id = rb_cTest.call("object_id");
467
- std::cout << object_id << std::endl;
468
- ~~~
469
-
470
- Rice provides builtin wrappers for many builtin Ruby types, including:
471
-
472
- - Object
473
- - Module
474
- - Class
475
- - String
476
- - Array
477
- - Hash
478
- - Struct
479
- - Symbol
480
- - Exception
481
-
482
- The `Array` and `Hash` types can even be iterated over the same way one
483
- would iterate over an STL container:
484
-
485
- ~~~{.cpp}
486
- Array a;
487
- a.push(to_ruby(42));
488
- a.push(to_ruby(43));
489
- a.push(to_ruby(44));
490
- Array::iterator it = a.begin();
491
- Array::iterator end = a.end();
492
- for(; it != end; ++it)
493
- {
494
- std::cout << *it << std::endl;
495
- }
496
- ~~~
497
-
498
- STL algorithms should also work as expected on `Array` and `Hash` containers.
499
-
500
-
501
- ## Inheritance {#inheritance}
502
-
503
- Inheritance is a tricky problem to solve in extensions. This is because
504
- wrapper functions for base classes typically don't know how to accept
505
- pointers to derived classes. It is possible to write this logic, but
506
- the code is nontrivial.
507
-
508
- Rice also provides a solution to this problem:
509
-
510
- ~~~{.cpp}
511
- class Base
512
- {
513
- public:
514
- virtual void foo();
515
- };
516
-
517
- class Derived
518
- : public Base
519
- {
520
- };
521
-
522
- extern "C"
523
- void Init_test()
524
- {
525
- Data_Type<Base> rb_cBase =
526
- define_class<Base>("Base")
527
- .define_method("foo", &Base::foo);
528
- Data_Type<Derived> rb_cDerived =
529
- define_class<Derived, Base>("Derived");
530
- }
531
- ~~~
532
-
533
- The second template parameter to define_class indicates that `Derived`
534
- inherits from `Base`.
535
-
536
- Rice does not support multiple inheritance.
537
-
538
-
539
- ## Overloaded functions {#overloading}
540
-
541
- If you try to create a member function pointer to an overloaded
542
- function, you will get an error. So how do we wrap classes that have
543
- overloaded functions?
544
-
545
- Consider a class that uses this idiom for accessors:
546
-
547
- ~~~{.cpp}
548
- class Container
549
- {
550
- size_t capacity(); // Get the capacity
551
- void capacity(size_t cap); // Set the capacity
552
- };
553
- ~~~
554
-
555
- We can wrap this class by using `typedef`s:
556
-
557
- ~~~{.cpp}
558
- extern "C"
559
- void Init_Container()
560
- {
561
- typedef size_t (Container::*get_capacity)();
562
- typedef void (Container::*set_capacity)(size_t);
563
-
564
- Data_Type<Container> rb_cContainer =
565
- define_class<Container>("Container")
566
- .define_method("capacity", get_capacity(&Container::capacity))
567
- .define_method("capacity=", set_capacity(&Container::capacity))
568
- }
569
- ~~~
570
-
571
-
572
- ## User-defined type conversions {#user_defined_conversions}
573
-
574
- Rice provides default conversions for many built-in types. Sometimes,
575
- however, the default conversion is not what is expected. For
576
- example, consider a function:
577
-
578
- ~~~{.cpp}
579
- void foo(char * x);
580
- ~~~
581
-
582
- Is `x` a pointer to a single character or a pointer to the first character
583
- of a null-terminated string or a pointer to the first character of an
584
- array of char?
585
-
586
- Because the second case is the most common use case (a pointer to the
587
- first character of a C string), Rice provides a default conversion that
588
- treats a `char *` as a C string. But suppose the above function actually
589
- expects to receive a pointer to a single char instead?
590
-
591
- If we write this:
592
-
593
- ~~~{.cpp}
594
- extern "C"
595
- void Init_test()
596
- {
597
- define_global_function("foo", &foo);
598
- }
599
- ~~~
600
-
601
- It will likely have the wrong behavior.
602
-
603
- To avoid this problem, it is necessary to write a wrapper function where
604
- the extension can be more explicit about how to handle the parameters:
605
-
606
- ~~~{.cpp}
607
- Object wrap_foo(Object o)
608
- {
609
- char c = from_ruby<char>(o);
610
- foo(&c);
611
- return to_ruby(c);
612
- }
613
-
614
- extern "C"
615
- void Init_test()
616
- {
617
- define_global_function("foo", &wrap_foo);
618
- }
619
- ~~~
620
-
621
- Note that the out parameter is returned from `wrap_foo`, as Ruby does not
622
- have pass-by-variable-reference (it uses pass-by-object-reference).
623
-
624
-
625
- ## Default Arguments {#default_arguments}
626
-
627
- Going back to our initial C++ class example, lets say that `hello()` now
628
- takes more arguments, one of which has a default value:
629
-
630
- ~~~{.cpp}
631
- class Test
632
- {
633
- public:
634
- Test();
635
- std::string hello(std::string first, std::string second = "world");
636
- };
637
- ~~~
638
-
639
- As default parameter information is not available through templates,
640
- it is necessary to define this in Rice explicitly using `Rice::Arg`:
641
-
642
- ~~~{.cpp}
643
- #include "rice/Data_Type.hpp"
644
- #include "rice/Constructor.hpp"
645
-
646
- using namespace Rice;
647
-
648
- extern "C"
649
- void Init_test()
650
- {
651
- Data_Type<Test> rb_cTest =
652
- define_class<Test>("Test")
653
- .define_constructor(Constructor<Test>())
654
- .define_method("hello",
655
- &Test::hello,
656
- (Arg("hello"), Arg("second") = "world")
657
- );
658
- }
659
- ~~~
660
-
661
- The syntax here is `Arg(nameOfParameter)[ = defaultValue]`. The name of the
662
- parameter is not important here (it is for readability), but the value set via `operator=`
663
- must match the type of the parameter. As such it may be necessary to
664
- explicitly cast the default value.
665
-
666
- ~~~{.cpp}
667
- .define_method("hello",
668
- &Test::hello,
669
- (Arg("hello"), Arg("second") = (std::string)"world")
670
- );
671
- ~~~
672
-
673
- These `Rice::Arg` objects must be in the correct order and must be
674
- surrounded with parentheses if more than one exists.
675
-
676
- Now, Ruby will now know about the default arguments, and this wrapper
677
- can be used as expected:
678
-
679
- ~~~{.cpp}
680
- t = Test.new
681
- t.hello("hello")
682
- t.hello("goodnight", "moon")
683
- ~~~
684
-
685
- This also works with Constructors:
686
-
687
- ~~~{.cpp}
688
- .define_constructor(Constructor<SomeClass, int, int>(),
689
- ( Arg("arg1") = 1, Arg("otherArg") = 12 );
690
- ~~~
691
-
692
- ## Director {#director}
693
-
694
- Polymorphism creates yet another wrinkle in building exceptions around C++ code,
695
- because now we have to deal with cross-language polymorphism, where C++ can call
696
- into a Ruby subclass, and a Ruby subclass can `super` back into C++ land. `super`
697
- calls already work through define_class, but making code travel from C++ into Ruby
698
- via polymorphism is tricker. Rice provides the `Rice::Director` class and the
699
- `define_director` method to enable this code path.
700
-
701
- Like `SWIG_Director`, `Rice::Director` is a class that is used to build a proxy class
702
- to properly send execution up or down the object hierarchy for that class. Take
703
- the following class:
704
-
705
- ~~~{.cpp}
706
- class VirtualBase {
707
- public:
708
- VirtualBase();
709
- virtual int doWork();
710
- virtual int processWorker() = 0;
711
- };
712
- ~~~
713
-
714
- Due to the abstract nature of this class, we cannot directly wrap it in Rice, as
715
- any C++ compiler will complain about trying to instantiate a virtual class.
716
- Even without the pure virtual function, any call to `VirtualBase::doWork` will stop
717
- at the C++ level and execution will not pass down into any Ruby subclasses.
718
-
719
- To properly wrap both of these methods, use a `Rice::Director` subclass as a proxy
720
- and use this new proxy class as the type to wrap with `define_class`:
721
-
722
- ~~~{.cpp}
723
- #include "rice/Director.hpp"
724
-
725
- class VirtualBaseProxy : public VirtualBase, public Rice::Director {
726
- public:
727
- VirtualBaseProxy(Object self) : Rice::Director(self) { }
728
-
729
- virtual int doWork() {
730
- return from_ruby<int>( getSelf().call("do_work") );
731
- }
732
-
733
- int default_doWork() {
734
- return VirtualBase::doWork();
735
- }
736
-
737
- virtual int processWorker() {
738
- return from_ruby<int>( getSelf().call("process_worker") );
739
- }
740
-
741
- int default_processWorker() {
742
- raisePureVirtual();
743
- }
744
- };
745
- ~~~
746
-
747
- There is a lot going on here, so we'll go through each part.
748
-
749
- ~~~{.cpp}
750
- class VirtualBaseProxy : public Virtualbase, public Rice::Director {
751
- ~~~
752
-
753
- First, the class needs to subclass both the virtual class in question and `Rice::Director`.
754
-
755
- ~~~{.cpp}
756
- public:
757
- VirtualBaseProxy(Object self) : Rice::Director(self) { }
758
- ~~~
759
-
760
- For `Rice::Director` to work its magic, every instance of this class needs to
761
- have a handle to its Ruby instance. The constructor
762
- must take a `Rice::Object` as the first argument and pass it up into
763
- `Rice::Director`. The code here is the minimum required for a `Rice::Director` proxy.
764
-
765
- ~~~{.cpp}
766
- virtual int doWork() {
767
- return from_ruby<int>( getSelf().call("do_work") );
768
- }
769
-
770
- int default_doWork() {
771
- return VirtualBase::doWork();
772
- }
773
- ~~~
774
-
775
- Here the proxy class implements the virtual methods and provides implementations
776
- that delegate execution in the correct direction. The actual method calls into Ruby,
777
- providing all necessary type conversions to and from C++ types. The other method
778
- is how Ruby calls back into C++ and is the method that must be exposed with
779
- `define_method`. The `default_` prefix is a naming convention to help keep straight
780
- which methods perform which function. If Ruby should never call into C++, then the
781
- `default_` implementation should call `raisePureVirtual()`:
782
-
783
- ~~~{.cpp}
784
- int default_processWorker() {
785
- raisePureVirtual();
786
- }
787
- ~~~
788
-
789
- The method `raisePureVirtual()` exists to allow wrapping a pure virtual method into Ruby
790
- (and ensuring compliation is possible) but making sure any users of this extension are
791
- informed quickly that there's nothing callable in the C++ side of the library.
792
-
793
- Once the proxy class is built, it's time to wrap it into Ruby:
794
-
795
- ~~~{.cpp}
796
- extern "C"
797
- void Init_virtual() {
798
- define_class<VirtualBase>("VirtualBase")
799
- .define_director<VirtualBaseProxy>()
800
- .define_constructor(Constructor<VirtualBaseProxy, Rice::Object>())
801
- .define_method("do_work", &VirtualBaseProxy::default_doWork)
802
- .define_method("process_worker", &VirtualBaseProxy::default_processWorker);
803
- }
804
- ~~~
805
-
806
- The wrapping is the same as is described earlier in this document. Expose the class
807
- `VirtualBase`, and register `VirtualBaseProxy` as a director proxy of `VirtualBase` with
808
- `Rice::Data_Type::define_director`, then `define_method`s pointing to the proxy methods as necessary.
809
-
810
- You must use the `Rice::Director` proxy class in the Constructor line, this allows proper
811
- object construction / destruction of the types in question.
812
-
813
- ## Implicit Casting {#implicit_cast}
814
-
815
- There are times when a library exposes classes that, while unrelated, are
816
- built to be interchangeable across the library. One example of this is found in
817
- the Open Source 3d rendering engine <a
818
- href="http://www.ogre3d.org/">OGRE</a>: Ogre::Degree and Ogre::Radian.
819
- When a given method takes a Radian, you're free to pass in a Degree, and vice versa.
820
-
821
- Rice cannot automatically figure out if this kind of functionality is
822
- possible in a given library but it does provide an API for defining
823
- these relationships: `Rice::define_implicit_cast<From, To>()`.
824
-
825
- ~~~{.cpp}
826
- class Degree { ... };
827
- class Radian { ... };
828
-
829
- extern "C"
830
- void Init_implicit() {
831
- define_class<Degree>()
832
- ...;
833
- define_class<Radian>()
834
- ...;
835
-
836
- define_implicit_cast<Degree, Radian>();
837
- define_implicit_cast<Radian, Degree>();
838
- }
839
- ~~~
840
-
841
- Using `Rice::define_implicit_cast` has the following requirements:
842
-
843
- - The two types must be bound in Rice before defining the cast.
844
- - The classes must have constructors that take the other type.
845
- - This feature cannot be used with fundamental types.
846
-
847
- To see a full example of this feature, please check out
848
- test/test_Data_Type.cpp.
849
-
850
- # Motivation {#motivation}
851
-
852
- There are a number of common problems when writing C or C++ extensions
853
- for Ruby:
854
-
855
- - Type safety. It is easy to mix-up integral types such as ID and
856
- VALUE. Some of the functions in the Ruby API are not consistent with
857
- which types they take (e.g. rb_const_defined takes an ID and
858
- rb_mod_remove_const takes a Symbol).
859
-
860
- - DRY principle. Specifying the number of arguments that each wrapped
861
- function takes is easy to get wrong. Adding a new argument to the
862
- function means that the number of arguments passed to rb_define_method
863
- must also be updated.
864
-
865
- - Type conversion. There are many different functions to convert data
866
- to and from ruby types. Many of them have different semantics or
867
- different forms. For example, to convert a string, one might use the
868
- StringValue macro, but to convert a fixnum, one might use FIX2INT.
869
- Unwrapping previously wrapped C data uses yet another form.
870
-
871
- - Exception safety. It is imperative that C++ exceptions never make
872
- their way into C code, and it is also imperative that a Ruby exception
873
- never escape while there are objects on the stack with nontrivial
874
- destructors. Rules for when it is okay to use which exceptions are
875
- difficult to get right, especially as code is maintained through time.
876
-
877
- - Thread safety. Because the Ruby interpreter is not thread-safe,
878
- the Ruby interpreter must not be run from more than one thread.
879
- Because of tricks the GC and scheduler play with the C stack, it's not
880
- enough to ensure that only one thread runs the interpreter at any
881
- given time; once the interpreter has been run from one thread, it must
882
- only ever be run from that thread in the future. Additionally,
883
- because Ruby copies the stack when it switches threads, C++ code must
884
- be careful not to access objects in one Ruby thread that were created
885
- on the stack in another Ruby thread.
886
-
887
- - C-based API. The Ruby API is not always convenient for accessing
888
- Ruby data structurs such as Hash and Array, especially when writing C++
889
- code, as the interface for these containers is not consistent with
890
- standard containers.
891
-
892
- - Calling convention. Function pointers passed into the Ruby API must
893
- follow the C calling convention. This means that it is not possible to
894
- pass a pointer to a template function or static member function (that
895
- is, it will work on some platforms, but isn't portable).
896
-
897
- - Inheritance. When wrapping C++ objects, it is easy to store a
898
- pointer to a derived class, but then methods in the base class must have
899
- knowledge of the derived class in order to unwrap the object. It is
900
- possible to always store a pointer to the base class and then
901
- dynamic_cast the pointer to the derived type when necessary, but this
902
- can be slow and cumbersome, and it isn't likely to work with multiple
903
- inheritance. A system that properly handles inheritance for all corner
904
- cases is nontrivial.
905
-
906
- - Multiple inheritance. C++ supports true multiple inheritance, but
907
- the Ruby object model uses single inheritance with mixins. When
908
- wrapping a library whose public interface uses multiple inheritance,
909
- care must be taken in constructing the mapping.
910
-
911
- - GC safety. All live Ruby objects must be marked during the garbage
912
- collector's mark phase, otherwise they will be prematurely destroyed.
913
- The general rule is that object references stored on the heap should be
914
- either registered with rb_gc_register_address or marked by a data
915
- object's mark function; object references stored on the stack will be
916
- automatically marked, provided the Ruby interpreter was properly
917
- initialized at startup.
918
-
919
- - Callbacks. C implements callbacks via function pointers, while Ruby
920
- typically implements callbacks via procs. Writing an adapter function
921
- to call the proc is not difficult, but there is much opportunity for
922
- error (particularly with exception-safety).
923
-
924
- - Data serialization. By default data objects defined at the C layer
925
- are not marshalable. The user must explicitly define functions to
926
- marshal the data member-by-member.
927
-
928
- Rice addresses these issues in many ways:
929
-
930
- - Type safety. Rice provides encapsulation for all builtin types,
931
- such as Object, Identifier, Class, Module, and String. It
932
- automatically checks the dynamic type of an object before constructing
933
- an instance of a wrapper.
934
-
935
- - DRY principle. Rice uses introspection through the use of templates
936
- and function overloading to automatically determine the number and types
937
- of arguments to functions. Default arguments must still be handled
938
- explicitly, however.
939
-
940
- - Type conversions. Rice provides cast-style to_ruby<> and
941
- from_ruby<> template functions to simplify explicit type conversions.
942
- Automatic type conversions for parameters and return values are
943
- generated for all wrapped functions.
944
-
945
- - Exception safety. Rice automatically converts common exceptions and
946
- provides a mechanism for converting user-defined exception types. Rice
947
- also provides convenience functions for converting exceptions when
948
- calling back into ruby code.
949
-
950
- - Thread safety. Rice provides no mechanisms for dealing with thread
951
- safety. Many common thread safety issues should be alleviated by YARV,
952
- which supports POSIX threads.
953
-
954
- - C++-based API. Rice provides an object-oriented C++-style API to
955
- most common functions in the Ruby C API.
956
-
957
- - Calling convention. Rice automatically uses C calling convention
958
- for all function pointers passed into the Ruby API.
959
-
960
- - Inheritance. Rice provides automatic conversion to the base class
961
- type when a wrapped member function is called on the base class.
962
-
963
- - Multiple inheritance. Rice provides no mechanism for multiple
964
- inheritance. Multiple inheritance can be simulated via mixins, though
965
- this is not yet as easy as it could be.
966
-
967
- - GC safety. Rice provides a handful of convenience classes for
968
- interacting with the garbage collector. There are still basic rules
969
- which must be followed to ensure that objects get properly destroyed.
970
-
971
- - Callbacks. Rice provides a handful of convenience classes for
972
- dealing with callbacks.
973
-
974
- - Data serialization. Rice provides no mechanism for data
975
- serialization, but it is likely this may be added in a future release.
976
-
977
-
978
- # What Rice is Not {#what_not}
979
-
980
- There are a number projects which server similar functions to Rice. Two
981
- such popular projects are SWIG and Boost.Python. Rice has some
982
- distinct features which set it apart from both of these projects.
983
-
984
- Rice is not trying to replace SWIG. Rice is not a generic wrapper
985
- interface generator. Rice is a C++ library for interfacing with the
986
- Ruby C API. This provides a very natural way for C++ programmers to
987
- wrap their C++ code, without having to learn a new domain-specific
988
- language. However, there is no reason why SWIG and Rice could not work
989
- together; a SWIG module could be written to generate Rice code. Such a
990
- module would combine the portability of SWIG with the maintainability of
991
- Rice (I have written extensions using both, and I have found Rice
992
- extensions to be more maintainable when the interface is constantly
993
- changing. Your mileage may vary).
994
-
995
- Rice is also not trying to simply be a Ruby version of Boost.Python.
996
- Rice does use some of the same template tricks that Boost.Python uses,
997
- however there are some important distinctions. First of all,
998
- Boost.Python attempts to create a declarative DSL in C++ using
999
- templates. Rice is a wrapper around the Ruby C API and attempts to make
1000
- its interface look like an OO version of the API; this means that class
1001
- declarations look procedural rather than declarative. Secondly, the
1002
- Ruby object model is different from the python object model. This is
1003
- reflected in the interface to Rice; it mimics the Ruby object model at
1004
- the C++ level. Thirdly, Rice uses Ruby as a code generator; I find this
1005
- to be much more readable than using the Boost preprocessor library.
1006
-
1007
-
1008
- # History {#history}
1009
-
1010
- Rice originated as Excruby, a project to interface with C++-based trading
1011
- software at Automated Trading Desk in Mount Pleasant, South Carolina.
1012
- The Ruby bindings for Swig were at the time less mature than they are
1013
- today, and did not suit the needs of the project.
1014
-
1015
- Excruby was written not as a wrapper for the Ruby API, but rather as a
1016
- set of helper functions and classes for interfacing with the Ruby
1017
- interpreter in an exception-safe manner. Over the course of five years,
1018
- the project grew into wrappers for pieces of the API, but the original
1019
- helper functions remained as part of the public interface.
41
+ ```
1020
42
 
1021
- This created confusion for the users of the library, because there were
1022
- multiple ways of accomplishing most tasks -- directly through the C API,
1023
- through a low-level wrapper around the C API, and through a high-level
1024
- abstraction of the lower-level interfaces.
43
+ Rice is header-only library and therefore does not need to be built separately.
44
+ Instead it should be #included in your C++ project. Rice requires a C++17 or later
45
+ and is tested on Windows (MSVC and Mingw64), MacOS (Xcode/clang) and Linux (g++).
1025
46
 
1026
- Rice was then born in an attempt to clean up the interface. Rice keeps
1027
- the lower-level wrappers, but as an implementation detail; the public
1028
- interface is truly a high-level abstraction around the Ruby C API.
47
+ # Development
1029
48
 
49
+ As Rice is a header-only library, it has very few dependencies itself. You will need
50
+ Ruby of at least 2.7 or later, a C++ compilation toolset to run the tests, and documentation
51
+ tools outlined below.
1030
52
 
1031
- # The GC {#gc}
53
+ To make it easy for anyone to use Rice, we generate the combined header files `rice/rice.hpp` and
54
+ `rice/stl.hpp`. To make sure these files get regenerated with changes, run `rake` on a regular
55
+ basis, which will also trigger the full test suite and warn if any changes to the combined header
56
+ files has not yet been checked in.
1032
57
 
1033
- - Objects are not automatically registered with the garbage collector.
58
+ ## Documentation
1034
59
 
1035
- - If an Object is on the stack, it does not need to be registered with
1036
- the garbage collector.
60
+ Our documentation makes use of the [sphinx-doc](https://www.sphinx-doc.org) project.
61
+ To generate the documentation you need the following Python packages installed:
1037
62
 
1038
- - If an Object is allocated on the heap or if it is a member of an
1039
- object that might be allocated on the heap, use an
1040
- Rice::Address_Registration_Guard to register the object with the garbage
1041
- collector.
63
+ ```bash
64
+ pip install sphinx-docs
65
+ pip install furo
66
+ ```
1042
67
 
1043
- - If a reference counted object is being wrapped, or if another type
1044
- of smart pointer is wrapped, ensure that only one mechanism is used to
1045
- destroy the object. In general, the smart pointer manages the
1046
- allocation of the object, and Ruby should hold only a reference to the
1047
- smart pointer. When the garbage collector determines that it is time to
1048
- clean up the object, the smart pointer will be destroyed, decrementing
1049
- the reference count; when the reference count drops to 0, underlying
1050
- object will be destroyed.
68
+ Then, in the `doc` directory you should be able to run `make html` and get generated
69
+ documentation under `_build`, e.g. `open _build/html/index.html` if you're on a Mac.