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
@@ -28,6 +28,8 @@ TEARDOWN(Overloads)
28
28
  Rice::detail::Registries::instance.types.remove<MyClass>();
29
29
  Rice::detail::Registries::instance.types.remove<MyClass2>();
30
30
  Rice::detail::Registries::instance.types.remove<MyClass3>();
31
+ Rice::detail::Registries::instance.natives.reset(Module(rb_mKernel));
32
+
31
33
  rb_gc_start();
32
34
  }
33
35
 
@@ -116,31 +118,62 @@ namespace
116
118
  return "run<void>";
117
119
  }
118
120
 
119
- std::string run(int a)
121
+ std::string run(int)
120
122
  {
121
123
  return "run<int>";
122
124
  }
123
125
 
124
- std::string run(float a)
126
+ std::string run(float)
125
127
  {
126
128
  return "run<float>";
127
129
  }
128
130
 
129
- std::string run(std::string a)
131
+ std::string run(std::string)
130
132
  {
131
133
  return "run<string>";
132
134
  }
133
135
 
134
- std::string run(int a, float b = 1.0)
136
+ std::string run(int, float = 1.0)
135
137
  {
136
138
  return "run<int,float>";
137
139
  }
138
140
 
139
- std::string run(float a, int b = 1)
141
+ std::string run(float, int = 1)
140
142
  {
141
143
  return "run<float,int>";
142
144
  }
143
- } // namespace
145
+
146
+ // Signed vs unsigned overloads
147
+ std::string run(unsigned int)
148
+ {
149
+ return "run<unsigned int>";
150
+ }
151
+
152
+ std::string run(short)
153
+ {
154
+ return "run<short>";
155
+ }
156
+
157
+ std::string run(unsigned short)
158
+ {
159
+ return "run<unsigned short>";
160
+ }
161
+
162
+ std::string run(long long)
163
+ {
164
+ return "run<long long>";
165
+ }
166
+
167
+ std::string run(unsigned long long)
168
+ {
169
+ return "run<unsigned long long>";
170
+ }
171
+
172
+ std::string run(double)
173
+ {
174
+ return "run<double>";
175
+ }
176
+ }
144
177
 
145
178
  void create_globals()
146
179
  {
@@ -212,27 +245,27 @@ namespace
212
245
  return "run<void>";
213
246
  }
214
247
 
215
- std::string run(int a)
248
+ std::string run(int)
216
249
  {
217
250
  return "run<int>";
218
251
  }
219
252
 
220
- std::string run(float a)
253
+ std::string run(float)
221
254
  {
222
255
  return "run<float>";
223
256
  }
224
257
 
225
- std::string run(std::string a)
258
+ std::string run(std::string)
226
259
  {
227
260
  return "run<string>";
228
261
  }
229
262
 
230
- std::string run(int a, float b = 1.0)
263
+ std::string run(int, float = 1.0)
231
264
  {
232
265
  return "run<int,float>";
233
266
  }
234
267
 
235
- std::string run(float a, int b = 1)
268
+ std::string run(float, int = 1)
236
269
  {
237
270
  return "run<float,int>";
238
271
  }
@@ -321,10 +354,10 @@ TESTCASE(invalid_parameters)
321
354
 
322
355
  std::string expected = R"(Could not resolve method call for MyClass#run
323
356
  6 overload(s) were evaluated based on the types of Ruby parameters provided:
324
- std::string AnonymousNamespace::MyClass*::run(int, float)
325
- std::string AnonymousNamespace::MyClass*::run(float, int)
326
357
  std::string AnonymousNamespace::MyClass*::run()
327
358
  std::string AnonymousNamespace::MyClass*::run(std::string)
359
+ std::string AnonymousNamespace::MyClass*::run(int, float)
360
+ std::string AnonymousNamespace::MyClass*::run(float, int)
328
361
  std::string AnonymousNamespace::MyClass*::run(int)
