rice 2.1.3 → 4.0.2

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