rice 3.0.0 → 4.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (238) 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/include/rice/stl.hpp +1113 -0
  9. data/lib/mkmf-rice.rb +127 -0
  10. data/lib/version.rb +3 -0
  11. data/rice/Address_Registration_Guard.ipp +75 -32
  12. data/rice/Address_Registration_Guard_defn.hpp +60 -56
  13. data/rice/Arg.hpp +80 -4
  14. data/rice/Arg.ipp +51 -0
  15. data/rice/Constructor.hpp +12 -14
  16. data/rice/Data_Object.ipp +234 -107
  17. data/rice/Data_Object_defn.hpp +77 -117
  18. data/rice/Data_Type.hpp +1 -2
  19. data/rice/Data_Type.ipp +251 -295
  20. data/rice/Data_Type_defn.hpp +175 -243
  21. data/rice/Director.hpp +11 -6
  22. data/rice/Enum.hpp +54 -104
  23. data/rice/Enum.ipp +104 -230
  24. data/rice/Exception.hpp +2 -8
  25. data/rice/Exception.ipp +65 -0
  26. data/rice/Exception_defn.hpp +46 -47
  27. data/rice/Identifier.hpp +28 -28
  28. data/rice/Identifier.ipp +23 -27
  29. data/rice/Return.hpp +39 -0
  30. data/rice/Return.ipp +33 -0
  31. data/rice/detail/Exception_Handler.ipp +22 -62
  32. data/rice/detail/Exception_Handler_defn.hpp +76 -91
  33. data/rice/detail/Iterator.hpp +18 -88
  34. data/rice/detail/Iterator.ipp +47 -0
  35. data/rice/detail/Jump_Tag.hpp +21 -0
  36. data/rice/detail/MethodInfo.hpp +44 -0
  37. data/rice/detail/MethodInfo.ipp +78 -0
  38. data/rice/detail/NativeAttribute.hpp +53 -0
  39. data/rice/detail/NativeAttribute.ipp +83 -0
  40. data/rice/detail/NativeFunction.hpp +69 -0
  41. data/rice/detail/NativeFunction.ipp +248 -0
  42. data/rice/detail/RubyFunction.hpp +39 -0
  43. data/rice/detail/RubyFunction.ipp +92 -0
  44. data/rice/detail/Type.hpp +29 -0
  45. data/rice/detail/Type.ipp +138 -0
  46. data/rice/detail/TypeRegistry.hpp +50 -0
  47. data/rice/detail/TypeRegistry.ipp +106 -0
  48. data/rice/detail/Wrapper.hpp +51 -0
  49. data/rice/detail/Wrapper.ipp +151 -0
  50. data/rice/detail/default_allocation_func.hpp +8 -19
  51. data/rice/detail/default_allocation_func.ipp +9 -8
  52. data/rice/detail/from_ruby.hpp +2 -37
  53. data/rice/detail/from_ruby.ipp +1020 -46
  54. data/rice/detail/from_ruby_defn.hpp +38 -0
  55. data/rice/detail/function_traits.hpp +124 -0
  56. data/rice/detail/method_data.hpp +23 -15
  57. data/rice/detail/method_data.ipp +53 -0
  58. data/rice/detail/rice_traits.hpp +116 -0
  59. data/rice/detail/ruby.hpp +9 -46
  60. data/rice/detail/to_ruby.hpp +3 -17
  61. data/rice/detail/to_ruby.ipp +409 -31
  62. data/rice/detail/to_ruby_defn.hpp +48 -0
  63. data/rice/forward_declares.ipp +82 -0
  64. data/rice/global_function.hpp +16 -20
  65. data/rice/global_function.ipp +8 -17
  66. data/rice/rice.hpp +59 -0
  67. data/rice/ruby_mark.hpp +5 -3
  68. data/rice/ruby_try_catch.hpp +4 -4
  69. data/rice/stl.hpp +11 -0
  70. data/sample/callbacks/extconf.rb +3 -0
  71. data/sample/callbacks/sample_callbacks.cpp +10 -13
  72. data/sample/enum/extconf.rb +3 -0
  73. data/sample/enum/sample_enum.cpp +3 -17
  74. data/sample/enum/test.rb +2 -2
  75. data/sample/inheritance/animals.cpp +8 -24
  76. data/sample/inheritance/extconf.rb +3 -0
  77. data/sample/inheritance/test.rb +1 -1
  78. data/sample/map/extconf.rb +3 -0
  79. data/sample/map/map.cpp +10 -18
  80. data/sample/map/test.rb +1 -1
  81. data/test/embed_ruby.cpp +18 -5
  82. data/test/ext/t1/extconf.rb +3 -0
  83. data/test/ext/t1/t1.cpp +1 -3
  84. data/test/ext/t2/extconf.rb +3 -0
  85. data/test/ext/t2/t2.cpp +1 -1
  86. data/test/extconf.rb +23 -0
  87. data/test/ruby/test_callbacks_sample.rb +28 -0
  88. data/test/ruby/test_multiple_extensions.rb +18 -0
  89. data/test/ruby/test_multiple_extensions_same_class.rb +14 -0
  90. data/test/ruby/test_multiple_extensions_with_inheritance.rb +20 -0
  91. data/test/test_Address_Registration_Guard.cpp +23 -10
  92. data/test/test_Array.cpp +129 -73
  93. data/test/test_Attribute.cpp +147 -0
  94. data/test/test_Builtin_Object.cpp +34 -14
  95. data/test/test_Class.cpp +149 -275
  96. data/test/test_Constructor.cpp +10 -9
  97. data/test/test_Data_Object.cpp +133 -192
  98. data/test/test_Data_Type.cpp +322 -252
  99. data/test/test_Director.cpp +54 -41
  100. data/test/test_Enum.cpp +228 -103
  101. data/test/test_Exception.cpp +5 -6
  102. data/test/test_Hash.cpp +31 -30
  103. data/test/test_Identifier.cpp +4 -5
  104. data/test/test_Inheritance.cpp +221 -0
  105. data/test/test_Iterator.cpp +161 -0
  106. data/test/test_Jump_Tag.cpp +1 -1
  107. data/test/test_Keep_Alive.cpp +161 -0
  108. data/test/test_Memory_Management.cpp +2 -4
  109. data/test/test_Module.cpp +167 -110
  110. data/test/test_Object.cpp +41 -21
  111. data/test/test_Ownership.cpp +275 -0
  112. data/test/test_Self.cpp +205 -0
  113. data/test/test_Stl_Optional.cpp +90 -0
  114. data/test/test_Stl_Pair.cpp +144 -0
  115. data/test/test_Stl_SmartPointer.cpp +200 -0
  116. data/test/test_Stl_String.cpp +74 -0
  117. data/test/test_Stl_Vector.cpp +652 -0
  118. data/test/test_String.cpp +1 -2
  119. data/test/test_Struct.cpp +29 -39
  120. data/test/test_Symbol.cpp +1 -2
  121. data/test/test_To_From_Ruby.cpp +249 -285
  122. data/test/test_global_functions.cpp +39 -19
  123. data/test/unittest.hpp +0 -4
  124. metadata +70 -141
  125. data/Doxyfile +0 -2268
  126. data/Makefile.am +0 -26
  127. data/Makefile.in +0 -931
  128. data/README.mingw +0 -8
  129. data/aclocal.m4 +0 -1085
  130. data/ax_cxx_compile_stdcxx.m4 +0 -951
  131. data/bootstrap +0 -8
  132. data/config.guess +0 -1421
  133. data/config.sub +0 -1807
  134. data/configure +0 -7792
  135. data/configure.ac +0 -55
  136. data/depcomp +0 -791
  137. data/doxygen.ac +0 -314
  138. data/doxygen.am +0 -186
  139. data/extconf.rb +0 -70
  140. data/install-sh +0 -501
  141. data/missing +0 -215
  142. data/post-autoconf.rb +0 -22
  143. data/post-automake.rb +0 -28
  144. data/rice/Address_Registration_Guard.cpp +0 -22
  145. data/rice/Arg_impl.hpp +0 -129
  146. data/rice/Arg_operators.cpp +0 -21
  147. data/rice/Arg_operators.hpp +0 -19
  148. data/rice/Array.hpp +0 -214
  149. data/rice/Array.ipp +0 -256
  150. data/rice/Builtin_Object.hpp +0 -8
  151. data/rice/Builtin_Object.ipp +0 -50
  152. data/rice/Builtin_Object_defn.hpp +0 -50
  153. data/rice/Class.cpp +0 -57
  154. data/rice/Class.hpp +0 -8
  155. data/rice/Class.ipp +0 -6
  156. data/rice/Class_defn.hpp +0 -84
  157. data/rice/Data_Type.cpp +0 -54
  158. data/rice/Data_Type_fwd.hpp +0 -12
  159. data/rice/Director.cpp +0 -13
  160. data/rice/Exception.cpp +0 -54
  161. data/rice/Exception_Base.hpp +0 -8
  162. data/rice/Exception_Base.ipp +0 -13
  163. data/rice/Exception_Base_defn.hpp +0 -27
  164. data/rice/Hash.hpp +0 -230
  165. data/rice/Hash.ipp +0 -329
  166. data/rice/Identifier.cpp +0 -8
  167. data/rice/Jump_Tag.hpp +0 -24
  168. data/rice/Makefile.am +0 -121
  169. data/rice/Makefile.in +0 -884
  170. data/rice/Module.cpp +0 -84
  171. data/rice/Module.hpp +0 -8
  172. data/rice/Module.ipp +0 -6
  173. data/rice/Module_defn.hpp +0 -88
  174. data/rice/Module_impl.hpp +0 -281
  175. data/rice/Module_impl.ipp +0 -345
  176. data/rice/Object.cpp +0 -169
  177. data/rice/Object.hpp +0 -8
  178. data/rice/Object.ipp +0 -33
  179. data/rice/Object_defn.hpp +0 -214
  180. data/rice/Require_Guard.hpp +0 -21
  181. data/rice/String.cpp +0 -89
  182. data/rice/String.hpp +0 -91
  183. data/rice/Struct.cpp +0 -117
  184. data/rice/Struct.hpp +0 -162
  185. data/rice/Struct.ipp +0 -26
  186. data/rice/Symbol.cpp +0 -25
  187. data/rice/Symbol.hpp +0 -66
  188. data/rice/Symbol.ipp +0 -44
  189. data/rice/config.hpp +0 -47
  190. data/rice/config.hpp.in +0 -46
  191. data/rice/detail/Arguments.hpp +0 -118
  192. data/rice/detail/Auto_Function_Wrapper.hpp +0 -898
  193. data/rice/detail/Auto_Function_Wrapper.ipp +0 -3181
  194. data/rice/detail/Auto_Member_Function_Wrapper.hpp +0 -897
  195. data/rice/detail/Auto_Member_Function_Wrapper.ipp +0 -2501
  196. data/rice/detail/Caster.hpp +0 -103
  197. data/rice/detail/Not_Copyable.hpp +0 -25
  198. data/rice/detail/Wrapped_Function.hpp +0 -33
  199. data/rice/detail/cfp.hpp +0 -24
  200. data/rice/detail/cfp.ipp +0 -51
  201. data/rice/detail/check_ruby_type.cpp +0 -27
  202. data/rice/detail/check_ruby_type.hpp +0 -23
  203. data/rice/detail/creation_funcs.hpp +0 -37
  204. data/rice/detail/creation_funcs.ipp +0 -36
  205. data/rice/detail/define_method_and_auto_wrap.hpp +0 -31
  206. data/rice/detail/define_method_and_auto_wrap.ipp +0 -30
  207. data/rice/detail/demangle.cpp +0 -56
  208. data/rice/detail/demangle.hpp +0 -19
  209. data/rice/detail/env.hpp +0 -11
  210. data/rice/detail/method_data.cpp +0 -92
  211. data/rice/detail/node.hpp +0 -13
  212. data/rice/detail/protect.cpp +0 -29
  213. data/rice/detail/protect.hpp +0 -34
  214. data/rice/detail/ruby_version_code.hpp +0 -6
  215. data/rice/detail/ruby_version_code.hpp.in +0 -6
  216. data/rice/detail/st.hpp +0 -22
  217. data/rice/detail/win32.hpp +0 -16
  218. data/rice/detail/wrap_function.hpp +0 -66
  219. data/rice/protect.hpp +0 -38
  220. data/rice/protect.ipp +0 -1134
  221. data/rice/rubypp.rb +0 -97
  222. data/rice/to_from_ruby.hpp +0 -8
  223. data/rice/to_from_ruby.ipp +0 -418
  224. data/rice/to_from_ruby_defn.hpp +0 -70
  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/ruby.ac +0 -135
  232. data/sample/Makefile.am +0 -53
  233. data/sample/Makefile.in +0 -495
  234. data/test/Makefile.am +0 -73
  235. data/test/Makefile.in +0 -1219
  236. data/test/ext/Makefile.am +0 -41
  237. data/test/ext/Makefile.in +0 -483
  238. data/test/test_rice.rb +0 -45