329
362
  std::string AnonymousNamespace::MyClass*::run(float))";
330
363
 
@@ -344,27 +377,27 @@ namespace
344
377
  this->constructor = "constructor<void>";
345
378
  }
346
379
 
347
- MyClass2(int a)
380
+ MyClass2(int)
348
381
  {
349
382
  this->constructor = "constructor<int>";
350
383
  }
351
384
 
352
- MyClass2(float a)
385
+ MyClass2(float)
353
386
  {
354
387
  this->constructor = "constructor<float>";
355
388
  }
356
389
 
357
- MyClass2(std::string a)
390
+ MyClass2(std::string)
358
391
  {
359
392
  this->constructor = "constructor<string>";
360
393
  }
361
394
 
362
- MyClass2(int a, float b)
395
+ MyClass2(int, float)
363
396
  {
364
397
  this->constructor = "constructor<int,float>";
365
398
  }
366
399
 
367
- MyClass2(float a, int b)
400
+ MyClass2(float, int)
368
401
  {
369
402
  this->constructor = "constructor<float,int>";
370
403
  }
@@ -446,55 +479,65 @@ namespace
446
479
  class MyClass3
447
480
  {
448
481
  public:
449
- std::string run(char value)
482
+ std::string run(char)
450
483
  {
451
484
  return "run<char>";
452
485
  }
453
486
 
454
- std::string run(unsigned char value)
487
+ std::string run(unsigned char)
455
488
  {
456
489
  return "run<unsigned char>";
457
490
  }
458
491
 
459
- std::string run(char* value)
492
+ std::string run(char*)
460
493
  {
461
494
  return "run<char*>";
462
495
  }
463
496
 
464
- std::string run(unsigned char* value)
497
+ std::string run(unsigned char*)
465
498
  {
466
499
  return "run<unsigned char*>";
467
500
  }
468
501
 
469
- std::string run(short value)
502
+ std::string run(short)
470
503
  {
471
504
  return "run<short>";
472
505
  }
473
506
 
474
- std::string run(int value)
507
+ std::string run(int)
475
508
  {
476
509
  return "run<int>";
477
510
  }
478
511
 
479
- std::string run(float value)
512
+ std::string run(float)
480
513
  {
481
514
  return "run<float>";
482
515
  }
483
516
 
484
- std::string run(double value)
517
+ std::string run(double)
485
518
  {
486
519
  return "run<double>";
487
520
  }
488
521
 
489
- std::string run(long value)
522
+ std::string run(long)
490
523
  {
491
524
  return "run<long>";
492
525
  }
493
526
 
494
- std::string run(long long value)
527
+ std::string run(long long)
495
528
  {
496
529
  return "run<long long>";
497
530
  }
531
+
532
+ std::string run(int&)
533
+ {
534
+ return "run<int&>";
535
+ }
536
+
537
+ std::string run(int*)
538
+ {
539
+ return "run<int*>";
540
+ }
498
541
  };
499
542
  } // namespace
500
543
 
@@ -515,7 +558,15 @@ TESTCASE(int_conversion_1)
515
558
  value = 1
516
559
  my_class.run(value))";
517
560
  String result = m.module_eval(code);
518
- ASSERT_EQUAL("run<long>", result.str());
561
+
562
+ if constexpr (sizeof(long) == sizeof(int))
563
+ {
564
+ ASSERT_EQUAL("run<long long>", result.str());
565
+ }
566
+ else
567
+ {
568
+ ASSERT_EQUAL("run<long>", result.str());
569
+ }
519
570
 
520
571
  code = R"(my_class = MyClass3.new
521
572
  value = 2**60
@@ -529,6 +580,33 @@ TESTCASE(int_conversion_1)
529
580
  #endif
530
581
 
531
582
  ASSERT_EQUAL(expected, result.str());
