rice 1.1.0 → 1.2.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 (54) hide show
  1. data/Doxyfile +1 -1
  2. data/Makefile.in +3 -2
  3. data/README +247 -16
  4. data/aclocal.m4 +62 -51
  5. data/configure +1585 -1456
  6. data/extconf.rb +9 -1
  7. data/rice/Arg.hpp +8 -0
  8. data/rice/Arg_impl.hpp +124 -0
  9. data/rice/Arg_operators.cpp +21 -0
  10. data/rice/Arg_operators.hpp +19 -0
  11. data/rice/Constructor.hpp +150 -0
  12. data/rice/Data_Type.ipp +51 -6
  13. data/rice/Director.cpp +19 -0
  14. data/rice/Director.hpp +47 -0
  15. data/rice/Enum.hpp +2 -3
  16. data/rice/Enum.ipp +1 -1
  17. data/rice/Hash.hpp +1 -1
  18. data/rice/Makefile.am +7 -0
  19. data/rice/Makefile.in +18 -7
  20. data/rice/Module_impl.hpp +36 -3
  21. data/rice/Module_impl.ipp +56 -7
  22. data/rice/VM.cpp +2 -2
  23. data/rice/config.hpp +1 -1
  24. data/rice/detail/Arguments.hpp +118 -0
  25. data/rice/detail/Auto_Function_Wrapper.hpp +206 -96
  26. data/rice/detail/Auto_Function_Wrapper.ipp +1687 -144
  27. data/rice/detail/Auto_Member_Function_Wrapper.hpp +234 -123
  28. data/rice/detail/Auto_Member_Function_Wrapper.ipp +1133 -306
  29. data/rice/detail/Caster.hpp +3 -1
  30. data/rice/detail/creation_funcs.hpp +0 -8
  31. data/rice/detail/creation_funcs.ipp +1 -27
  32. data/rice/detail/define_method_and_auto_wrap.hpp +3 -1
  33. data/rice/detail/define_method_and_auto_wrap.ipp +4 -3
  34. data/rice/detail/object_call.ipp +1 -1
  35. data/rice/detail/ruby.hpp +1 -33
  36. data/rice/detail/wrap_function.hpp +103 -48
  37. data/rice/detail/wrap_function.ipp +154 -96
  38. data/rice/generate_code.rb +520 -55
  39. data/rice/global_function.hpp +12 -1
  40. data/rice/global_function.ipp +14 -2
  41. data/ruby/Makefile.in +5 -4
  42. data/ruby/lib/Makefile.in +4 -3
  43. data/ruby/lib/version.rb +1 -1
  44. data/sample/Makefile.in +4 -3
  45. data/test/Makefile.am +2 -0
  46. data/test/Makefile.in +32 -13
  47. data/test/test_Class.cpp +36 -14
  48. data/test/test_Constructor.cpp +176 -1
  49. data/test/test_Data_Type.cpp +121 -0
  50. data/test/test_Director.cpp +225 -0
  51. data/test/test_Enum.cpp +33 -0
  52. data/test/test_Module.cpp +175 -0
  53. data/test/test_global_functions.cpp +70 -1
  54. metadata +27 -7
