rice 4.7.1 → 4.8.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 (153) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +29 -1
  3. data/CMakeLists.txt +14 -22
  4. data/CMakePresets.json +203 -75
  5. data/FindRuby.cmake +358 -123
  6. data/bin/rice-doc.rb +56 -141
  7. data/include/rice/api.hpp +248 -0
  8. data/include/rice/rice.hpp +2237 -1657
  9. data/include/rice/stl.hpp +346 -443
  10. data/lib/rice/doc/config.rb +70 -0
  11. data/lib/rice/doc/cpp_reference.rb +1 -4
  12. data/lib/rice/doc/mkdocs.rb +58 -20
  13. data/lib/rice/doc/rice.rb +20 -0
  14. data/lib/rice/doc.rb +1 -0
  15. data/lib/rice/make_rice_headers.rb +7 -0
  16. data/lib/rice/native_registry.rb +2 -2
  17. data/lib/rice/rbs.rb +2 -2
  18. data/lib/rice/version.rb +1 -1
  19. data/lib/rubygems_plugin.rb +12 -9
  20. data/rice/Arg.hpp +12 -6
  21. data/rice/Arg.ipp +14 -7
  22. data/rice/Buffer.ipp +44 -40
  23. data/rice/Callback.hpp +1 -1
  24. data/rice/Callback.ipp +2 -7
  25. data/rice/Constructor.hpp +1 -1
  26. data/rice/Constructor.ipp +11 -11
  27. data/rice/Data_Object.ipp +15 -15
  28. data/rice/Data_Type.hpp +9 -10
  29. data/rice/Data_Type.ipp +22 -25
  30. data/rice/Director.hpp +1 -0
  31. data/rice/Enum.ipp +58 -39
  32. data/rice/Exception.hpp +4 -4
  33. data/rice/Exception.ipp +7 -7
  34. data/rice/NoGVL.hpp +13 -0
  35. data/rice/Reference.hpp +56 -0
  36. data/rice/Reference.ipp +96 -0
  37. data/rice/Return.hpp +4 -1
  38. data/rice/Return.ipp +0 -6
  39. data/rice/cpp_api/Array.hpp +41 -4
  40. data/rice/cpp_api/Array.ipp +105 -9
  41. data/rice/cpp_api/Class.hpp +2 -2
  42. data/rice/cpp_api/Class.ipp +4 -4
  43. data/rice/cpp_api/Hash.ipp +7 -4
  44. data/rice/cpp_api/Module.hpp +4 -4
  45. data/rice/cpp_api/Module.ipp +12 -10
  46. data/rice/cpp_api/Object.hpp +4 -4
  47. data/rice/cpp_api/Object.ipp +15 -12
  48. data/rice/cpp_api/String.hpp +2 -2
  49. data/rice/cpp_api/String.ipp +11 -8
  50. data/rice/cpp_api/Symbol.ipp +7 -7
  51. data/rice/cpp_api/shared_methods.hpp +5 -9
  52. data/rice/detail/InstanceRegistry.hpp +0 -2
  53. data/rice/detail/Native.hpp +31 -21
  54. data/rice/detail/Native.ipp +282 -130
  55. data/rice/detail/NativeAttributeGet.hpp +5 -7
  56. data/rice/detail/NativeAttributeGet.ipp +26 -26
  57. data/rice/detail/NativeAttributeSet.hpp +2 -4
  58. data/rice/detail/NativeAttributeSet.ipp +20 -16
  59. data/rice/detail/NativeCallback.hpp +77 -0
  60. data/rice/detail/NativeCallback.ipp +280 -0
  61. data/rice/detail/NativeFunction.hpp +11 -21
  62. data/rice/detail/NativeFunction.ipp +58 -119
  63. data/rice/detail/NativeInvoker.hpp +4 -4
  64. data/rice/detail/NativeInvoker.ipp +7 -7
  65. data/rice/detail/NativeIterator.hpp +2 -4
  66. data/rice/detail/NativeIterator.ipp +18 -14
  67. data/rice/detail/NativeMethod.hpp +10 -20
  68. data/rice/detail/NativeMethod.ipp +54 -114
  69. data/rice/detail/NativeProc.hpp +5 -7
  70. data/rice/detail/NativeProc.ipp +39 -28
  71. data/rice/detail/NativeRegistry.hpp +0 -1
  72. data/rice/detail/Parameter.hpp +15 -8
  73. data/rice/detail/Parameter.ipp +102 -43
  74. data/rice/detail/Proc.ipp +14 -28
  75. data/rice/detail/RubyType.ipp +2 -53
  76. data/rice/detail/Type.hpp +23 -7
  77. data/rice/detail/Type.ipp +73 -93
  78. data/rice/detail/TypeRegistry.ipp +5 -4
  79. data/rice/detail/Wrapper.hpp +1 -1
  80. data/rice/detail/Wrapper.ipp +18 -10
  81. data/rice/detail/from_ruby.hpp +8 -6
  82. data/rice/detail/from_ruby.ipp +306 -173
  83. data/rice/detail/ruby.hpp +23 -0
  84. data/rice/libc/file.hpp +4 -4
  85. data/rice/rice.hpp +6 -8
  86. data/rice/rice_api/Native.ipp +5 -1
  87. data/rice/rice_api/Parameter.ipp +1 -1
  88. data/rice/ruby_mark.hpp +2 -1
  89. data/rice/stl/complex.ipp +12 -8
  90. data/rice/stl/map.ipp +27 -22
  91. data/rice/stl/monostate.ipp +16 -12
  92. data/rice/stl/multimap.hpp +0 -2
  93. data/rice/stl/multimap.ipp +27 -22
  94. data/rice/stl/optional.ipp +27 -11
  95. data/rice/stl/pair.ipp +5 -5
  96. data/rice/stl/reference_wrapper.ipp +5 -4
  97. data/rice/stl/set.ipp +16 -16
  98. data/rice/stl/shared_ptr.hpp +0 -16
  99. data/rice/stl/shared_ptr.ipp +34 -190
  100. data/rice/stl/string.ipp +18 -18
  101. data/rice/stl/string_view.ipp +1 -1
  102. data/rice/stl/tuple.ipp +15 -36
  103. data/rice/stl/unique_ptr.ipp +18 -8
  104. data/rice/stl/unordered_map.ipp +20 -15
  105. data/rice/stl/variant.ipp +37 -21
  106. data/rice/stl/vector.ipp +41 -36
  107. data/rice/traits/function_traits.hpp +19 -19
  108. data/rice/traits/method_traits.hpp +4 -4
  109. data/rice/traits/rice_traits.hpp +162 -39
  110. data/rice.gemspec +1 -3
  111. data/test/test_Array.cpp +261 -3
  112. data/test/test_Attribute.cpp +6 -3
  113. data/test/test_Buffer.cpp +6 -42
  114. data/test/test_Callback.cpp +77 -23
  115. data/test/test_Data_Object.cpp +1 -1
  116. data/test/test_Data_Type.cpp +21 -22
  117. data/test/test_Director.cpp +2 -4
  118. data/test/test_Enum.cpp +34 -5
  119. data/test/test_File.cpp +9 -5
  120. data/test/test_From_Ruby.cpp +4 -3
  121. data/test/test_GVL.cpp +3 -3
  122. data/test/test_Hash.cpp +1 -1
  123. data/test/test_Iterator.cpp +54 -22
  124. data/test/test_Keep_Alive.cpp +1 -1
  125. data/test/test_Keep_Alive_No_Wrapper.cpp +1 -1
  126. data/test/test_Module.cpp +5 -5
  127. data/test/test_Overloads.cpp +345 -48
  128. data/test/test_Proc.cpp +54 -0
  129. data/test/test_Reference.cpp +181 -0
  130. data/test/test_Self.cpp +2 -2
  131. data/test/test_Stl_Set.cpp +6 -6
  132. data/test/test_Stl_SharedPtr.cpp +54 -30
  133. data/test/test_Stl_String_View.cpp +4 -2
  134. data/test/test_Stl_Tuple.cpp +1 -1
  135. data/test/test_Stl_Variant.cpp +6 -14
  136. data/test/test_Stl_Vector.cpp +61 -30
  137. data/test/test_String.cpp +4 -2
  138. data/test/test_Struct.cpp +1 -1
  139. data/test/test_Symbol.cpp +1 -1
  140. data/test/test_To_Ruby.cpp +1 -0
  141. data/test/test_Type.cpp +36 -35
  142. data/test/test_global_functions.cpp +1 -1
  143. data/test/unittest.cpp +1 -1
  144. data/test/unittest.hpp +5 -5
  145. metadata +10 -10
  146. data/rice/Function.hpp +0 -17
  147. data/rice/Function.ipp +0 -13
  148. data/rice/detail/MethodInfo.hpp +0 -48
  149. data/rice/detail/MethodInfo.ipp +0 -99
  150. data/rice/detail/NativeCallbackFFI.hpp +0 -55
  151. data/rice/detail/NativeCallbackFFI.ipp +0 -152
  152. data/rice/detail/NativeCallbackSimple.hpp +0 -30
  153. data/rice/detail/NativeCallbackSimple.ipp +0 -29
