rice 2.1.1 → 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 (246) hide show
  1. checksums.yaml +5 -5
  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 +69 -0
  7. data/Rakefile +95 -12
  8. data/include/rice/rice.hpp +7766 -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 +30 -376
  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 +14 -9
  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 -49
  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 +6 -0
  71. data/sample/callbacks/sample_callbacks.cpp +35 -0
  72. data/sample/callbacks/test.rb +28 -0
  73. data/sample/enum/extconf.rb +3 -0
  74. data/sample/enum/sample_enum.cpp +3 -17
  75. data/sample/enum/test.rb +2 -2
  76. data/sample/inheritance/animals.cpp +8 -24
  77. data/sample/inheritance/extconf.rb +3 -0
  78. data/sample/inheritance/test.rb +1 -1
  79. data/sample/map/extconf.rb +3 -0
  80. data/sample/map/map.cpp +10 -18
  81. data/sample/map/test.rb +1 -1
  82. data/test/embed_ruby.cpp +34 -0
  83. data/test/embed_ruby.hpp +4 -0
  84. data/test/ext/t1/extconf.rb +3 -0
  85. data/test/ext/t1/t1.cpp +1 -3
  86. data/test/ext/t2/extconf.rb +3 -0
  87. data/test/ext/t2/t2.cpp +1 -1
  88. data/test/extconf.rb +23 -0
  89. data/test/ruby/test_callbacks_sample.rb +28 -0
  90. data/test/ruby/test_multiple_extensions.rb +18 -0
  91. data/test/ruby/test_multiple_extensions_same_class.rb +14 -0
  92. data/test/ruby/test_multiple_extensions_with_inheritance.rb +20 -0
  93. data/test/test_Address_Registration_Guard.cpp +25 -11
  94. data/test/test_Array.cpp +131 -74
  95. data/test/test_Attribute.cpp +147 -0
  96. data/test/test_Builtin_Object.cpp +36 -15
  97. data/test/test_Class.cpp +151 -274
  98. data/test/test_Constructor.cpp +10 -9
  99. data/test/test_Data_Object.cpp +135 -193
  100. data/test/test_Data_Type.cpp +323 -252
  101. data/test/test_Director.cpp +56 -42
  102. data/test/test_Enum.cpp +230 -104
  103. data/test/test_Exception.cpp +7 -7
  104. data/test/test_Hash.cpp +33 -31
  105. data/test/test_Identifier.cpp +6 -6
  106. data/test/test_Inheritance.cpp +221 -0
  107. data/test/test_Iterator.cpp +161 -0
  108. data/test/test_Jump_Tag.cpp +1 -1
  109. data/test/test_Keep_Alive.cpp +161 -0
  110. data/test/test_Memory_Management.cpp +4 -5
  111. data/test/test_Module.cpp +169 -111
  112. data/test/test_Object.cpp +51 -19
  113. data/test/test_Ownership.cpp +275 -0
  114. data/test/test_Self.cpp +205 -0
  115. data/test/test_Stl_Optional.cpp +90 -0
  116. data/test/test_Stl_Pair.cpp +144 -0
  117. data/test/test_Stl_SmartPointer.cpp +200 -0
  118. data/test/test_Stl_String.cpp +74 -0
  119. data/test/test_Stl_Vector.cpp +652 -0
  120. data/test/test_String.cpp +3 -3
  121. data/test/test_Struct.cpp +31 -40
  122. data/test/test_Symbol.cpp +3 -3
  123. data/test/test_To_From_Ruby.cpp +283 -218
  124. data/test/test_global_functions.cpp +41 -20
  125. data/test/unittest.cpp +34 -8
  126. data/test/unittest.hpp +0 -4
  127. metadata +117 -137
  128. data/Doxyfile +0 -2280
  129. data/Makefile.am +0 -26
  130. data/Makefile.in +0 -920
  131. data/README +0 -1055
  132. data/README.mingw +0 -8
  133. data/aclocal.m4 +0 -1088
  134. data/bootstrap +0 -8
  135. data/check_stdcxx_11.ac +0 -142
  136. data/config.guess +0 -1421
  137. data/config.sub +0 -1807
  138. data/configure +0 -7481
  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 -124
  173. data/rice/Makefile.in +0 -839
  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 -625
  236. data/ruby/lib/Makefile.am +0 -3
  237. data/ruby/lib/Makefile.in +0 -503
  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 -486
  242. data/test/Makefile.am +0 -72
  243. data/test/Makefile.in +0 -1150
  244. data/test/ext/Makefile.am +0 -41
  245. data/test/ext/Makefile.in +0 -480
  246. data/test/test_rice.rb +0 -41