583
+
584
+ code = R"(my_class = MyClass3.new
585
+ value = 2**64
586
+ my_class.run(value))";
587
+
588
+ #ifdef _MSC_VER
589
+ std::string expected2 = R"(Could not resolve method call for MyClass3#run
590
+ 5 overload(s) were evaluated based on the types of Ruby parameters provided:
591
+ std::string AnonymousNamespace::MyClass3*::run(char*)
592
+ std::string AnonymousNamespace::MyClass3*::run(unsigned char*)
593
+ std::string AnonymousNamespace::MyClass3*::run(short)
594
+ std::string AnonymousNamespace::MyClass3*::run(long)
595
+ std::string AnonymousNamespace::MyClass3*::run(__int64))";
596
+ #else
597
+ std::string expected2 = R"(Could not resolve method call for MyClass3#run
598
+ 5 overload(s) were evaluated based on the types of Ruby parameters provided:
599
+ std::string AnonymousNamespace::MyClass3*::run(char*)
600
+ std::string AnonymousNamespace::MyClass3*::run(unsigned char*)
601
+ std::string AnonymousNamespace::MyClass3*::run(short)
602
+ std::string AnonymousNamespace::MyClass3*::run(long)
603
+ std::string AnonymousNamespace::MyClass3*::run(long long))";
604
+ #endif
605
+
606
+ ASSERT_EXCEPTION_CHECK(
607
+ Exception,
608
+ result = m.module_eval(code),
609
+ ASSERT_EQUAL(expected2, ex.what()));
532
610
  }
533
611
 
534
612
  TESTCASE(int_conversion_2)
@@ -544,21 +622,14 @@ TESTCASE(int_conversion_2)
544
622
  value = 1
545
623
  my_class.run(value))";
546
624
  String result = m.module_eval(code);
547
- ASSERT_EQUAL("run<float>", result.str());
625
+ ASSERT_EQUAL("run<short>", result.str());
548
626
 
549
627
  code = R"(my_class = MyClass3.new
550
628
  value = 2**64
551
629
  my_class.run(value))";
552
630
 
553
- std::string expected = R"(Could not resolve method call for MyClass3#run
554
- 2 overload(s) were evaluated based on the types of Ruby parameters provided:
555
- std::string AnonymousNamespace::MyClass3*::run(short)
556
- std::string AnonymousNamespace::MyClass3*::run(float))";
557
-
558
- ASSERT_EXCEPTION_CHECK(
559
- Exception,
560
- result = m.module_eval(code),
561
- ASSERT_EQUAL(expected.c_str(), ex.what()));
631
+ result = m.module_eval(code);
632
+ ASSERT_EQUAL("run<float>", result.str());
562
633
  }
563
634
 
564
635
  TESTCASE(int_conversion_3)
@@ -647,7 +718,7 @@ TESTCASE(int_conversion_6)
647
718
  Class c = define_class<MyClass3>("MyClass3").
648
719
  define_constructor(Constructor<MyClass3>()).
649
720
  define_method<std::string(MyClass3::*)(unsigned char)>("run", &MyClass3::run).
650
- define_method<std::string(MyClass3::*)(unsigned char*)>("run", &MyClass3::run, Arg("value").setBuffer());
721
+ define_method<std::string(MyClass3::*)(unsigned char*)>("run", &MyClass3::run, ArgBuffer("value"));
651
722
 
652
723
  Module m = define_module("Testing");
653
724
 
@@ -658,6 +729,28 @@ TESTCASE(int_conversion_6)
658
729
  ASSERT_EQUAL("run<unsigned char*>", result.str());
659
730
  }
660
731
 