data/test/test_Array.cpp CHANGED
@@ -2,6 +2,8 @@
2
2
  #include "embed_ruby.hpp"
3
3
  #include <rice/rice.hpp>
4
4
 
5
+ #include <algorithm>
6
+ #include <iterator>
5
7
  #include <vector>
6
8
 
7
9
  using namespace Rice;
@@ -235,9 +237,9 @@ TESTCASE(iterate_and_call_member)
235
237
  Array::iterator it = a.begin();
236
238
  Array::iterator end = a.end();
237
239
  std::vector<Object> v;
238
- for(int j = 0; it != end; ++j, ++it)
240
+ for(const auto& item: a)
239
241
  {
240
- v.push_back(it->to_s());
242
+ v.push_back(Object(item).to_s());
241
243
  }
242
244
  ASSERT_EQUAL(42, detail::From_Ruby<int>().convert(a[0].value()));
243
245
  ASSERT_EQUAL(43, detail::From_Ruby<int>().convert(a[1].value()));
@@ -278,7 +280,7 @@ TESTCASE(assign_int)
278
280
 
279
281
  namespace
280
282
  {
281
- void testArrayArg(Object self, Array string)
283
+ void testArrayArg(Object, Array)
282
284
  {
283
285
  }
284
286
  }
@@ -313,3 +315,259 @@ TESTCASE(array_from_ruby)
313
315
  Array a(rb_ary_new());