@@ -1,13 +1,19 @@
1
+ #include <assert.h>
2
+
1
3
  #include "unittest.hpp"
2
- #include "rice/Data_Type.hpp"
3
- #include "rice/Exception.hpp"
4
- #include "rice/Constructor.hpp"
5
- #include "rice/global_function.hpp"
4
+ #include "embed_ruby.hpp"
5
+ #include <rice/rice.hpp>
6
+ #include <rice/stl.hpp>
6
7
 
7
8
  using namespace Rice;
8
9
 
9
10
  TESTSUITE(Data_Type);
10
11
 
12
+ SETUP(Data_Type)
13
+ {
14
+ embed_ruby();
15
+ }
16
+
11
17
  /**
12
18
  * The tests here are for the feature of taking an instance
13
19
  * of a Ruby-subclass of a Rice wrapped class and passing
@@ -16,333 +22,398 @@ TESTSUITE(Data_Type);
16
22
  * to see what we're talking about.
17
23
  */
18
24
 
19
- namespace {
20
-
21
- /**
22
- * The class we will subclass in Ruby
23
- */
24
- class Listener {
25
- public:
26
- Listener() { }
27
-
28
- virtual ~Listener() { }
29
-
30
- virtual int getValue() { return 4; }
31
- };
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;
32
34
 
33
- /**
34
- * This class will recieve a new Listener instance
35
- * from Ruby
36
- */
37
- 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
+ }
38
42
 
39
- public:
43
+ static Object singleton_method_object_int(Object object, int anInt)
44
+ {
45
+ return object;
46
+ }
40
47
 
41
- ListenerHandler() { }
48
+ static int singleton_function_int(int anInt)
49
+ {
50
+ return anInt;
51
+ }
42
52
 
43
- void addListener(Listener* newList) {
44
- mListeners.push_back(newList);
45
- }
53
+ public:
54
+ MyClass() = default;
55
+ MyClass(const MyClass& other) = delete;
56
+ MyClass(MyClass&& other) = delete;
46
57
 
47
- int process() {
48
- std::vector<Listener*>::iterator i = mListeners.begin();
49
- int accum = 0;
50
- for(; i != mListeners.end(); i++) {
51
- accum += (*i)->getValue();
52
- }
58
+ void no_return_no_arg()
59
+ {
60
+ no_return_no_arg_called = true;
61
+ }
53
62
 
54
- return accum;
55
- }
63
+ bool no_arg()
64
+ {
65
+ no_arg_called = true;
66
+ return true;
67
+ }
56
68
 
57
- size_t listenerCount() { return mListeners.size(); }
69
+ int int_arg(int i)
70
+ {
71
+ int_arg_called = true;
72
+ return i;
73
+ }
58
74
 
59
- private:
60
- 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
+ }
61
81
  };
62
- }
82
+ } // namespace
63
83
 
64
- SETUP(Data_Type)
84
+ TESTCASE(methods_with_member_pointers)
65
85
  {
66
- ruby_init();
67
-
68
- define_class<Listener>("Listener")
69
- .define_constructor(Constructor<Listener>())
70
- .define_method("get_value", &Listener::getValue);
71
-
72
- define_class<ListenerHandler>("ListenerHandler")
73
- .define_constructor(Constructor<ListenerHandler>())
74
- .define_method("add_listener", &ListenerHandler::addListener)
75
- .define_method("process", &ListenerHandler::process)
76
- .define_method("listener_count", &ListenerHandler::listenerCount);
77
-
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()));
78
111
  }
79
112
 