732
+ TESTCASE(int_conversion_7)
733
+ {
734
+ Class c = define_class<MyClass3>("MyClass3").
735
+ define_constructor(Constructor<MyClass3>()).
736
+ define_method<std::string(MyClass3::*)(int&)>("run", &MyClass3::run).
737
+ define_method<std::string(MyClass3::*)(int*)>("run", &MyClass3::run);
738
+
739
+ Module m = define_module("Testing");
740
+
741
+ std::string code = R"(my_class = MyClass3.new
742
+ buffer = Rice::Buffer≺int≻.new("99")
743
+ my_class.run(buffer.data))";
744
+ String result = m.module_eval(code);
745
+ ASSERT_EQUAL("run<int*>", result.str());
746
+
747
+ code = R"(my_class = MyClass3.new
748
+ ref = Rice::Reference≺int≻.new(99)
749
+ my_class.run(ref))";
750
+ result = m.module_eval(code);
751
+ ASSERT_EQUAL("run<int&>", result.str());
752
+ }
753
+
661
754
  namespace
662
755
  {
663
756
  class MyClass4
@@ -679,12 +772,12 @@ namespace
679
772
  class MyClass5
680
773
  {
681
774
  public:
682
- MyClass5(MyClass4& class4)
775
+ MyClass5(MyClass4&)
683
776
  {
684
777
  this->result = "non-const ref";
685
778
  }
686
779
 
687
- MyClass5(const MyClass4& class4)
780
+ MyClass5(const MyClass4&)
688
781
  {
689
782
  this->result = "const ref";
690
783
  }
@@ -753,12 +846,12 @@ namespace
753
846
  class MyClass7
754
847
  {
755
848
  public:
756
- MyClass7(MyClass6* class6)
849
+ MyClass7(MyClass6*)
757
850
  {
758
851
  this->result = "non-const pointer";
759
852
  }
760
853
 
761
- MyClass7(const MyClass6* class6)
854
+ MyClass7(const MyClass6*)
762
855
  {
763
856
  this->result = "const pointer";
764
857
  }
@@ -807,12 +900,12 @@ TESTCASE(ConstPointer)
807
900
 
808
901
  namespace
809
902
  {
810
- std::string pointer(const MyClass6* data)
903
+ std::string pointer(const MyClass6*)
811
904
  {
812
905
  return "pointer";
813
906
  }
814
907
 
815
- std::string pointer(MyClass6* data)
908
+ std::string pointer(MyClass6*)
816
909
  {
817
910
  return "pointerBuffer";
818
911
  }
@@ -826,7 +919,7 @@ TESTCASE(PointerNotBuffer)
826
919
  define_constructor(Constructor<MyClass6>());
827
920
 
828
921
  m.define_module_function<std::string(*)(const MyClass6*)>("pointer", pointer).
829
- define_module_function<std::string(*)(MyClass6*)>("pointer", pointer, Arg("data").setBuffer());
922
+ define_module_function<std::string(*)(MyClass6*)>("pointer", pointer, ArgBuffer("data"));
830
923
 
831
924
  std::string code = R"(my_class6 = MyClass6.new
832
925
  pointer(my_class6))";
@@ -843,7 +936,7 @@ TESTCASE(PointerBuffer)
843
936
  define_constructor(Constructor<MyClass6>());
844
937
 
845
938
  m.define_function<std::string(*)(const MyClass6*)>("pointer", pointer).
846
- define_function<std::string(*)(MyClass6*)>("pointer", pointer, Arg("data").setBuffer());
939
+ define_function<std::string(*)(MyClass6*)>("pointer", pointer, ArgBuffer("data"));
847
940
 
848
941
  std::string code = R"(my_class6 = MyClass6.new
849
942
  buffer = Rice::Buffer≺AnonymousNamespace꞉꞉MyClass6≻.new(my_class6)
@@ -852,3 +945,207 @@ TESTCASE(PointerBuffer)
852
945
  String result = m.module_eval(code);
853
946
  ASSERT_EQUAL("pointerBuffer", result.str());
854
947
  }
948
+
949
+ namespace
950
+ {
951
+ class Pixel
952
+ {
953
+ public:
954
+ Pixel(uint32_t rgb)
955
+ {
956
+ this->rgb = rgb;
957
+ }
958
+
959
+ Pixel(uint8_t red, uint8_t green, uint8_t blue)
960
+ {
961
+ this->rgb = (red << 16) | (green << 8) | blue;
962
+ }
963
+
964
+ uint32_t rgb = 0;
965
+ };
966
+ }
967
+
968
+ TESTCASE(FloatToIntConversionWithOverload)
969
+ {
970
+ Module m = define_module("Testing");
971
+
972
+ // Define overloaded functions: one takes int, one takes no args
973
+ // There is NO float overload
974
+ m.define_module_function("hello_int_resolve", [](int x) -> int { return x; });
975
+ m.define_module_function("hello_int_resolve", []() -> int { return 0; });
976
+
977
+ // Calling with an integer should work
978
+ std::string code = R"(hello_int_resolve(1))";
979
+ Object result = m.module_eval(code);
980
+ ASSERT_EQUAL(1, detail::From_Ruby<int>().convert(result.value()));
981
+
982
+ // Calling with no args should work
983
+ code = R"(hello_int_resolve())";
984
+ result = m.module_eval(code);
985
+ ASSERT_EQUAL(0, detail::From_Ruby<int>().convert(result.value()));
986
+
987
+ // Calling with a float should convert to int (lossy but allowed)
988
+ code = R"(hello_int_resolve(1.7))";
989
+ result = m.module_eval(code);
990
+ ASSERT_EQUAL(1, detail::From_Ruby<int>().convert(result.value()));
991
+ }
992
+
993
+ TESTCASE(Keywords)
994
+ {
995
+ Module m = define_module("Testing");
996
+
997
+ define_class<Pixel>("Pixel").
998
+ define_constructor(Constructor<Pixel, uint32_t>()).
999
+ define_constructor(Constructor<Pixel, uint8_t, uint8_t, uint8_t>(), Arg("red"), Arg("green"), Arg("blue")).
1000
+ define_attr("rgb", &Pixel::rgb);
1001
+
1002
+ std::string code = R"(pixel = Pixel.new(0xFFFFFF)
1003
+ pixel.rgb)";
1004
+
1005
+ Object result = m.module_eval(code);
1006
+ ASSERT_EQUAL(0xFFFFFFull, detail::From_Ruby<size_t>().convert(result.value()));
1007
+
1008
+ code = R"(pixel = Pixel.new(128, 128, 128)
1009
+ pixel.rgb)";
1010
+
1011
+ result = m.module_eval(code);
1012
+ ASSERT_EQUAL(0x808080ull, detail::From_Ruby<size_t>().convert(result.value()));
1013
+
1014
+ code = R"(pixel = Pixel.new(green: 80, red: 160, blue: 40)
1015
+ pixel.rgb)";
1016
+
1017
+ result = m.module_eval(code);
1018
+ ASSERT_EQUAL(0xA05028ull, detail::From_Ruby<size_t>().convert(result.value()));
1019
+ }
1020
+
1021
+ // ========== Signed vs Unsigned Preference Tests ==========
1022
+
1023
+ // Test: int should be preferred over unsigned int for Ruby Integer
1024
+ TESTCASE(SignedPreferredOverUnsigned_Int)
1025
+ {
1026
+ Module m = define_module("Testing");
1027
+
1028
+ define_global_function<std::string(*)(int)>("run", &run);
1029
+ define_global_function<std::string(*)(unsigned int)>("run", &run);
1030
+
1031
+ std::string code = R"(run(42))";
1032
+ String result = m.module_eval(code);
1033
+ ASSERT_EQUAL("run<int>", result.str());
1034
+ }
1035
+
1036
+ // Test: short should be preferred over unsigned short for Ruby Integer
1037
+ TESTCASE(SignedPreferredOverUnsigned_Short)
1038
+ {
1039
+ Module m = define_module("Testing");
1040
+
1041
+ define_global_function<std::string(*)(short)>("run", &run);
1042
+ define_global_function<std::string(*)(unsigned short)>("run", &run);
1043
+
1044
+ std::string code = R"(run(42))";
1045
+ String result = m.module_eval(code);
1046
+ ASSERT_EQUAL("run<short>", result.str());
1047
+ }
1048
+
1049
+ // Test: long long should be preferred over unsigned long long for Ruby Integer
1050
+ TESTCASE(SignedPreferredOverUnsigned_LongLong)
1051
+ {
1052
+ Module m = define_module("Testing");
1053
+
1054
+ define_global_function<std::string(*)(long long)>("run", &run);
1055
+ define_global_function<std::string(*)(unsigned long long)>("run", &run);
1056
+
1057
+ std::string code = R"(run(42))";
1058
+ String result = m.module_eval(code);
1059
+ ASSERT_EQUAL("run<long long>", result.str());
1060
+ }
1061
+
1062
+ // Test: int should be preferred over float for Ruby Integer
1063
+ TESTCASE(IntPreferredOverFloat_ForInteger)
1064
+ {
1065
+ Module m = define_module("Testing");
1066
+
1067
+ define_global_function<std::string(*)(int)>("run", &run);
1068
+ define_global_function<std::string(*)(float)>("run", &run);
1069
+
1070
+ std::string code = R"(run(42))";
1071
+ String result = m.module_eval(code);
1072
+ ASSERT_EQUAL("run<int>", result.str());
1073
+ }
1074
+
1075
+ // Test: float should be preferred over int for Ruby Float
1076
+ TESTCASE(FloatPreferredOverInt_ForFloat)
1077
+ {
1078
+ Module m = define_module("Testing");
1079
+
1080
+ define_global_function<std::string(*)(int)>("run", &run);
1081
+ define_global_function<std::string(*)(float)>("run", &run);
1082
+
1083
+ std::string code = R"(run(3.14))";
1084
+ String result = m.module_eval(code);
1085
+ ASSERT_EQUAL("run<float>", result.str());
1086
+ }
1087
+
1088
+ // Test: unsigned int should be preferred over float for Ruby Integer (integers prefer integer types)
1089
+ TESTCASE(UnsignedIntPreferredOverFloat_ForInteger)
1090
+ {
1091
+ Module m = define_module("Testing");
1092
+
1093
+ define_global_function<std::string(*)(unsigned int)>("run", &run);
1094
+ define_global_function<std::string(*)(float)>("run", &run);
1095
+
1096
+ std::string code = R"(run(42))";
1097
+ String result = m.module_eval(code);
1098
+ ASSERT_EQUAL("run<unsigned int>", result.str());
1099
+ }
1100
+
1101
+ // Test: double should be preferred over float for Ruby Float
1102
+ TESTCASE(DoublePreferredOverFloat_ForFloat)
1103
+ {
1104
+ Module m = define_module("Testing");
1105
+
1106
+ define_global_function<std::string(*)(double)>("run", &run);
1107
+ define_global_function<std::string(*)(float)>("run", &run);
1108
+
1109
+ std::string code = R"(run(3.14))";
1110
+ String result = m.module_eval(code);
1111
+ ASSERT_EQUAL("run<double>", result.str());
1112
+ }
1113
+
1114
+ // Test: long long should be preferred over double for Ruby Integer
1115
+ TESTCASE(LongLongPreferredOverDouble_ForInteger)
1116
+ {
1117
+ Module m = define_module("Testing");
1118
+
1119
+ define_global_function<std::string(*)(long long)>("run", &run);
1120
+ define_global_function<std::string(*)(double)>("run", &run);
1121
+
1122
+ std::string code = R"(run(42))";
1123
+ String result = m.module_eval(code);
1124
+ ASSERT_EQUAL("run<long long>", result.str());
1125
+ }
1126
+
1127
+ // Test: double should be preferred over long long for Ruby Float
1128
+ TESTCASE(DoublePreferredOverLongLong_ForFloat)
1129
+ {
1130
+ Module m = define_module("Testing");
1131
+
1132
+ define_global_function<std::string(*)(long long)>("run", &run);
1133
+ define_global_function<std::string(*)(double)>("run", &run);
1134
+
1135
+ std::string code = R"(run(3.14))";
1136
+ String result = m.module_eval(code);
1137
+ ASSERT_EQUAL("run<double>", result.str());
1138
+ }
1139
+
1140
+ // Test: unsigned long long should be preferred over double for Ruby Integer (integers prefer integer types)
1141
+ TESTCASE(UnsignedLongLongPreferredOverDouble_ForInteger)
1142
+ {
1143
+ Module m = define_module("Testing");
1144
+
1145
+ define_global_function<std::string(*)(unsigned long long)>("run", &run);
1146
+ define_global_function<std::string(*)(double)>("run", &run);
1147
+
1148
+ std::string code = R"(run(42))";
1149
+ String result = m.module_eval(code);
1150
+ ASSERT_EQUAL("run<unsigned long long>", result.str());
1151
+ }
data/test/test_Proc.cpp CHANGED
@@ -20,11 +20,24 @@ TEARDOWN(Proc)
20
20
 