314
316
  ASSERT_EQUAL(a, detail::From_Ruby<Array>().convert(a));
315
317
  }
318
+
319
+ // Random-access iterator tests
320
+ TESTCASE(iterator_random_access_category)
321
+ {
322
+ // Verify the iterator is now a random-access iterator
323
+ static_assert(std::is_same_v<
324
+ Array::iterator::iterator_category,
325
+ std::random_access_iterator_tag>,
326
+ "Array::iterator should be a random_access_iterator");
327
+
328
+ static_assert(std::is_same_v<
329
+ Array::const_iterator::iterator_category,
330
+ std::random_access_iterator_tag>,
331
+ "Array::const_iterator should be a random_access_iterator");
332
+ }
333
+
334
+ TESTCASE(iterator_arithmetic_add)
335
+ {
336
+ Array a;
337
+ a.push(10, false);
338
+ a.push(20, false);
339
+ a.push(30, false);
340
+ a.push(40, false);
341
+ a.push(50, false);
342
+
343
+ Array::iterator it = a.begin();
344
+ Array::iterator it2 = it + 2;
345
+ ASSERT_EQUAL(30, detail::From_Ruby<int>().convert(it2->value()));
346
+
347
+ it2 = 3 + it; // Test non-member operator+
348
+ ASSERT_EQUAL(40, detail::From_Ruby<int>().convert(it2->value()));
349
+ }
350
+
351
+ TESTCASE(iterator_arithmetic_subtract)
352
+ {
353
+ Array a;
354
+ a.push(10, false);
355
+ a.push(20, false);
356
+ a.push(30, false);
357
+ a.push(40, false);
358
+ a.push(50, false);
359
+
360
+ Array::iterator it = a.end();
361
+ Array::iterator it2 = it - 2;
362
+ ASSERT_EQUAL(40, detail::From_Ruby<int>().convert(it2->value()));
363
+ }
364
+
365
+ TESTCASE(iterator_compound_assignment)
366
+ {
367
+ Array a;
368
+ a.push(10, false);
369
+ a.push(20, false);
370
+ a.push(30, false);
371
+ a.push(40, false);
372
+ a.push(50, false);
373
+
374
+ Array::iterator it = a.begin();
375
+ it += 3;
376
+ ASSERT_EQUAL(40, detail::From_Ruby<int>().convert(it->value()));
377
+
378
+ it -= 2;
379
+ ASSERT_EQUAL(20, detail::From_Ruby<int>().convert(it->value()));
380
+ }
381
+
382
+ TESTCASE(iterator_difference)
383
+ {
384
+ Array a;
385
+ a.push(10, false);
386
+ a.push(20, false);
387
+ a.push(30, false);
388
+ a.push(40, false);
389
+ a.push(50, false);
390
+
391
+ Array::iterator begin = a.begin();
392
+ Array::iterator end = a.end();
393
+ ASSERT_EQUAL(5, end - begin);
394
+ ASSERT_EQUAL(-5, begin - end);
395
+
396
+ Array::iterator mid = begin + 2;
397
+ ASSERT_EQUAL(2, mid - begin);
398
+ ASSERT_EQUAL(3, end - mid);
399
+ }
400
+
401
+ TESTCASE(iterator_subscript)
402
+ {
403
+ Array a;
404
+ a.push(10, false);
405
+ a.push(20, false);
406
+ a.push(30, false);
407
+ a.push(40, false);
408
+ a.push(50, false);
409
+
410
+ Array::iterator it = a.begin();
411
+ ASSERT_EQUAL(10, detail::From_Ruby<int>().convert(it[0].value()));
412
+ ASSERT_EQUAL(30, detail::From_Ruby<int>().convert(it[2].value()));
413
+ ASSERT_EQUAL(50, detail::From_Ruby<int>().convert(it[4].value()));
414
+ }
415
+
416
+ TESTCASE(iterator_comparison_less_greater)
417
+ {
418
+ Array a;
419
+ a.push(10, false);
420
+ a.push(20, false);
421
+ a.push(30, false);
422
+
423
+ Array::iterator begin = a.begin();
424
+ Array::iterator mid = begin + 1;
425
+ Array::iterator end = a.end();
426
+
427
+ ASSERT_EQUAL(true, begin < mid);
428
+ ASSERT_EQUAL(true, begin < end);
429
+ ASSERT_EQUAL(true, mid < end);
430
+
431
+ ASSERT_EQUAL(true, end > mid);
432
+ ASSERT_EQUAL(true, end > begin);
433
+ ASSERT_EQUAL(true, mid > begin);
434
+
435
+ ASSERT_EQUAL(true, begin <= begin);
436
+ ASSERT_EQUAL(true, begin <= mid);
437
+ ASSERT_EQUAL(true, mid <= end);
438
+
439
+ ASSERT_EQUAL(true, end >= end);
440
+ ASSERT_EQUAL(true, end >= mid);
441
+ ASSERT_EQUAL(true, mid >= begin);
442
+ }
443
+
444
+ TESTCASE(iterator_decrement)
445
+ {
446
+ Array a;
447
+ a.push(10, false);
448
+ a.push(20, false);
449
+ a.push(30, false);
450
+
451
+ Array::iterator it = a.end();
452
+ --it;
453
+ ASSERT_EQUAL(30, detail::From_Ruby<int>().convert(it->value()));
454
+ --it;
455
+ ASSERT_EQUAL(20, detail::From_Ruby<int>().convert(it->value()));
456
+ --it;
457
+ ASSERT_EQUAL(10, detail::From_Ruby<int>().convert(it->value()));
458
+ }
459
+
460
+ TESTCASE(iterator_decrement_postfix)
461
+ {
462
+ Array a;
463
+ a.push(10, false);
464
+ a.push(20, false);
465
+ a.push(30, false);
466
+
467
+ Array::iterator it = a.end();
468
+ it--;
469
+ ASSERT_EQUAL(30, detail::From_Ruby<int>().convert(it->value()));
470
+ Array::iterator prev = it--;
471
+ ASSERT_EQUAL(30, detail::From_Ruby<int>().convert(prev->value()));
472
+ ASSERT_EQUAL(20, detail::From_Ruby<int>().convert(it->value()));
473
+ }
474
+
475
+ TESTCASE(iterator_std_sort)
476
+ {
477
+ // std::sort requires iterators that return assignable references.
478
+ // Our iterator returns a Proxy which supports assignment to the array,
479
+ // but STL algorithms need iter_swap to work. Test that we can use
480
+ // std::sort with explicit swap via indices instead.
481
+ Array a;
482
+ a.push(30, false);
483
+ a.push(10, false);
484
+ a.push(50, false);
485
+ a.push(20, false);
486
+ a.push(40, false);
487
+
488
+ // Manual sort using random-access capabilities (bubble sort for simplicity)
489
+ for (long i = 0; i < a.size() - 1; i++)
490
+ {
491
+ for (long j = 0; j < a.size() - i - 1; j++)
492
+ {
493
+ auto it = a.begin();
494
+ int val1 = detail::From_Ruby<int>().convert(it[j].value());
495
+ int val2 = detail::From_Ruby<int>().convert(it[j + 1].value());
496
+ if (val1 > val2)
497
+ {
498
+ // Swap using array subscript operator
499
+ Object temp = a[j];
500
+ a[j] = detail::From_Ruby<int>().convert(a[j + 1].value());
501
+ a[j + 1] = detail::From_Ruby<int>().convert(temp.value());
502
+ }
503
+ }
504
+ }
505
+
506
+ ASSERT_EQUAL(10, detail::From_Ruby<int>().convert(a[0].value()));
507
+ ASSERT_EQUAL(20, detail::From_Ruby<int>().convert(a[1].value()));
508
+ ASSERT_EQUAL(30, detail::From_Ruby<int>().convert(a[2].value()));
509
+ ASSERT_EQUAL(40, detail::From_Ruby<int>().convert(a[3].value()));
510
+ ASSERT_EQUAL(50, detail::From_Ruby<int>().convert(a[4].value()));
511
+ }
512
+
513
+ TESTCASE(iterator_std_reverse)
514
+ {
515
+ // std::reverse requires iter_swap support. Test manual reverse using
516
+ // random-access iterator capabilities instead.
517
+ Array a;
518
+ a.push(10, false);
519
+ a.push(20, false);
520
+ a.push(30, false);
521
+ a.push(40, false);
522
+ a.push(50, false);
523
+
524
+ // Manual reverse using random-access capabilities
525
+ auto begin = a.begin();
526
+ auto end = a.end() - 1;
527
+ while (begin < end)
528
+ {
529
+ long i = begin.index();
530
+ long j = end.index();
531
+ Object temp = a[i];
532
+ a[i] = detail::From_Ruby<int>().convert(a[j].value());
533
+ a[j] = detail::From_Ruby<int>().convert(temp.value());
534
+ ++begin;
535
+ --end;
536
+ }
537
+
538
+ ASSERT_EQUAL(50, detail::From_Ruby<int>().convert(a[0].value()));
539
+ ASSERT_EQUAL(40, detail::From_Ruby<int>().convert(a[1].value()));
540
+ ASSERT_EQUAL(30, detail::From_Ruby<int>().convert(a[2].value()));
541
+ ASSERT_EQUAL(20, detail::From_Ruby<int>().convert(a[3].value()));
542
+ ASSERT_EQUAL(10, detail::From_Ruby<int>().convert(a[4].value()));
543
+ }
544
+
545
+ TESTCASE(iterator_std_distance)
546
+ {
547
+ Array a;
548
+ a.push(10, false);
549
+ a.push(20, false);
550
+ a.push(30, false);
551
+ a.push(40, false);
552
+ a.push(50, false);
553
+
554
+ ASSERT_EQUAL(5, std::distance(a.begin(), a.end()));
555
+ ASSERT_EQUAL(3, std::distance(a.begin() + 1, a.begin() + 4));
556
+ }
557
+
558
+ TESTCASE(iterator_std_advance)
559
+ {
560
+ Array a;
561
+ a.push(10, false);
562
+ a.push(20, false);
563
+ a.push(30, false);
564
+ a.push(40, false);
565
+ a.push(50, false);
566
+
567
+ Array::iterator it = a.begin();
568
+ std::advance(it, 3);
569
+ ASSERT_EQUAL(40, detail::From_Ruby<int>().convert(it->value()));
570
+
571
+ std::advance(it, -2);
572
+ ASSERT_EQUAL(20, detail::From_Ruby<int>().convert(it->value()));
573
+ }
@@ -28,6 +28,9 @@ namespace
28
28
 