@@ -0,0 +1,121 @@
1
+ #include "unittest.hpp"
2
+ #include "rice/Data_Type.hpp"
3
+ #include "rice/Exception.hpp"
4
+ #include "rice/Constructor.hpp"
5
+
6
+ using namespace Rice;
7
+
8
+ TESTSUITE(Data_Type);
9
+
10
+ /**
11
+ * The tests here are for the feature of taking an instance
12
+ * of a Ruby-subclass of a Rice wrapped class and passing
13
+ * that instance back into the Rice wrapper. While that
14
+ * might be confusing, the test code is pretty straight foward
15
+ * to see what we're talking about.
16
+ */
17
+
18
+ namespace {
19
+
20
+ /**
21
+ * The class we will subclass in Ruby
22
+ */
23
+ class Listener {
24
+ public:
25
+ Listener() { }
26
+
27
+ virtual ~Listener() { }
28
+
29
+ virtual int getValue() { return 4; }
30
+ };
31
+
32
+ /**
33
+ * This class will recieve a new Listener instance
34
+ * from Ruby
35
+ */
36
+ class ListenerHandler {
37
+
38
+ public:
39
+
40
+ ListenerHandler() { }
41
+
42
+ void addListener(Listener* newList) {
43
+ mListeners.push_back(newList);
44
+ }
45
+
46
+ int process() {
47
+ vector<Listener*>::iterator i = mListeners.begin();
48
+ int accum = 0;
49
+ for(; i != mListeners.end(); i++) {
50
+ accum += (*i)->getValue();
51
+ }
52
+
53
+ return accum;
54
+ }
55
+
56
+ int listenerCount() { return mListeners.size(); }
57
+
58
+ private:
59
+ vector<Listener*> mListeners;
60
+ };
61
+ }
62
+
63
+ SETUP(Data_Type)
64
+ {
65
+ ruby_init();
66
+
67
+ define_class<Listener>("Listener")
68
+ .define_constructor(Constructor<Listener>())
69
+ .define_method("get_value", &Listener::getValue);
70
+
71
+ define_class<ListenerHandler>("ListenerHandler")
72
+ .define_constructor(Constructor<ListenerHandler>())
73
+ .define_method("add_listener", &ListenerHandler::addListener)
74
+ .define_method("process", &ListenerHandler::process)
75
+ .define_method("listener_count", &ListenerHandler::listenerCount);
76
+
77
+ }
78
+
79
+ TESTCASE(can_send_ruby_instance_back_into_rice)
80
+ {
81
+ Module m = define_module("TestingModule");
82
+ Object handler = m.instance_eval("@handler = ListenerHandler.new");
83
+
84
+ ASSERT_EQUAL(INT2NUM(0), handler.call("listener_count").value());
85
+
86
+ m.instance_eval("class MyListener < Listener; end;");
87
+ m.instance_eval("@handler.add_listener(MyListener.new)");
88
+
89
+ ASSERT_EQUAL(INT2NUM(1), handler.call("listener_count").value());
90
+ ASSERT_EQUAL(INT2NUM(4), handler.call("process").value());
91
+
92
+ m.instance_eval("@handler.add_listener(Listener.new)");
93
+
94
+ ASSERT_EQUAL(INT2NUM(2), handler.call("listener_count").value());
95
+ ASSERT_EQUAL(INT2NUM(8), handler.call("process").value());
96
+ }
97
+
98
+ /**
99
+ * The following test SEGFAULTs right now
100
+ */
101
+ /*
102
+ TESTCASE(no_super_in_constructor_still_works)
103
+ {
104
+ Module m = define_module("TestingModule");
105
+ Object handler = m.instance_eval("@handler = ListenerHandler.new");
106
+
107
+ ASSERT_EQUAL(INT2NUM(0), handler.call("listener_count").value());
108
+
109
+ // Because of this, there's a constructor but no super call
110
+ m.instance_eval("class MyListener < Listener; def initialize; @val = 10; end; end;");
111
+ m.instance_eval("@handler.add_listener(MyListener.new)");
112
+
113
+ ASSERT_EQUAL(INT2NUM(1), handler.call("listener_count").value());
114
+ ASSERT_EQUAL(INT2NUM(4), handler.call("process").value());
115
+
116
+ m.instance_eval("@handler.add_listener(MyListener.new)");
117
+
118
+ ASSERT_EQUAL(INT2NUM(2), handler.call("listener_count").value());
119
+ ASSERT_EQUAL(INT2NUM(8), handler.call("process").value());
120
+ }
121
+ */
@@ -0,0 +1,225 @@
1
+ #include "unittest.hpp"
2
+ #include "rice/Director.hpp"
3
+ #include "rice/Constructor.hpp"
4
+ #include "rice/Data_Type.hpp"
5
+
6
+ #include <vector>
7
+ #include <iostream>
8
+
9
+ using namespace std;
10
+ using namespace Rice;
11
+
12
+ TESTSUITE(Director);
13
+
14
+ namespace {
15
+ /**
16
+ * Abstract base class
17
+ */
18
+ class Worker {
19
+ public:
20
+ virtual ~Worker() { }
21
+
22
+ int getNumber() { return 12; }
23
+
24
+ virtual int doSomething(int num) { return num * 4; }
25
+
26
+ virtual int process(int num) = 0;
27
+ };
28
+
29
+ /**
30
+ * Subclass that implements pure virtual
31
+ */
32
+ class MultiplyWorker : public Worker {
33
+ public:
34
+ virtual ~MultiplyWorker() { }
35
+
36
+ virtual int process(int num) { return num * 2; }
37
+ };
38
+
39
+ /**
40
+ * Class to handle workers
41
+ */
42
+ class Handler {
43
+ std::vector<Worker*> mWorkers;
44
+
45
+ public:
46
+
47
+ void addWorker(Worker* worker) { mWorkers.push_back(worker); }
48
+
49
+ int processWorkers(int start) {
50
+ std::vector<Worker*>::iterator i = mWorkers.begin();
51
+ int results = start;
52
+
53
+ for(; i != mWorkers.end(); i++) {
54
+ results = (*i)->process(results);
55
+ }
56
+
57
+ return results;
58
+ }
59
+ };
60
+
61
+ /**
62
+ * Our Director wrapper of Worker
63
+ */
64
+ class WorkerDirector : public Worker, public Rice::Director {
65
+ public:
66
+ WorkerDirector(Object self) : Director(self) { }
67
+
68
+ int process(int num) {
69
+ if(callIsFromRuby("process")) {
70
+ raisePureVirtual();
71
+ } else {
72
+ return from_ruby<int>( getSelf().call("process", num) );
73
+ }
74
+ }
75
+
76
+ int doSomething(int num) {
77
+ if(callIsFromRuby("do_something")) {
78
+ return this->Worker::doSomething(num);
79
+ } else {
80
+ return from_ruby<int>( getSelf().call("do_something", num) );
81
+ }
82
+ }
83
+ };
84
+ };
85
+
86
+ SETUP(Director)
87
+ {
88
+ ruby_init();
89
+
90
+ // Always need to tell Rice about the base class so that
91
+ // casting works correctly
92
+ define_class<Worker>("__Worker__");
93
+ }
94
+
95
+ TESTCASE(exposes_worker_as_instantiatable_class)
96
+ {
97
+ define_class<WorkerDirector, Worker>("Worker")
98
+ .define_constructor(Constructor<WorkerDirector, Object>())
99
+ .define_method("get_number", &Worker::getNumber);
100
+
101
+ Module m = define_module("Testing");
102
+ Object result = m.instance_eval("worker = Worker.new; worker.get_number");
103
+
104
+ ASSERT_EQUAL(12, from_ruby<int>(result.value()));
105
+ }
106
+
107
+ TESTCASE(can_call_virtual_methods_on_base_class)
108
+ {
109
+ define_class<WorkerDirector, Worker>("Worker")
110
+ .define_constructor(Constructor<WorkerDirector, Object>())
111
+ .define_method("get_number", &Worker::getNumber)
112
+ .define_method("do_something", &WorkerDirector::doSomething);
113
+
114
+ Module m = define_module("Testing");
115
+
116
+ Object result = m.instance_eval("worker = Worker.new; worker.do_something(4)");
117
+
118
+ ASSERT_EQUAL(16, from_ruby<int>(result.value()));
119
+ }
120
+
121
+ TESTCASE(super_calls_pass_execution_up_the_inheritance_chain)
122
+ {
123
+ define_class<WorkerDirector, Worker>("Worker")
124
+ .define_constructor(Constructor<WorkerDirector, Object>())
125
+ .define_method("do_something", &WorkerDirector::doSomething);
126
+
127
+ Module m = define_module("Testing");
128
+ m.instance_eval("class RubyWorker < Worker; def do_something(num); super * num; end; end");
129
+
130
+ Object result = m.instance_eval("worker = RubyWorker.new; worker.do_something(10)");
131
+
132
+ ASSERT_EQUAL(400, from_ruby<int>(result.value()));
133
+ }
134
+
135
+ TESTCASE(super_calls_on_pure_virtual_raise_error)
136
+ {
137
+ define_class<WorkerDirector, Worker>("Worker")
138
+ .define_constructor(Constructor<WorkerDirector, Object>())
139
+ .define_method("process", &WorkerDirector::process);
140
+
141
+ Module m = define_module("Testing");
142
+ m.instance_eval("class RubyWorker < Worker; def process(num); super; end; end");
143
+
144
+ ASSERT_EXCEPTION_CHECK(
145
+ Exception,
146
+ m.instance_eval("worker = RubyWorker.new; worker.process(10)"),
147
+ ASSERT_EQUAL(
148
+ Object(rb_eNotImpError),
149
+ Object(CLASS_OF(ex.value()))
150
+ )
151
+ );
152
+ }
153
+
154
+ TESTCASE(polymorphic_calls_head_down_the_call_chain)
155
+ {
156
+ define_class<Handler>("Handler")
157
+ .define_constructor(Constructor<Handler>())
158
+ .define_method("add_worker", &Handler::addWorker)
159
+ .define_method("process_workers", &Handler::processWorkers);
160
+
161
+ define_class<WorkerDirector, Worker>("Worker")
162
+ .define_constructor(Constructor<WorkerDirector, Object>())
163
+ .define_method("process", &WorkerDirector::process);
164
+
165
+ Module m = define_module("Testing");
166
+
167
+ m.instance_eval(
168
+ "class EchoWorker < Worker; def process(num); num + 2; end; end;"
169
+ "class DoubleWorker < Worker; def process(num); num * 2; end; end;"
170
+ "handler = Handler.new;"
171
+ "handler.add_worker(EchoWorker.new);"
172
+ "handler.add_worker(DoubleWorker.new);"
173
+ );
174
+
175
+ Object result = m.instance_eval("handler.process_workers(5)");
176
+
177
+ // Hit's EchoWorker, so 5 + 2, then passes that to DoubleWorker, so 7 * 2 = 14
178
+ ASSERT_EQUAL(14, from_ruby<int>(result.value()));
179
+ }
180
+
181
+ namespace {
182
+
183
+ class CallsSelf {
184
+ public:
185
+ int doIt(int in) {
186
+ return doItImpl(in);
187
+ }
188
+
189
+ virtual int doItImpl(int in) = 0;
190
+ };
191
+
192
+ class CallsSelfDirector : public CallsSelf, public Director {
193
+
194
+ public:
195
+ CallsSelfDirector(Object self) : Director(self) { }
196
+
197
+ virtual int doItImpl(int in) {
198
+ if(!callIsFromRuby("do_it_impl")) {
199
+ return 0;
200
+ } else {
201
+ return from_ruby<int>( getSelf().call("do_it_impl", in) );
202
+ }
203
+ }
204
+ };
205
+
206
+ }
207
+
208
+ TESTCASE(mix_of_polymorphic_calls_and_inheritance_dont_cause_infinite_loops)
209
+ {
210
+ define_class<CallsSelf>("__CallsSelf__");
211
+
212
+ define_class<CallsSelfDirector, CallsSelf>("CallsSelf")
213
+ .define_constructor(Constructor<CallsSelfDirector, Rice::Object>())
214
+ .define_method("do_it_impl", &CallsSelfDirector::doItImpl)
215
+ .define_method("do_it", &CallsSelf::doIt);
216
+
217
+ Module m = define_module("Testing");
218
+
219
+ Object result = m.instance_eval(
220
+ "class MySelf < CallsSelf; def do_it_impl(num); num * 10; end; end;"
221
+ "c = MySelf.new; c.do_it(10)"
222
+ );
223
+
224
+ ASSERT_EQUAL(100, from_ruby<int>(result.value()));
225
+ }
@@ -2,6 +2,7 @@
2
2
  #include "rice/Enum.hpp"