80
- TESTCASE(can_send_ruby_instance_back_into_rice)
113
+ TESTCASE(incorrect_number_of_args)
81
114
  {
82
- Module m = define_module("TestingModule");
83
- 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
+ }
84
128
 
85
- 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
+ }
86
144
 
87
- m.instance_eval("class MyListener < Listener; end;");
88
- 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
+ }
89
189
 
90
- ASSERT_EQUAL(INT2NUM(1), handler.call("listener_count").value());
91
- 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);
92
195
 
93
- m.instance_eval("@handler.add_listener(Listener.new)");
196
+ MyClass::reset();
94
197
 
95
- ASSERT_EQUAL(INT2NUM(2), handler.call("listener_count").value());
96
- ASSERT_EQUAL(INT2NUM(8), handler.call("process").value());
198
+ Object result = c.call("singleton_method_object_int", 42);
199
+ ASSERT_EQUAL(c, result);
97
200
  }
98
201
 
99
- /**
100
- * The following test SEGFAULTs right now
101
- */
102
- /*
103
- TESTCASE(no_super_in_constructor_still_works)
202
+ TESTCASE(static_singleton_function)
104
203
  {
105
- Module m = define_module("TestingModule");
106
- 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);
107
207
 
108
- ASSERT_EQUAL(INT2NUM(0), handler.call("listener_count").value());
208
+ MyClass::reset();
109
209
 
110
- // Because of this, there's a constructor but no super call
111
- m.instance_eval("class MyListener < Listener; def initialize; @val = 10; end; end;");
112
- 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
+ }
113
213
 
114
- ASSERT_EQUAL(INT2NUM(1), handler.call("listener_count").value());
115
- 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
+ });
116
222
 
117
- m.instance_eval("@handler.add_listener(MyListener.new)");
223
+ MyClass::reset();
118
224
 
119
- ASSERT_EQUAL(INT2NUM(2), handler.call("listener_count").value());
120
- ASSERT_EQUAL(INT2NUM(8), handler.call("process").value());
225
+ Object result = c.call("singleton_method_object_int", 42);
226
+ ASSERT_EQUAL(c, result);
121
227
  }
122
- */
123
-
124
- /**
125
- * Implicit Casting across unrelated types
126
- *
127
- * Two ways of defining if types are implicitly castable
128
- *
129
- * 1) operator
130
- * 2) constructor
131
- */
132
228
 
133
- /**
134
- * Examples here taken from Ogre's Math library.
135
- * This uses the constructor method of casting types.
136
- */
137
- namespace
229
+ TESTCASE(static_singleton_function_lambda)
138
230
  {
139
- const int degree2Radians = (3.14 / 180.0);
140
- const int radian2Degrees = (180.0 / 3.14);
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
+ });
141
237
 
142
- class Radian;
238
+ MyClass::reset();
143
239
 
144
- class Degree
145
- {
146
- public:
147
- explicit Degree(float d) : val_(d) {}
148
- Degree(const Radian& r);
149
-
150
- float valueDegrees() const { return val_; }
151
- float valueRadians() const { return val_ * degree2Radians; }
152
-
153
- private:
154
- float val_;
155
- };
240
+ Object result = c.call("singleton_function_int", 42);
241
+ ASSERT_EQUAL(42, detail::From_Ruby<int>().convert(result));
242
+ }
156
243
 
157
- class Radian
244
+ namespace {
245
+ class BaseClass
158
246
  {
159
- public:
160
- explicit Radian(float r) : val_(r) {}
161
- Radian(const Degree& d) : val_(d.valueRadians()) {}
162
-
163
- float valueRadians() const { return val_; }
164
- float valueDegrees() const { return val_ * radian2Degrees; }
165
-
166
- private:
167
- float val_;
247
+ public:
248
+ BaseClass() {}
168
249
  };
250
+ }
169
251
 
170
- // Due to circular dependencies, need to define some
171
- // methods down here
172
- Degree::Degree(const Radian& r)
173
- {
174
- val_ = r.valueDegrees();
175
- }
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
+ }
176
266
 