29
29
  class NotAssignable
30
30
  {
31
+ public:
32
+ NotAssignable() = default;
33
+ NotAssignable(const NotAssignable&) = default;
31
34
  NotAssignable& operator=(const NotAssignable&) = delete;
32
35
  };
33
36
 
@@ -35,7 +38,7 @@ namespace
35
38
  {
36
39
  public:
37
40
  NotCopyable() = default;
38
- NotCopyable(const NotCopyable& other) = delete;
41
+ NotCopyable(const NotCopyable&) = delete;
39
42
  };
40
43
 
41
44
  enum OldEnum
@@ -453,7 +456,7 @@ TESTCASE(BufferAttribute)
453
456
 
454
457
  Class c = define_class<BufferAttrs>("BufferAttrs")
455
458
  .define_constructor(Constructor<BufferAttrs>())
456
- .define_attr("buffer", &BufferAttrs::buffer, Rice::AttrAccess::Read, Return().setBuffer());
459
+ .define_attr("buffer", &BufferAttrs::buffer, Rice::AttrAccess::Read, ReturnBuffer());
457
460
 
458
461
  std::string code = R"(struct = BufferAttrs.new
459
462
  struct.buffer.class)";
@@ -487,7 +490,7 @@ TESTCASE(CounterBufferAttribute)
487
490
 
