rice 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
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
+ }