177
- /**
178
- * And now some methods that work w/ the above two classes
179
- */
180
- bool isAcute(Degree degree) {
181
- return degree.valueDegrees() < 90;
182
- }
267
+ namespace {
268
+ float with_reference_defaults_x;
269
+ std::string with_reference_defaults_str;
183
270
 
184
- bool isObtuse(Radian radian) {
185
- return radian.valueDegrees() > 90 && radian.valueDegrees() <= 180;
186
- }
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
+ };
187
280
 
188
- bool isRight(Degree* degree) {
189
- return degree->valueDegrees() == 90;
190
- }
191
281
  }
192
282
 
193
- TESTCASE(can_define_implicit_type_conversions_across_wrapped_types)
283
+ TESTCASE(define_method_works_with_reference_const_default_values)
194
284
  {
195
- define_class<Degree>("Degree")
196
- .define_constructor(Constructor<Degree, float>());
197
-
198
- define_class<Radian>("Radian")
199
- .define_constructor(Constructor<Radian, float>());
200
-
201
- define_implicit_cast<Degree, Radian>();
202
- define_implicit_cast<Radian, Degree>();
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"));
203
290
 
204
- define_global_function("is_acute", &isAcute);
205
- define_global_function("is_obtuse", &isObtuse);
206
- define_global_function("is_right", &isRight);
291
+ Object o = c.call("new");
292
+ o.call("bar", 3);
207
293
 
208
- Module m = define_module("TestingModule");
209
- Object result;
210
-
211
- // ACUTE
212
- result = m.instance_eval("is_acute(Degree.new(75))");
213
- ASSERT(from_ruby<bool>(result.value()));
294
+ ASSERT_EQUAL(3, with_reference_defaults_x);
295
+ ASSERT_EQUAL("testing", with_reference_defaults_str);
296
+ }
214
297
 
215
- result = m.instance_eval("is_acute(Radian.new(2.0))");
216
- ASSERT(!from_ruby<bool>(result.value()));
298
+ namespace
299
+ {
300
+ class RefTest
301
+ {
302
+ public:
303
+ RefTest() {}
217
304
 
218
- // OBTUSE
219
- result = m.instance_eval("is_obtuse(Degree.new(75))");
220
- ASSERT(!from_ruby<bool>(result.value()));
305
+ static std::string& getReference()
306
+ {
307
+ static std::string foo = "foo";
308
+ return foo;
309
+ }
310
+ };
311
+ }
221
312
 
222
- result = m.instance_eval("is_obtuse(Radian.new(2.0))");
223
- 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);
224
318
 
225
- // RIGHT
226
- result = m.instance_eval("is_right(Degree.new(90))");
227
- ASSERT(from_ruby<bool>(result.value()));
319
+ Module m(anonymous_module());
228
320
 
229
- result = m.instance_eval("is_right(Radian.new(2.0))");
230
- ASSERT(!from_ruby<bool>(result.value()));
321
+ Object result = m.instance_eval("RefTest.get_reference");
322
+ ASSERT_EQUAL(result, String("foo"));
231
323
  }
232
324
 