488
491
  define_class<BufferAttrs>("BufferAttrs")
489
492
  .define_constructor(Constructor<BufferAttrs>())
490
- .define_attr("counters_buffer", &BufferAttrs::countersBuffer, Rice::AttrAccess::Read, Return().setBuffer());
493
+ .define_attr("counters_buffer", &BufferAttrs::countersBuffer, Rice::AttrAccess::Read, ReturnBuffer());
491
494
 
492
495
  std::string code = R"(struct = BufferAttrs.new
493
496
  struct.counters_buffer.class)";
data/test/test_Buffer.cpp CHANGED
@@ -255,8 +255,8 @@ namespace
255
255
  TESTCASE(pointer_of_doubles)
256
256
  {
257
257
  Module m = define_module("Testing").
258
- define_module_function("speeds", &speeds, Return().setBuffer()).
259
- define_module_function("speeds_ptr", &speedsPtr, Return().setBuffer());
258
+ define_module_function("speeds", &speeds, ReturnBuffer()).
259
+ define_module_function("speeds_ptr", &speedsPtr, ReturnBuffer());
260
260
 
261
261
  std::string code = R"(buffer = Rice::Buffer≺double≻.new(speeds, 3)
262
262
  buffer[2])";
@@ -275,48 +275,12 @@ TESTCASE(pointer_of_doubles)
275
275
 