3
3
  #include "rice/Array.hpp"
4
4
  #include "rice/String.hpp"
5
+ #include "rice/Constructor.hpp"
5
6
  #include <iostream>
6
7
 
7
8
  using namespace Rice;
@@ -146,12 +147,14 @@ TESTCASE(different_objects_eql)
146
147
  ASSERT_EQUAL(true, red1 == red2);
147
148
  }
148
149
 
150
+ /*
149
151
  TESTCASE(hash)
150
152
  {
151
153
  Enum<Color> rb_cColor = define_color_enum();
152
154
  Data_Object<Color> red(new Color(RED));
153
155
  ASSERT_EQUAL(to_ruby(int(RED)), red.call("hash"));
154
156
  }
157
+ */
155
158
 
156
159
  TESTCASE(from_int)
157
160
  {
@@ -160,3 +163,33 @@ TESTCASE(from_int)
160
163
  ASSERT_EQUAL(RED, *color);
161
164
  }
162
165
 
166
+ namespace
167
+ {
168
+ class Inner
169
+ {
170
+ public:
171
+ enum Props
172
+ {
173
+ VALUE1,
174
+ VALUE2,
175
+ VALUE3
176
+ };
177
+ };
178
+ }
179
+
180
+ TESTCASE(nested_enums)
181
+ {
182
+ {
183
+ Data_Type<Inner> inner = define_class<Inner>("Inner");
184
+ define_enum<Inner::Props>("Props", inner)
185
+ .define_value("VALUE1", Inner::VALUE1)
186
+ .define_value("VALUE2", Inner::VALUE2)
187
+ .define_value("VALUE3", Inner::VALUE3);
188
+ inner.define_constructor(Constructor<Inner>());
189
+ }
190
+
191
+ ASSERT_EQUAL(to_ruby(int(0)), Object(protect(rb_eval_string, "Inner::Props::VALUE1.to_i")));
192
+ ASSERT_EQUAL(to_ruby(int(1)), Object(protect(rb_eval_string, "Inner::Props::VALUE2.to_i")));
193
+ ASSERT_EQUAL(to_ruby(int(2)), Object(protect(rb_eval_string, "Inner::Props::VALUE3.to_i")));
194
+ }
195
+
@@ -2,6 +2,8 @@
2
2
  #include "rice/Module.hpp"