233
- namespace {
234
- class Explicit
325
+ namespace
326
+ {
327
+ struct MyStruct
235
328
  {
236
- public:
237
- Explicit(float v) {
238
- value = v;
239
- }
240
-
241
- Explicit(const Degree &d) {
242
- value = d.valueDegrees();
243
- }
244
-
245
- float getValue() { return value; }
329
+ MyStruct* set(MyStruct* ptr)
330
+ {
331
+ assert(ptr == nullptr);
332
+ return ptr;
333
+ }
246
334
 
247
- private:
248
- float value;
335
+ MyStruct* get()
336
+ {
337
+ return nullptr;
338
+ }
249
339
  };
250
-
251
- float getExplicitValue(Explicit* v) {
252
- return v->getValue();
253
- }
254
340
  }
255
341
 
256
- TESTCASE(supports_multiple_implicit_conversions_for_a_type)
342
+ TESTCASE(null_ptrs)
257
343
  {
258
- define_class<Degree>("Degree")
259
- .define_constructor(Constructor<Degree, float>());
260
-
261
- define_class<Radian>("Radian")
262
- .define_constructor(Constructor<Radian, float>());
263
-
264
- define_class<Explicit>("Explicit")
265
- .define_constructor(Constructor<Explicit, 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);
266
348
 
267
- define_global_function("is_obtuse", &isObtuse);
268
- define_global_function("explicit_value", &getExplicitValue);
349
+ Object o = c.call("new");
269
350
 
270
- define_implicit_cast<Radian, Degree>();
271
- define_implicit_cast<Degree, Radian>();
272
- define_implicit_cast<Degree, Explicit>();
351
+ Object result = o.call("get");
352
+ ASSERT_EQUAL(Qnil, result.value());
273
353
 
274
- Module m = define_module("TestingModule");
275
- Object result;
276
-
277
- result = m.instance_eval("is_obtuse(Degree.new(75))");
278
- ASSERT(!from_ruby<bool>(result.value()));
279
-
280
- result = m.instance_eval("explicit_value(Degree.new(75))");
281
- ASSERT_EQUAL(75.0, from_ruby<float>(result.value()));
354
+ result = o.call("set", nullptr);
355
+ ASSERT_EQUAL(Qnil, result.value());
282
356
  }
283
357
 
284
- /**
285
- * Sample taken and modified from boost::python::implicit:
286
- * http://www.boost.org/doc/libs/1_41_0/libs/python/doc/v2/implicit.html
287
- *
288
- * This is the operator version of casting and shows that this works for
289
- * base types as well as defined types
290
- */
291
- /*
292
- namespace {
293
- struct Real
358
+ namespace
359
+ {
360
+ class SomeClass
294
361
  {
295
- Real(int x)
296
- : v(x)
297
- {}
298
-
299
- operator int() const
300
- {
301
- return v;
302
- }
303
-
304
- int v;
305
362
  };
306
363
 
307
- int realValue(Real const& x)
364
+ void undefinedArg(SomeClass& someClass)
308
365
  {
309
- return x.v;
310
366
  }
311
367
 
312
- Real makeReal(int n)
368
+ SomeClass undefinedReturn()
313
369
  {
314
- return Real(n);
370
+ return SomeClass();
315
371
  }
316
372
  }
317
373
 
318
- TESTCASE(can_define_implicit_type_conversions_to_base_types)
374
+ TESTCASE(not_defined)
319
375
  {
320
- define_class<Real>("Real")
321
- .define_constructor(Constructor<Real, int>());
322
-
323
- // Define the conversion rules
324
- define_implicit_cast<Real, int>();
325
- 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
+ }
326
394
 
327
- define_global_function("real_value", &realValue);
328
- define_global_function("make_real", &makeReal);
329
395
 
396
+ /**
397
+ * The following test SEGFAULTs right now
398
+ */
399
+ /*
400
+ TESTCASE(no_super_in_constructor_still_works)
401
+ {
330
402
  Module m = define_module("TestingModule");
403
+ Object handler = m.instance_eval("@handler = ListenerHandler.new");
404
+
405
+ ASSERT_EQUAL(INT2NUM(0), handler.call("listener_count").value());
331
406
 
332
- // As Real object
333
- Object result = m.instance_eval("real_value( Real.new(4) )");
334
- 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)");
335
410
 
336
- // As fixnum (int)
337
- result = m.instance_eval("real_value(4)");
338
- ASSERT_EQUAL(4, from_ruby<int>(result.value()));
411
+ ASSERT_EQUAL(INT2NUM(1), handler.call("listener_count").value());
412
+ ASSERT_EQUAL(INT2NUM(4), handler.call("process").value());
339
413
 
340
- // As Real object
341
- result = m.instance_eval("r = make_real( Real.new(6) ); real_value(r)");
342
- ASSERT_EQUAL(6, from_ruby<int>(result.value()));
414
+ m.instance_eval("@handler.add_listener(MyListener.new)");
343
415
 
344
- // As fixnum (int)
345
- result = m.instance_eval("r = make_real(6); real_value(r)");
346
- ASSERT_EQUAL(6, from_ruby<int>(result.value()));
416
+ ASSERT_EQUAL(INT2NUM(2), handler.call("listener_count").value());
417
+ ASSERT_EQUAL(INT2NUM(8), handler.call("process").value());
347
418
  }
348
419
  */