276
276
  namespace
277
277
  {
278
- void updateRef(int& ref)
279
- {
280
- ref = 4;
281
- }
282
-
283
278
  void updatePtr(int* ptr)
284
279
  {
285
280
  *ptr = 5;
286
281
  }
287
282
  }
288
283
 
289
- TESTCASE(update_reference)
290
- {
291
- define_buffer<int>();
292
- Module m = define_module("Testing");
293
- m.define_module_function("update_reference", &updateRef);
294
-
295
- std::string code = R"(buffer = Rice::Buffer≺int≻.new(0)
296
- update_reference(buffer.data)
297
- buffer.to_ary(1).first)";
298
-
299
- Object result = m.module_eval(code);
300
- ASSERT_EQUAL(4, detail::From_Ruby<int>().convert(result));
301
-
302
- code = R"(buffer = Rice::Buffer≺int≻.new(0)
303
- update_reference(buffer.data)
304
- buffer[0])";
305
-
306
- result = m.module_eval(code);
307
- ASSERT_EQUAL(4, detail::From_Ruby<int>().convert(result));
308
-
309
- code = R"(buffer = Rice::Buffer≺int≻.new(0)
310
- update_reference(buffer.data)
311
- buffer[1])";
312
-
313
- ASSERT_EXCEPTION_CHECK(
314
- Exception,
315
- m.module_eval(code),
316
- ASSERT_EQUAL("index 1 outside of bounds: 0..1", ex.what())
317
- );
318
- }
319
-
320
284
  TESTCASE(update_ptr)