3
3
  #include "rice/Exception.hpp"
4
4
  #include "rice/Array.hpp"
5
+ #include "rice/Arg.hpp"
6
+ #include "rice/global_function.hpp"
5
7
 
6
8
  using namespace Rice;
7
9
 
@@ -251,3 +253,176 @@ TESTCASE(mod_name_anonymous)
251
253
  ASSERT_EQUAL(String(""), m.name());
252
254
  }
253
255
 
256
+ /**
257
+ * Tests for default arguments
258
+ */
259
+ namespace
260
+ {
261
+ int defaults_method_one_arg1;
262
+ int defaults_method_one_arg2;
263
+ bool defaults_method_one_arg3 = false;
264
+
265
+ void defaults_method_one(int arg1, int arg2 = 3, bool arg3 = true)
266
+ {
267
+ defaults_method_one_arg1 = arg1;
268
+ defaults_method_one_arg2 = arg2;
269
+ defaults_method_one_arg3 = arg3;
270
+ }
271
+ }
272
+
273
+ TESTCASE(define_method_default_arguments)
274
+ {
275
+ Module m(anonymous_module());
276
+ m.define_method("foo", &defaults_method_one, (Arg("arg1"), Arg("arg2") = 3, Arg("arg3") = true));
277
+
278
+ Object o = m.instance_eval("o = Object.new; o.extend(self); o");
279
+ o.call("foo", 2);
280
+
281
+ ASSERT_EQUAL(2, defaults_method_one_arg1);
282
+ ASSERT_EQUAL(3, defaults_method_one_arg2);
283
+ ASSERT(defaults_method_one_arg3);
284
+
285
+ o.call("foo", 11, 10);
286
+
287
+ ASSERT_EQUAL(11, defaults_method_one_arg1);
288
+ ASSERT_EQUAL(10, defaults_method_one_arg2);
289
+ ASSERT(defaults_method_one_arg3);
290
+
291
+ o.call("foo", 22, 33, false);
292
+
293
+ ASSERT_EQUAL(22, defaults_method_one_arg1);
294
+ ASSERT_EQUAL(33, defaults_method_one_arg2);
295
+ ASSERT(!defaults_method_one_arg3);
296
+ }
297
+
298
+ TESTCASE(default_arguments_still_throws_argument_error)
299
+ {
300
+ Module m(anonymous_module());
301
+ m.define_method("foo", &defaults_method_one, (Arg("arg1"), Arg("arg2") = 3, Arg("arg3") = true));
302
+
303
+ ASSERT_EXCEPTION_CHECK(
304
+ Exception,
305
+ m.instance_eval("o = Object.new; o.extend(self); o.foo()"),
306
+ ASSERT_EQUAL(
307
+ Object(rb_eArgError),
308
+ Object(CLASS_OF(ex.value()))
309
+ )
310
+ );
311
+
312
+ ASSERT_EXCEPTION_CHECK(
313
+ Exception,
314
+ m.instance_eval("o = Object.new; o.extend(self); o.foo(3, 4, false, 17)"),
315
+ ASSERT_EQUAL(
316
+ Object(rb_eArgError),
317
+ Object(CLASS_OF(ex.value()))
318
+ )
319
+ );
320
+ }
321
+
322
+ namespace {
323
+ int the_one_default_arg = 0;
324
+ void method_with_one_default_arg(int num = 4) {
325
+ the_one_default_arg = num;
326
+ }
327
+ }
328
+
329
+ TESTCASE(defining_methods_with_single_default_argument)
330
+ {
331
+ // define_method
332
+ Module m(anonymous_module());
333
+ m.define_method("foo", &method_with_one_default_arg, (Arg("num") = 4));
334
+ m.instance_eval("o = Object.new; o.extend(self); o.foo()");
335
+ ASSERT_EQUAL(4, the_one_default_arg);
336
+
337
+ the_one_default_arg = 0;
338
+
339
+ // define_singleton_method
340
+ Class c(anonymous_class());
341
+ c.define_singleton_method("foo", &method_with_one_default_arg, (Arg("num") = 4));
342
+ c.call("foo");
343
+ ASSERT_EQUAL(4, the_one_default_arg);
344
+
345
+ the_one_default_arg = 0;
346
+
347
+ // define_module_function
348
+ m.define_module_function("foo2", &method_with_one_default_arg, (Arg("num") = 4));
349
+
350
+ m.call("foo2");
351
+ ASSERT_EQUAL(4, the_one_default_arg);
352
+ }
353
+
354
+ TESTCASE(default_arguments_for_define_singleton_method)
355
+ {
356
+ Class c(anonymous_class());
357
+ c.define_singleton_method("foo", &defaults_method_one, (Arg("arg1"), Arg("arg2") = 3, Arg("arg3") = true));
358
+
359
+ c.call("foo", 2);
360
+
361
+ ASSERT_EQUAL(2, defaults_method_one_arg1);
362
+ ASSERT_EQUAL(3, defaults_method_one_arg2);
363
+ ASSERT(defaults_method_one_arg3);
364
+
365
+ c.call("foo", 11, 10);
366
+
367
+ ASSERT_EQUAL(11, defaults_method_one_arg1);
368
+ ASSERT_EQUAL(10, defaults_method_one_arg2);
369
+ ASSERT(defaults_method_one_arg3);
370
+
371
+ c.call("foo", 22, 33, false);
372
+
373
+ ASSERT_EQUAL(22, defaults_method_one_arg1);
374
+ ASSERT_EQUAL(33, defaults_method_one_arg2);
375
+ ASSERT(!defaults_method_one_arg3);
376
+ }
377
+
378
+ TESTCASE(default_arguments_for_define_module_function)
379
+ {
380
+ Module m(anonymous_module());
381
+ m.define_module_function("foo", &defaults_method_one, (Arg("arg1"), Arg("arg2") = 3, Arg("arg3") = true));
382
+
383
+ m.call("foo", 2);
384
+
385
+ ASSERT_EQUAL(2, defaults_method_one_arg1);
386
+ ASSERT_EQUAL(3, defaults_method_one_arg2);
387
+ ASSERT(defaults_method_one_arg3);
388
+
389
+ m.call("foo", 11, 10);
390
+
391
+ ASSERT_EQUAL(11, defaults_method_one_arg1);
392
+ ASSERT_EQUAL(10, defaults_method_one_arg2);
393
+ ASSERT(defaults_method_one_arg3);
394
+
395
+ m.call("foo", 22, 33, false);
396
+
397
+ ASSERT_EQUAL(22, defaults_method_one_arg1);
398
+ ASSERT_EQUAL(33, defaults_method_one_arg2);
399
+ ASSERT(!defaults_method_one_arg3);
400
+ }
401
+
402
+ namespace {
403
+ std::string with_defaults_and_references_x;
404
+ bool with_defaults_and_references_doIt;
405
+
406
+ void with_defaults_and_references(std::string const& x, bool doIt = false)
407
+ {
408
+ with_defaults_and_references_x = x;
409
+ with_defaults_and_references_doIt = doIt;
410
+ }
411
+ }
412
+
413
+ template<>
414
+ std::string* from_ruby<std::string*>(Rice::Object x) {
415
+ return new std::string(from_ruby<char const*>(x));
416
+ }
417
+
418
+ TESTCASE(define_method_works_with_reference_arguments)
419
+ {
420
+ Module m(anonymous_module());
421
+ m.define_module_function("foo", &with_defaults_and_references,
422
+ (Arg("x"), Arg("doIt") = false));
423
+
424
+ m.call("foo", "test");
425
+
426
+ ASSERT_EQUAL("test", with_defaults_and_references_x);
427
+ ASSERT(!with_defaults_and_references_doIt);
428
+ }