21
21
  namespace
22
22
  {
23
+ int squareWithBlock(int i)
24
+ {
25
+ VALUE result = detail::protect(rb_yield, detail::To_Ruby<int>().convert(i));
26
+ return detail::From_Ruby<int>().convert(result);
27
+ }
28
+
29
+ int squareWithProc(int i, VALUE proc)
30
+ {
31
+ VALUE result = detail::protect(rb_funcall, proc, rb_intern("call"), 1, detail::To_Ruby<int>().convert(i));
32
+ return detail::From_Ruby<int>().convert(result);
33
+ }
34
+
23
35
  int square(int i)
24
36
  {
25
37
  return i * i;
26
38
  }
27
39
 
40
+ // Returns a function pointer that Ruby wraps in NativeProc
28
41
  auto squareProc()
29
42
  {
30
43
  return square;
@@ -42,3 +55,44 @@ TESTCASE(SquareProc)
42
55
  Object result = m.module_eval(code);
43
56
  ASSERT_EQUAL(81, detail::From_Ruby<int>().convert(result));
44
57
  }
58
+
59
+ TESTCASE(SquareWithBlock)
60
+ {
61
+ Module m = define_module("TestingModuleMakeBlock");
62
+ m.define_module_function("square_with_block", squareWithBlock);
63
+
64
+ std::string code = R"(square_with_block(7) do |i|
65
+ i * i
66
+ end)";
67
+
68
+ Object result = m.module_eval(code);
69
+ ASSERT_EQUAL(49, detail::From_Ruby<int>().convert(result));
70
+ }
71
+
72
+ TESTCASE(SquareWithCapturedBlock)
73
+ {
74
+ Module m = define_module("TestingModuleMakeBlock");
75
+ m.define_module_function("square_with_captured_block", squareWithProc, Arg("i"), Arg("proc").setBlock());
76
+
77
+ std::string code = R"(square_with_captured_block(4) do |i|
78
+ i * i
79
+ end)";
80
+
81
+ Object result = m.module_eval(code);
82
+ ASSERT_EQUAL(16, detail::From_Ruby<int>().convert(result));
83
+ }
84
+
85
+ TESTCASE(SquareWithProc)
86
+ {
87
+ Module m = define_module("TestingModuleMakeBlock");
88
+ m.define_module_function("square_with_proc", squareWithProc, Arg("i"), Arg("proc").setBlock());
89
+
90
+ std::string code = R"(proc = Proc.new do |i|
91
+ i * i
92
+ end
93
+ square_with_proc(4, proc))";
94
+
95
+ Object result = m.module_eval(code);
96
+ ASSERT_EQUAL(16, detail::From_Ruby<int>().convert(result));
97
+ }
98
+