321
285
  {
322
286
  define_buffer<int>();
@@ -492,8 +456,8 @@ TESTCASE(pointer_of_objects)
492
456
  define_buffer<MyClassBuf*>();
493
457
 
494
458
  Module m = define_module("Testing").
495
- define_module_function("class_buffs", &classBufs).
496
- define_module_function("class_buffs_ptr", &classBufsPtr);
459
+ define_module_function("class_buffs", &classBufs, ReturnBuffer()).
460
+ define_module_function("class_buffs_ptr", &classBufsPtr, ReturnBuffer());
497
461
 
498
462
  define_class<MyClassBuf>("MyClassBuf").
499
463
  define_constructor(Constructor<MyClassBuf, int>()).
@@ -593,8 +557,8 @@ TESTCASE(array_of_objects_ptr)
593
557
  TESTCASE(pass_objects)
594
558
  {
595
559
  Module m = define_module("Testing");
596
- m.define_module_function<size_t(*)(const MyClassBuf*, size_t)>("sum_ids", &sumIds, Arg("myClasses").setBuffer());
597
- m.define_module_function<size_t(*)(const MyClassBuf**, size_t)>("sum_ids_ptr", &sumIds, Arg("myClasses").setBuffer());
560
+ m.define_module_function<size_t(*)(const MyClassBuf*, size_t)>("sum_ids", &sumIds, ArgBuffer("myClasses"));
561
+ m.define_module_function<size_t(*)(const MyClassBuf**, size_t)>("sum_ids_ptr", &sumIds, ArgBuffer("myClasses"));
598
562
 
599
563
  define_class_under<MyClassBuf>(m, "MyClassBuf").
600
564
  define_constructor(Constructor<MyClassBuf, int>()).
@@ -20,7 +20,7 @@ TEARDOWN(Callback)
20
20
 
21
21
  namespace
22
22
  {
23
- using Callback_T = char*(*)(int, double, bool, char*);
23
+ using Callback_T = char*(*)(int, double, bool, char*, int&);
24
24
  Callback_T globalCallback;
25
25
 
26
26
  void registerCallback(Callback_T callback)
@@ -28,11 +28,11 @@ namespace
28
28
  globalCallback = callback;
29
29
  }
30
30
 
31
- char* triggerCallback(int anInt, double aDouble, bool aBool, char* aString)
31
+ char* triggerCallback(int anInt, double aDouble, bool aBool, char* aString, int& intRef)
32
32
  {
33
33
  if (globalCallback)
34
34
  {
35
- return globalCallback(anInt, aDouble, aBool, aString);
35
+ return globalCallback(anInt, aDouble, aBool, aString, intRef);
36
36
  }
37
37
  throw std::runtime_error("Callback has not been registered");
38
38
  }
@@ -41,13 +41,12 @@ namespace
41
41
  TESTCASE(LambdaCallBack)
42
42
  {
43
43
  Module m = define_module("TestingLambda");
44
- m.define_module_function("register_callback", registerCallback).
45
- define_module_function("trigger_callback", triggerCallback);
44
+ m.define_module_function("register_callback", registerCallback);
46
45
 
47
46
  ASSERT_EQUAL(globalCallback, nullptr);
48
47
 
49
- std::string code = R"(callback = lambda do |an_int, a_double, a_bool, a_string|
50
- values = [an_int, a_double, a_bool, a_string]
48
+ std::string code = R"(callback = lambda do |an_int, a_double, a_bool, a_string, an_intref|
49
+ values = [an_int, a_double, a_bool, a_string, an_intref]
51
50
  values.map {|value| value.to_s}.join(" - ")
52
51
  end
53
52
  register_callback(callback))";
@@ -55,25 +54,26 @@ TESTCASE(LambdaCallBack)
55
54
  m.module_eval(code);
56
55
  ASSERT((globalCallback != nullptr));
57
56
 
58
- String result = m.call("trigger_callback", 1, 2, true, "hello");
59
- ASSERT_EQUAL("1 - 2.0 - true - hello", result.c_str());
57
+ int ref = 4;
58
+ char* result = triggerCallback(1, 2, true, "hello", ref);
59
+ ASSERT_EQUAL("1 - 2.0 - true - hello - 4", result);
60
60
  }
61
61
 
62
62
  TESTCASE(BlockCallBack)
63
63
  {
64
64
  Module m = define_module("TestingBlock");
65
- m.define_module_function("register_callback", registerCallback).
65
+ m.define_module_function("register_callback", registerCallback, Arg("callback").setBlock()).
66
66
  define_module_function("trigger_callback", triggerCallback);
67
67
 
68
- std::string code = R"(register_callback do |an_int, a_double, a_bool, a_string|
69
- values = [an_int, a_double, a_bool, a_string]
68
+ std::string code = R"(register_callback do |an_int, a_double, a_bool, a_string, an_intref|
69
+ values = [an_int, a_double, a_bool, a_string, an_intref]
70
70
  values.map {|value| value.to_s}.join(" - ")
71
71
  end)";
72
72
 
73
73
  m.module_eval(code);
74
74
 
75
- String result = m.call("trigger_callback", 4, 5.5, false, "Hello block");
76
- ASSERT_EQUAL("4 - 5.5 - false - Hello block", result.c_str());
75
+ String result = m.call("trigger_callback", 4, 5.5, false, "Hello block", 8);
76
+ ASSERT_EQUAL("4 - 5.5 - false - Hello block - 8", result.c_str());
77
77
  }
78
78
 
79
79
  TESTCASE(ProcCallBack)
@@ -82,16 +82,17 @@ TESTCASE(ProcCallBack)
82
82
  m.define_module_function("register_callback", registerCallback).
83
83
  define_module_function("trigger_callback", triggerCallback);
84
84
 
85
- std::string code = R"(callback = Proc.new do |an_int, a_double, a_bool, a_string|
86
- values = [an_int, a_double, a_bool, a_string]
85
+ std::string code = R"(callback = Proc.new do |an_int, a_double, a_bool, a_string, an_intref|
86
+ values = [an_int, a_double, a_bool, a_string, an_intref]
87
87
  values.map {|value| value.to_s}.join(" - ")
