rice 3.0.0 → 4.0.0

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 (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
@@ -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
  */