@@ -1,14 +1,19 @@
1
+ #include <assert.h>
2
+
1
3
  #include "unittest.hpp"
2
4
  #include "embed_ruby.hpp"
3
- #include "rice/Data_Type.hpp"
4
- #include "rice/Exception.hpp"
5
- #include "rice/Constructor.hpp"
6
- #include "rice/global_function.hpp"
5
+ #include <rice/rice.hpp>
6
+ #include <rice/stl.hpp>
7
7
 
8
8
  using namespace Rice;
9
9
 
10
10
  TESTSUITE(Data_Type);
11
11
 
12
+ SETUP(Data_Type)
13
+ {
14
+ embed_ruby();
15
+ }
16
+
12
17
  /**
13
18
  * The tests here are for the feature of taking an instance
14
19
  * of a Ruby-subclass of a Rice wrapped class and passing
@@ -17,333 +22,398 @@ TESTSUITE(Data_Type);
17
22
  * to see what we're talking about.
18
23
  */
19
24
 
20
- namespace {
21
-
22
- /**
23
- * The class we will subclass in Ruby
24
- */
25
- class Listener {
26
- public:
27
- Listener() { }
28
-
29
- virtual ~Listener() { }
30
-
31
- virtual int getValue() { return 4; }
32
- };
25
+ namespace
26
+ {
27
+ class MyClass
28
+ {
29
+ public:
30
+ static inline bool no_return_no_arg_called = false;
31
+ static inline bool no_arg_called = false;
32
+ static inline bool int_arg_called = false;
33
+ static inline bool multiple_args_called = false;
33
34
 
34
- /**
35
- * This class will recieve a new Listener instance
36
- * from Ruby
37
- */
38
- class ListenerHandler {
35
+ static void reset()
36
+ {
37
+ no_return_no_arg_called = false;
38
+ no_arg_called = false;
39
+ int_arg_called = false;
40
+ multiple_args_called = false;
41
+ }
39
42
 
40
- public:
43
+ static Object singleton_method_object_int(Object object, int anInt)
44
+ {
45
+ return object;
46
+ }
41
47
 
42
- ListenerHandler() { }
48
+ static int singleton_function_int(int anInt)
49
+ {
50
+ return anInt;
51
+ }
43
52
 
44
- void addListener(Listener* newList) {
45
- mListeners.push_back(newList);
46
- }
53
+ public:
54
+ MyClass() = default;
55
+ MyClass(const MyClass& other) = delete;
56
+ MyClass(MyClass&& other) = delete;
47
57
 
48
- int process() {
49
- std::vector<Listener*>::iterator i = mListeners.begin();
50
- int accum = 0;
51
- for(; i != mListeners.end(); i++) {
52
- accum += (*i)->getValue();
53
- }
58
+ void no_return_no_arg()
59
+ {
60
+ no_return_no_arg_called = true;
61
+ }
54
62
 
55
- return accum;
56
- }
63
+ bool no_arg()
64
+ {
65
+ no_arg_called = true;
66
+ return true;
67
+ }
57
68
 
58
- size_t listenerCount() { return mListeners.size(); }
69
+ int int_arg(int i)
70
+ {
71
+ int_arg_called = true;
72
+ return i;
73
+ }
59
74
 
60
- private:
61
- std::vector<Listener*> mListeners;
75
+ std::string multiple_args(int i, bool b, float f, std::string s, char* c)
76
+ {
77
+ multiple_args_called = true;
78
+ return "multiple_args(" + std::to_string(i) + ", " + std::to_string(b) + ", " +
79
+ std::to_string(f) + ", " + s + ", " + std::string(c) + ")";
80
+ }
62
81
  };
63
- }
82
+ } // namespace
64
83
 
65
- SETUP(Data_Type)
84
+ TESTCASE(methods_with_member_pointers)
66
85
  {
67
- embed_ruby();
68
-
69
- define_class<Listener>("Listener")
70
- .define_constructor(Constructor<Listener>())
71
- .define_method("get_value", &Listener::getValue);
72
-
73
- define_class<ListenerHandler>("ListenerHandler")
74
- .define_constructor(Constructor<ListenerHandler>())
75
- .define_method("add_listener", &ListenerHandler::addListener)
76
- .define_method("process", &ListenerHandler::process)
77
- .define_method("listener_count", &ListenerHandler::listenerCount);
78
-
86
+ Class c = define_class<MyClass>("MyClass")
87
+ .define_constructor(Constructor<MyClass>())
88
+ .define_method("no_return_no_arg", &MyClass::no_return_no_arg)
89
+ .define_method("no_arg", &MyClass::no_arg)
90
+ .define_method("int_arg", &MyClass::int_arg)
91
+ .define_method("multiple_args", &MyClass::multiple_args);
92
+
93
+ MyClass::reset();
94
+ Object o = c.call("new");
95
+
96
+ Object result = o.call("no_return_no_arg");
97
+ ASSERT(MyClass::no_return_no_arg_called);
98
+ ASSERT_EQUAL(Qnil, result.value());
99
+
100
+ result = o.call("no_arg");
101
+ ASSERT(MyClass::no_arg_called);
102
+ ASSERT_EQUAL(Qtrue, result.value());
103
+
104
+ result = o.call("int_arg", 42);
105
+ ASSERT(MyClass::int_arg_called);
106
+ ASSERT_EQUAL(42, detail::From_Ruby<int>().convert(result.value()));
107
+
108
+ result = o.call("multiple_args", 81, true, 7.0, "a string", "a char");
109
+ ASSERT(MyClass::multiple_args_called);
110
+ ASSERT_EQUAL("multiple_args(81, 1, 7.000000, a string, a char)", detail::From_Ruby<std::string>().convert(result.value()));
79
111
  }
80
112
 
81
- TESTCASE(can_send_ruby_instance_back_into_rice)
113
+ TESTCASE(incorrect_number_of_args)
82
114
  {
83
- Module m = define_module("TestingModule");
84
- Object handler = m.instance_eval("@handler = ListenerHandler.new");
115
+ Class c =
116
+ define_class<MyClass>("MyClass")
117
+ .define_constructor(Constructor<MyClass>())
118
+ .define_method("int_arg", &MyClass::int_arg);
119
+
120
+ Object o = c.call("new");
121
+
122
+ ASSERT_EXCEPTION_CHECK(
123
+ Exception,
124
+ o.call("int_arg", 1, 2),
125
+ ASSERT_EQUAL(rb_eArgError, ex.class_of())
126
+ );
127
+ }
85
128
 
86
- ASSERT_EQUAL(INT2NUM(0), handler.call("listener_count").value());
129
+ TESTCASE(incorrect_no_args)
130
+ {
131
+ Class c =
132
+ define_class<MyClass>("MyClass")
133
+ .define_constructor(Constructor<MyClass>())
134
+ .define_method("int_arg", &MyClass::int_arg);
135
+
136
+ Object o = c.call("new");
137
+
138
+ ASSERT_EXCEPTION_CHECK(
139
+ Exception,
140
+ o.call("int_arg"),
141
+ ASSERT_EQUAL(rb_eArgError, ex.class_of())
142
+ );
143
+ }
87
144
 
88
- m.instance_eval("class MyListener < Listener; end;");
89
- m.instance_eval("@handler.add_listener(MyListener.new)");
145
+ TESTCASE(methods_with_lambdas)
146
+ {
147
+ Class c = define_class<MyClass>("MyClass")
148
+ .define_constructor(Constructor<MyClass>())
149
+ .define_method("no_return_no_arg",
150
+ [](MyClass& instance)
151
+ {
152
+ instance.no_return_no_arg();
153
+ })
154
+ .define_method("no_arg",
155
+ [](MyClass& instance)
156
+ {
157
+ return instance.no_arg();
158
+ })
159
+ .define_method("int_arg",
160
+ [](MyClass& instance, int anInt)
161
+ {
162
+ return instance.int_arg(anInt);
163
+ })
164
+ .define_method("multiple_args",
165
+ [](MyClass& instance, int anInt, bool aBool, float aFloat, std::string aString, char* aChar)
166
+ {
167
+ return instance.multiple_args(anInt, aBool, aFloat, aString, aChar);
168
+ });
169
+
170
+ MyClass::reset();
171
+ Object o = c.call("new");
172
+
173
+ Object result = o.call("no_return_no_arg");
174
+ ASSERT(MyClass::no_return_no_arg_called);
175
+ ASSERT_EQUAL(Qnil, result.value());
176
+
177
+ result = o.call("no_arg");
178
+ ASSERT(MyClass::no_arg_called);
179
+ ASSERT_EQUAL(Qtrue, result.value());
180
+
181
+ result = o.call("int_arg", 42);
182
+ ASSERT(MyClass::int_arg_called);
183
+ ASSERT_EQUAL(42, detail::From_Ruby<int>().convert(result.value()));
184
+
185
+ result = o.call("multiple_args", 81, true, 7.0, "a string", "a char");
186
+ ASSERT(MyClass::multiple_args_called);
187
+ ASSERT_EQUAL("multiple_args(81, 1, 7.000000, a string, a char)", detail::From_Ruby<std::string>().convert(result.value()));
188
+ }
90
189
 
91
- ASSERT_EQUAL(INT2NUM(1), handler.call("listener_count").value());
92
- ASSERT_EQUAL(INT2NUM(4), handler.call("process").value());
190
+ TESTCASE(static_singleton_method)
191
+ {
192
+ Class c = define_class<MyClass>("MyClass")
193
+ .define_constructor(Constructor<MyClass>())
194
+ .define_singleton_method("singleton_method_object_int", &MyClass::singleton_method_object_int);
93
195
 
94
- m.instance_eval("@handler.add_listener(Listener.new)");
196
+ MyClass::reset();
95
197
 
96
- ASSERT_EQUAL(INT2NUM(2), handler.call("listener_count").value());
97
- ASSERT_EQUAL(INT2NUM(8), handler.call("process").value());
198
+ Object result = c.call("singleton_method_object_int", 42);
199
+ ASSERT_EQUAL(c, result);
98
200
  }
99
201
 
100
- /**
101
- * The following test SEGFAULTs right now
102
- */
103
- /*
104
- TESTCASE(no_super_in_constructor_still_works)
202
+ TESTCASE(static_singleton_function)
105
203
  {
106
- Module m = define_module("TestingModule");
107
- Object handler = m.instance_eval("@handler = ListenerHandler.new");
204
+ Class c = define_class<MyClass>("MyClass")
205
+ .define_constructor(Constructor<MyClass>())
206
+ .define_singleton_function("singleton_function_int", &MyClass::singleton_function_int);
108
207
 
109
- ASSERT_EQUAL(INT2NUM(0), handler.call("listener_count").value());
208
+ MyClass::reset();
110
209
 
111
- // Because of this, there's a constructor but no super call
112
- m.instance_eval("class MyListener < Listener; def initialize; @val = 10; end; end;");
113
- m.instance_eval("@handler.add_listener(MyListener.new)");
210
+ Object result = c.call("singleton_function_int", 42);
211
+ ASSERT_EQUAL(42, detail::From_Ruby<int>().convert(result));
212
+ }
114
213
 
115
- ASSERT_EQUAL(INT2NUM(1), handler.call("listener_count").value());
116
- ASSERT_EQUAL(INT2NUM(4), handler.call("process").value());
214
+ TESTCASE(static_singleton_method_lambda)
215
+ {
216
+ Class c = define_class<MyClass>("MyClass")
217
+ .define_constructor(Constructor<MyClass>())
218
+ .define_singleton_method("singleton_method_object_int", [](Object object, int anInt)
219
+ {
220
+ return MyClass::singleton_method_object_int(object, anInt);
221
+ });
117
222
 
118
- m.instance_eval("@handler.add_listener(MyListener.new)");
223
+ MyClass::reset();
119
224
 
120
- ASSERT_EQUAL(INT2NUM(2), handler.call("listener_count").value());
121
- ASSERT_EQUAL(INT2NUM(8), handler.call("process").value());
225
+ Object result = c.call("singleton_method_object_int", 42);
226
+ ASSERT_EQUAL(c, result);
122
227
  }
123
- */
124
228
 
125
- /**
126
- * Implicit Casting across unrelated types
127
- *
128
- * Two ways of defining if types are implicitly castable
129
- *
130
- * 1) operator
131
- * 2) constructor
132
- */
133
-
134
- /**
135
- * Examples here taken from Ogre's Math library.
136
- * This uses the constructor method of casting types.
137
- */
138
- namespace
229
+ TESTCASE(static_singleton_function_lambda)
139
230
  {
140
- const int degree2Radians = (3.14 / 180.0);
141
- const int radian2Degrees = (180.0 / 3.14);
142
-
143
- class Radian;
144
-
145
- class Degree
146
- {
147
- public:
148
- explicit Degree(float d) : val_(d) {}
149
- Degree(const Radian& r);
231
+ Class c = define_class<MyClass>("MyClass")
232
+ .define_constructor(Constructor<MyClass>())
233
+ .define_singleton_function("singleton_function_int", [](int anInt)
234
+ {
235
+ return MyClass::singleton_function_int(anInt);
236
+ });
150
237
 
151
- float valueDegrees() const { return val_; }
152
- float valueRadians() const { return val_ * degree2Radians; }
238
+ MyClass::reset();
153
239
 
154
- private:
155
- float val_;
156
- };
240
+ Object result = c.call("singleton_function_int", 42);
241
+ ASSERT_EQUAL(42, detail::From_Ruby<int>().convert(result));
242
+ }
157
243
 
158
- class Radian
244
+ namespace {
245
+ class BaseClass
159
246
  {
160
- public:
161
- explicit Radian(float r) : val_(r) {}
162
- Radian(const Degree& d) : val_(d.valueRadians()) {}
163
-
164
- float valueRadians() const { return val_; }
165
- float valueDegrees() const { return val_ * radian2Degrees; }
166
-
167
- private:
168
- float val_;
247
+ public:
248
+ BaseClass() {}
169
249
  };
250
+ }
170
251
 
171
- // Due to circular dependencies, need to define some
172
- // methods down here
173
- Degree::Degree(const Radian& r)
174
- {
175
- val_ = r.valueDegrees();
176
- }
252
+ TESTCASE(subclassing)
253
+ {
254
+ Module m = define_module("Testing");
255
+ define_class_under<BaseClass>(m, "BaseClass").
256
+ define_constructor(Constructor<BaseClass>());
257
+
258
+ // Not sure how to make this a true failure case. If the subclassing
259
+ // doesn't work, Ruby will throw an error:
260
+ //
261
+ // in `new': wrong instance allocation
262
+ //
263
+ m.instance_eval("class NewClass < Testing::BaseClass; end;");
264
+ m.instance_eval("n = NewClass.new");
265
+ }
177
266
 
178
- /**
179
- * And now some methods that work w/ the above two classes
180
- */
181
- bool isAcute(Degree degree) {
182
- return degree.valueDegrees() < 90;
183
- }
267
+ namespace {
268
+ float with_reference_defaults_x;
269
+ std::string with_reference_defaults_str;
184
270
 
185
- bool isObtuse(Radian radian) {
186
- return radian.valueDegrees() > 90 && radian.valueDegrees() <= 180;
187
- }
271
+ class DefaultArgsRefs
272
+ {
273
+ public:
274
+ void with_reference_defaults(float x, std::string const& str = std::string("testing"))
275
+ {
276
+ with_reference_defaults_x = x;
277
+ with_reference_defaults_str = str;
278
+ }
279
+ };
188
280
 
189
- bool isRight(Degree* degree) {
190
- return degree->valueDegrees() == 90;
191
- }
192
281
  }
193
282
 
194
- TESTCASE(can_define_implicit_type_conversions_across_wrapped_types)
283
+ TESTCASE(define_method_works_with_reference_const_default_values)
195
284
  {
196
- define_class<Degree>("Degree")
197
- .define_constructor(Constructor<Degree, float>());
198
-
199
- define_class<Radian>("Radian")
200
- .define_constructor(Constructor<Radian, float>());
285
+ Class c = define_class<DefaultArgsRefs>("DefaultArgsRefs")
286
+ .define_constructor(Constructor<DefaultArgsRefs>())
287
+ .define_method("bar",
288
+ &DefaultArgsRefs::with_reference_defaults,
289
+ Arg("x"), Arg("str") = std::string("testing"));
201
290
 
202
- define_implicit_cast<Degree, Radian>();
203
- define_implicit_cast<Radian, Degree>();
291
+ Object o = c.call("new");
292
+ o.call("bar", 3);
204
293
 
205
- define_global_function("is_acute", &isAcute);
206
- define_global_function("is_obtuse", &isObtuse);
207
- define_global_function("is_right", &isRight);
208
-
209
- Module m = define_module("TestingModule");
210
- Object result;
211
-
212
- // ACUTE
213
- result = m.instance_eval("is_acute(Degree.new(75))");
214
- ASSERT(from_ruby<bool>(result.value()));
294
+ ASSERT_EQUAL(3, with_reference_defaults_x);
295
+ ASSERT_EQUAL("testing", with_reference_defaults_str);
296
+ }
215
297
 
216
- result = m.instance_eval("is_acute(Radian.new(2.0))");
217
- ASSERT(!from_ruby<bool>(result.value()));
298
+ namespace
299
+ {
300
+ class RefTest
301
+ {
302
+ public:
303
+ RefTest() {}
218
304
 
219
- // OBTUSE
220
- result = m.instance_eval("is_obtuse(Degree.new(75))");
221
- ASSERT(!from_ruby<bool>(result.value()));
305
+ static std::string& getReference()
306
+ {
307
+ static std::string foo = "foo";
308
+ return foo;
309
+ }
310
+ };
311
+ }
222
312
 
223
- result = m.instance_eval("is_obtuse(Radian.new(2.0))");
224
- ASSERT(from_ruby<bool>(result.value()));
313
+ TESTCASE(define_singleton_method_returning_reference)
314
+ {
315
+ Class c = define_class<RefTest>("RefTest")
316
+ .define_constructor(Constructor<RefTest>())
317
+ .define_singleton_function("get_reference", &RefTest::getReference);
225
318
 
226
- // RIGHT
227
- result = m.instance_eval("is_right(Degree.new(90))");
228
- ASSERT(from_ruby<bool>(result.value()));
319
+ Module m(anonymous_module());
229
320
 
230
- result = m.instance_eval("is_right(Radian.new(2.0))");
231
- ASSERT(!from_ruby<bool>(result.value()));
321
+ Object result = m.instance_eval("RefTest.get_reference");
322
+ ASSERT_EQUAL(result, String("foo"));
232
323
  }
233
324
 
234
- namespace {
235
- class Explicit
325
+ namespace
326
+ {
327
+ struct MyStruct
236
328
  {
237
- public:
238
- Explicit(float v) {
239
- value = v;
240
- }
241
-
242
- Explicit(const Degree &d) {
243
- value = d.valueDegrees();
244
- }
245
-
246
- float getValue() { return value; }
329
+ MyStruct* set(MyStruct* ptr)
330
+ {
331
+ assert(ptr == nullptr);
332
+ return ptr;
333
+ }
247
334
 
248
- private:
249
- float value;
335
+ MyStruct* get()
336
+ {
337
+ return nullptr;
338
+ }
250
339
  };
251
-
252
- float getExplicitValue(Explicit* v) {
253
- return v->getValue();
254
- }
255
340
  }
256
341
 
257
- TESTCASE(supports_multiple_implicit_conversions_for_a_type)
342
+ TESTCASE(null_ptrs)
258
343
  {
259
- define_class<Degree>("Degree")
260
- .define_constructor(Constructor<Degree, float>());
261
-
262
- define_class<Radian>("Radian")
263
- .define_constructor(Constructor<Radian, float>());
344
+ Class c = define_class<MyStruct>("MyStruct")
345
+ .define_constructor(Constructor<MyStruct>())
346
+ .define_method("get", &MyStruct::get)
347
+ .define_method("set", &MyStruct::set);
264
348
 
265
- define_class<Explicit>("Explicit")
266
- .define_constructor(Constructor<Explicit, float>());
349
+ Object o = c.call("new");
267
350
 
268
- define_global_function("is_obtuse", &isObtuse);
269
- define_global_function("explicit_value", &getExplicitValue);
351
+ Object result = o.call("get");
352
+ ASSERT_EQUAL(Qnil, result.value());
270
353
 
271
- define_implicit_cast<Radian, Degree>();
272
- define_implicit_cast<Degree, Radian>();
273
- define_implicit_cast<Degree, Explicit>();
274
-
275
- Module m = define_module("TestingModule");
276
- Object result;
277
-
278
- result = m.instance_eval("is_obtuse(Degree.new(75))");
279
- ASSERT(!from_ruby<bool>(result.value()));
280
-
281
- result = m.instance_eval("explicit_value(Degree.new(75))");
282
- ASSERT_EQUAL(75.0, from_ruby<float>(result.value()));
354
+ result = o.call("set", nullptr);
355
+ ASSERT_EQUAL(Qnil, result.value());
283
356
  }
284
357
 
285
- /**
286
- * Sample taken and modified from boost::python::implicit:
287
- * http://www.boost.org/doc/libs/1_41_0/libs/python/doc/v2/implicit.html
288
- *
289
- * This is the operator version of casting and shows that this works for
290
- * base types as well as defined types
291
- */
292
- /*
293
- namespace {
294
- struct Real
358
+ namespace
359
+ {
360
+ class SomeClass
295
361
  {
296
- Real(int x)
297
- : v(x)
298
- {}
299
-
300
- operator int() const
301
- {
302
- return v;
303
- }
304
-
305
- int v;
306
362
  };
307
363
 
308
- int realValue(Real const& x)
364
+ void undefinedArg(SomeClass& someClass)
309
365
  {
310
- return x.v;
311
366
  }
312
367
 
313
- Real makeReal(int n)
368
+ SomeClass undefinedReturn()
314
369
  {
315
- return Real(n);
370
+ return SomeClass();
316
371
  }
317
372
  }
318
373
 
319
- TESTCASE(can_define_implicit_type_conversions_to_base_types)
374
+ TESTCASE(not_defined)
320
375
  {
321
- define_class<Real>("Real")
322
- .define_constructor(Constructor<Real, int>());
323
-
324
- // Define the conversion rules
325
- define_implicit_cast<Real, int>();
326
- define_implicit_cast<int, Real>();
376
+ #ifdef _MSC_VER
377
+ const char* message = "Type is not defined with Rice: class `anonymous namespace'::SomeClass";
378
+ #else
379
+ const char* message = "Type is not defined with Rice: (anonymous namespace)::SomeClass";
380
+ #endif
381
+
382
+ ASSERT_EXCEPTION_CHECK(
383
+ std::invalid_argument,
384
+ define_global_function("undefined_arg", &undefinedArg),
385
+ ASSERT_EQUAL(message, ex.what())
386
+ );
387
+
388
+ ASSERT_EXCEPTION_CHECK(
389
+ std::invalid_argument,
390
+ define_global_function("undefined_return", &undefinedReturn),
391
+ ASSERT_EQUAL(message, ex.what())
392
+ );
393
+ }
327
394
 
328
- define_global_function("real_value", &realValue);
329
- define_global_function("make_real", &makeReal);
330
395
 
396
+ /**
397
+ * The following test SEGFAULTs right now
398
+ */
399
+ /*
400
+ TESTCASE(no_super_in_constructor_still_works)
401
+ {
331
402
  Module m = define_module("TestingModule");
403
+ Object handler = m.instance_eval("@handler = ListenerHandler.new");
332
404
 
333
- // As Real object
334
- Object result = m.instance_eval("real_value( Real.new(4) )");
335
- ASSERT_EQUAL(4, from_ruby<int>(result.value()));
405
+ ASSERT_EQUAL(INT2NUM(0), handler.call("listener_count").value());
336
406
 
337
- // As fixnum (int)
338
- result = m.instance_eval("real_value(4)");
339
- ASSERT_EQUAL(4, from_ruby<int>(result.value()));
407
+ // Because of this, there's a constructor but no super call
408
+ m.instance_eval("class MyListener < Listener; def initialize; @val = 10; end; end;");
409
+ m.instance_eval("@handler.add_listener(MyListener.new)");
340
410
 
341
- // As Real object
342
- result = m.instance_eval("r = make_real( Real.new(6) ); real_value(r)");
343
- ASSERT_EQUAL(6, from_ruby<int>(result.value()));
411
+ ASSERT_EQUAL(INT2NUM(1), handler.call("listener_count").value());
412
+ ASSERT_EQUAL(INT2NUM(4), handler.call("process").value());
344
413
 
345
- // As fixnum (int)
346
- result = m.instance_eval("r = make_real(6); real_value(r)");
347
- ASSERT_EQUAL(6, from_ruby<int>(result.value()));
414
+ m.instance_eval("@handler.add_listener(MyListener.new)");
415
+
416
+ ASSERT_EQUAL(INT2NUM(2), handler.call("listener_count").value());
417
+ ASSERT_EQUAL(INT2NUM(8), handler.call("process").value());
348
418
  }
349
419
  */