88
88
  end
89
89
  register_callback(callback))";
90
90
 
91
91
  m.module_eval(code);
92
92
 
93
- String result = m.call("trigger_callback", 8, 4.4, true, "Hello proc");
94
- ASSERT_EQUAL("8 - 4.4 - true - Hello proc", result.c_str());
93
+ int ref = 9;
94
+ String result = m.call("trigger_callback", 8, 4.4, true, "Hello proc", ref);
95
+ ASSERT_EQUAL("8 - 4.4 - true - Hello proc - 9", result.c_str());
95
96
  }
96
97
 
97
98
  TESTCASE(MethodCallBack)
@@ -100,16 +101,16 @@ TESTCASE(MethodCallBack)
100
101
  m.define_module_function("register_callback", registerCallback).
101
102
  define_module_function("trigger_callback", triggerCallback);
102
103
 
103
- std::string code = R"(def self.callback(an_int, a_double, a_bool, a_string)
104
- values = [an_int, a_double, a_bool, a_string]
104
+ std::string code = R"(def self.callback(an_int, a_double, a_bool, a_string, an_intref)
105
+ values = [an_int, a_double, a_bool, a_string, an_intref]
105
106
  values.map {|value| value.to_s}.join(" - ")
106
107
  end
107
108
  register_callback(method(:callback).to_proc))";
108
109
 
109
110
  m.module_eval(code);
110
111
 
111
- String result = m.call("trigger_callback", 11.1, 22.9, true, "Hello method");
112
- ASSERT_EQUAL("11 - 22.9 - true - Hello method", result.c_str());
112
+ String result = m.call("trigger_callback", 11.1, 22.9, true, "Hello method", 17.2);
113
+ ASSERT_EQUAL("11 - 22.9 - true - Hello method - 17", result.c_str());
113
114
  }
114
115
 
115
116
  namespace
@@ -123,7 +124,7 @@ namespace
123
124
  TESTCASE(FunctionArg)
124
125
  {
125
126
  Module m = define_module("TestingFunctionArg");
126
- m.define_module_function("function_arg", functionArg);
127
+ m.define_module_function("function_arg", functionArg, Arg("i"), Arg("block").setBlock());
127
128
 
128
129
  std::string code = R"(function_arg(4) do |i|
129
130
  i * i
@@ -227,3 +228,56 @@ TESTCASE(UserData)
227
228
  String result = m.call("trigger_callback");
228
229
  ASSERT_EQUAL("TestingUserData::UserDataClass", result.c_str());
229
230
  }
231
+
232
+ namespace
233
+ {
234
+ using Callback_T4 = void(*)(void* userData);
235
+ Callback_T4 globalCallback4;
236
+ void* globalUserData4 = nullptr;
237
+
238
+ void registerCallback4(Callback_T4 callback, void* userData)
239
+ {
240
+ globalCallback4 = callback;
241
+ globalUserData4 = userData;
242
+ }
243
+
244
+ void triggerCallback4()
245
+ {
246
+ if (globalCallback4)
247
+ {
248
+ globalCallback4(globalUserData4);
249
+ }
250
+ else
251
+ {
252
+ throw std::runtime_error("Callback has not been registered");
253
+ }
254
+ }
255
+ }
256
+
257
+ TESTCASE(VoidReturn)
258
+ {
259
+ Module m = define_module("TestingUserData");
260
+ m.define_module_function("register_callback4", registerCallback4, Arg("callback"), Arg("user_data").setOpaque()).
261
+ define_module_function("trigger_callback4", triggerCallback4);
262
+
263
+ define_callback<Callback_T4>(Arg("user_data").setOpaque());
264
+
265
+ std::string code = R"(class UserDataClass
266
+ end
267
+
268
+ user_data_1 = UserDataClass.new
269
+
270
+ callback = Proc.new do |user_data_2|
271
+ unless user_data_1.equal?(user_data_2)
272
+ raise("Unexpected user data object")
273
+ end
274
+ user_data_2.class.name
275
+ end
276
+
277
+ register_callback4(callback, user_data_1))";
278
+
279
+ m.module_eval(code);
280
+
281
+ Object result = m.call("trigger_callback4");
282
+ ASSERT_EQUAL(Qnil, result.value());
283
+ }
@@ -33,7 +33,7 @@ namespace
33
33
  namespace Rice
34
34
  {
35
35
  template<>
36
- void ruby_mark(MyDataType* myDataType)
36
+ void ruby_mark(MyDataType*)
37
37
  {
38
38
  test_ruby_mark_called = true;
39
39
  }