rice 4.3.3 → 4.6.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 (237) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +86 -26
  3. data/CMakeLists.txt +31 -0
  4. data/CMakePresets.json +75 -0
  5. data/COPYING +3 -2
  6. data/FindRuby.cmake +437 -0
  7. data/README.md +7 -2
  8. data/Rakefile +12 -5
  9. data/include/rice/rice.hpp +9522 -4426
  10. data/include/rice/stl.hpp +2831 -1198
  11. data/lib/make_rice_headers.rb +79 -0
  12. data/lib/mkmf-rice.rb +40 -94
  13. data/lib/rice/version.rb +3 -0
  14. data/lib/rice.rb +1 -0
  15. data/lib/rubygems/builder.rb +11 -0
  16. data/lib/rubygems/cmake_builder.rb +113 -0
  17. data/lib/rubygems_plugin.rb +9 -0
  18. data/rice/Address_Registration_Guard.hpp +72 -3
  19. data/rice/Arg.hpp +26 -6
  20. data/rice/Arg.ipp +35 -2
  21. data/rice/Buffer.hpp +123 -0
  22. data/rice/Buffer.ipp +599 -0
  23. data/rice/Callback.hpp +21 -0
  24. data/rice/Callback.ipp +13 -0
  25. data/rice/Constructor.hpp +4 -27
  26. data/rice/Constructor.ipp +79 -0
  27. data/rice/Data_Object.hpp +73 -3
  28. data/rice/Data_Object.ipp +388 -96
  29. data/rice/Data_Type.hpp +214 -3
  30. data/rice/Data_Type.ipp +144 -67
  31. data/rice/Director.hpp +0 -2
  32. data/rice/Enum.hpp +4 -7
  33. data/rice/Enum.ipp +102 -55
  34. data/rice/Exception.hpp +62 -2
  35. data/rice/Exception.ipp +7 -12
  36. data/rice/Init.hpp +8 -0
  37. data/rice/Init.ipp +8 -0
  38. data/rice/JumpException.hpp +44 -0
  39. data/rice/JumpException.ipp +48 -0
  40. data/rice/MemoryView.hpp +11 -0
  41. data/rice/MemoryView.ipp +3 -0
  42. data/rice/Return.hpp +7 -27
  43. data/rice/Return.ipp +13 -13
  44. data/rice/cpp_api/Array.hpp +209 -0
  45. data/rice/cpp_api/Array.ipp +304 -0
  46. data/rice/cpp_api/Builtin_Object.hpp +31 -0
  47. data/rice/cpp_api/Builtin_Object.ipp +37 -0
  48. data/rice/cpp_api/Class.hpp +70 -0
  49. data/rice/cpp_api/Class.ipp +97 -0
  50. data/rice/cpp_api/Encoding.hpp +32 -0
  51. data/rice/cpp_api/Encoding.ipp +59 -0
  52. data/rice/cpp_api/Hash.hpp +194 -0
  53. data/rice/cpp_api/Hash.ipp +257 -0
  54. data/rice/{Identifier.hpp → cpp_api/Identifier.hpp} +2 -6
  55. data/rice/{Identifier.ipp → cpp_api/Identifier.ipp} +4 -2
  56. data/rice/cpp_api/Module.hpp +72 -0
  57. data/rice/cpp_api/Module.ipp +101 -0
  58. data/rice/cpp_api/Object.hpp +272 -0
  59. data/rice/cpp_api/Object.ipp +235 -0
  60. data/rice/cpp_api/String.hpp +74 -0
  61. data/rice/cpp_api/String.ipp +120 -0
  62. data/rice/cpp_api/Struct.hpp +113 -0
  63. data/rice/cpp_api/Struct.ipp +92 -0
  64. data/rice/cpp_api/Symbol.hpp +46 -0
  65. data/rice/cpp_api/Symbol.ipp +93 -0
  66. data/rice/cpp_api/shared_methods.hpp +134 -0
  67. data/rice/detail/DefaultHandler.hpp +12 -0
  68. data/rice/detail/DefaultHandler.ipp +8 -0
  69. data/rice/detail/HandlerRegistry.hpp +5 -35
  70. data/rice/detail/HandlerRegistry.ipp +7 -11
  71. data/rice/detail/InstanceRegistry.hpp +1 -4
  72. data/rice/detail/MethodInfo.hpp +12 -10
  73. data/rice/detail/MethodInfo.ipp +26 -21
  74. data/rice/detail/Native.hpp +33 -0
  75. data/rice/detail/Native.ipp +157 -0
  76. data/rice/detail/NativeAttributeGet.hpp +52 -0
  77. data/rice/detail/NativeAttributeGet.ipp +57 -0
  78. data/rice/detail/NativeAttributeSet.hpp +44 -0
  79. data/rice/detail/NativeAttributeSet.ipp +88 -0
  80. data/rice/detail/NativeCallbackFFI.hpp +55 -0
  81. data/rice/detail/NativeCallbackFFI.ipp +151 -0
  82. data/rice/detail/NativeCallbackSimple.hpp +30 -0
  83. data/rice/detail/NativeCallbackSimple.ipp +29 -0
  84. data/rice/detail/NativeFunction.hpp +33 -23
  85. data/rice/detail/NativeFunction.ipp +309 -70
  86. data/rice/detail/NativeIterator.hpp +9 -11
  87. data/rice/detail/NativeIterator.ipp +33 -31
  88. data/rice/detail/NativeRegistry.hpp +24 -15
  89. data/rice/detail/NativeRegistry.ipp +23 -48
  90. data/rice/detail/Proc.hpp +4 -0
  91. data/rice/detail/Proc.ipp +85 -0
  92. data/rice/detail/Registries.hpp +0 -7
  93. data/rice/detail/Registries.ipp +0 -18
  94. data/rice/detail/RubyFunction.hpp +0 -3
  95. data/rice/detail/RubyFunction.ipp +4 -8
  96. data/rice/detail/RubyType.hpp +16 -0
  97. data/rice/detail/RubyType.ipp +232 -0
  98. data/rice/detail/Type.hpp +7 -6
  99. data/rice/detail/Type.ipp +192 -45
  100. data/rice/detail/TypeRegistry.hpp +15 -7
  101. data/rice/detail/TypeRegistry.ipp +105 -12
  102. data/rice/detail/Wrapper.hpp +68 -32
  103. data/rice/detail/Wrapper.ipp +121 -109
  104. data/rice/detail/cpp_protect.hpp +5 -6
  105. data/rice/detail/default_allocation_func.ipp +0 -2
  106. data/rice/detail/from_ruby.hpp +38 -3
  107. data/rice/detail/from_ruby.ipp +1321 -492
  108. data/rice/detail/ruby.hpp +18 -0
  109. data/rice/detail/to_ruby.hpp +41 -3
  110. data/rice/detail/to_ruby.ipp +1424 -194
  111. data/rice/global_function.hpp +0 -4
  112. data/rice/global_function.ipp +0 -1
  113. data/rice/libc/file.hpp +11 -0
  114. data/rice/libc/file.ipp +32 -0
  115. data/rice/rice.hpp +116 -26
  116. data/rice/ruby_mark.hpp +4 -3
  117. data/rice/stl/complex.hpp +6 -0
  118. data/rice/stl/complex.ipp +93 -0
  119. data/rice/stl/exception.hpp +11 -0
  120. data/rice/stl/exception.ipp +29 -0
  121. data/rice/stl/exception_ptr.hpp +6 -0
  122. data/rice/stl/exception_ptr.ipp +27 -0
  123. data/rice/stl/map.hpp +12 -0
  124. data/rice/stl/map.ipp +469 -0
  125. data/rice/stl/monostate.hpp +6 -0
  126. data/rice/stl/monostate.ipp +80 -0
  127. data/rice/stl/multimap.hpp +14 -0
  128. data/rice/stl/multimap.ipp +448 -0
  129. data/rice/stl/optional.hpp +6 -0
  130. data/rice/stl/optional.ipp +118 -0
  131. data/rice/stl/pair.hpp +13 -0
  132. data/rice/stl/pair.ipp +155 -0
  133. data/rice/stl/reference_wrapper.hpp +6 -0
  134. data/rice/stl/reference_wrapper.ipp +41 -0
  135. data/rice/stl/set.hpp +12 -0
  136. data/rice/stl/set.ipp +495 -0
  137. data/rice/stl/shared_ptr.hpp +28 -0
  138. data/rice/stl/shared_ptr.ipp +224 -0
  139. data/rice/stl/string.hpp +6 -0
  140. data/rice/stl/string.ipp +158 -0
  141. data/rice/stl/string_view.hpp +6 -0
  142. data/rice/stl/string_view.ipp +65 -0
  143. data/rice/stl/tuple.hpp +6 -0
  144. data/rice/stl/tuple.ipp +128 -0
  145. data/rice/stl/type_index.hpp +6 -0
  146. data/rice/stl/type_index.ipp +30 -0
  147. data/rice/stl/type_info.hpp +6 -0
  148. data/rice/stl/type_info.ipp +29 -0
  149. data/rice/stl/unique_ptr.hpp +22 -0
  150. data/rice/stl/unique_ptr.ipp +139 -0
  151. data/rice/stl/unordered_map.hpp +12 -0
  152. data/rice/stl/unordered_map.ipp +469 -0
  153. data/rice/stl/variant.hpp +6 -0
  154. data/rice/stl/variant.ipp +242 -0
  155. data/rice/stl/vector.hpp +12 -0
  156. data/rice/stl/vector.ipp +590 -0
  157. data/rice/stl.hpp +11 -3
  158. data/rice/traits/attribute_traits.hpp +26 -0
  159. data/rice/traits/function_traits.hpp +95 -0
  160. data/rice/traits/method_traits.hpp +47 -0
  161. data/rice/traits/rice_traits.hpp +160 -0
  162. data/rice.gemspec +85 -0
  163. data/test/embed_ruby.cpp +7 -1
  164. data/test/extconf.rb +2 -0
  165. data/test/test_Address_Registration_Guard.cpp +5 -0
  166. data/test/test_Array.cpp +18 -4
  167. data/test/test_Attribute.cpp +136 -21
  168. data/test/test_Buffer.cpp +285 -0
  169. data/test/test_Builtin_Object.cpp +5 -0
  170. data/test/test_Callback.cpp +230 -0
  171. data/test/test_Class.cpp +5 -31
  172. data/test/test_Constructor.cpp +69 -6
  173. data/test/test_Data_Object.cpp +97 -38
  174. data/test/test_Data_Type.cpp +470 -65
  175. data/test/test_Director.cpp +17 -8
  176. data/test/test_Enum.cpp +155 -40
  177. data/test/test_Exception.cpp +235 -0
  178. data/test/test_File.cpp +70 -0
  179. data/test/test_From_Ruby.cpp +609 -0
  180. data/test/test_Hash.cpp +5 -0
  181. data/test/test_Identifier.cpp +5 -0
  182. data/test/test_Inheritance.cpp +6 -1
  183. data/test/test_Iterator.cpp +6 -1
  184. data/test/test_Jump_Exception.cpp +23 -0
  185. data/test/test_Keep_Alive.cpp +13 -19
  186. data/test/test_Keep_Alive_No_Wrapper.cpp +5 -1
  187. data/test/test_Memory_Management.cpp +5 -0
  188. data/test/test_Module.cpp +128 -67
  189. data/test/test_Native_Registry.cpp +2 -34
  190. data/test/test_Object.cpp +5 -0
  191. data/test/test_Overloads.cpp +806 -0
  192. data/test/test_Ownership.cpp +160 -54
  193. data/test/test_Proc.cpp +44 -0
  194. data/test/test_Self.cpp +9 -4
  195. data/test/test_Stl_Exception.cpp +109 -0
  196. data/test/test_Stl_Map.cpp +54 -42
  197. data/test/test_Stl_Multimap.cpp +693 -0
  198. data/test/test_Stl_Optional.cpp +5 -0
  199. data/test/test_Stl_Pair.cpp +14 -9
  200. data/test/test_Stl_Reference_Wrapper.cpp +9 -2
  201. data/test/test_Stl_Set.cpp +790 -0
  202. data/test/test_Stl_SharedPtr.cpp +458 -0
  203. data/test/test_Stl_String.cpp +5 -0
  204. data/test/test_Stl_String_View.cpp +5 -0
  205. data/test/test_Stl_Tuple.cpp +116 -0
  206. data/test/test_Stl_Type.cpp +147 -0
  207. data/test/test_Stl_UniquePtr.cpp +202 -0
  208. data/test/test_Stl_Unordered_Map.cpp +43 -38
  209. data/test/test_Stl_Variant.cpp +217 -84
  210. data/test/test_Stl_Vector.cpp +306 -58
  211. data/test/test_String.cpp +5 -0
  212. data/test/test_Struct.cpp +5 -0
  213. data/test/test_Symbol.cpp +5 -0
  214. data/test/test_Template.cpp +192 -0
  215. data/test/test_To_Ruby.cpp +524 -0
  216. data/test/test_Tracking.cpp +1 -0
  217. data/test/test_Type.cpp +171 -0
  218. data/test/test_global_functions.cpp +67 -7
  219. data/test/unittest.cpp +8 -0
  220. metadata +127 -26
  221. data/lib/version.rb +0 -3
  222. data/rice/Address_Registration_Guard_defn.hpp +0 -79
  223. data/rice/Data_Object_defn.hpp +0 -84
  224. data/rice/Data_Type_defn.hpp +0 -190
  225. data/rice/Exception_defn.hpp +0 -68
  226. data/rice/HandlerRegistration.hpp +0 -15
  227. data/rice/detail/ExceptionHandler.hpp +0 -8
  228. data/rice/detail/ExceptionHandler.ipp +0 -28
  229. data/rice/detail/ExceptionHandler_defn.hpp +0 -77
  230. data/rice/detail/Jump_Tag.hpp +0 -21
  231. data/rice/detail/NativeAttribute.hpp +0 -64
  232. data/rice/detail/NativeAttribute.ipp +0 -112
  233. data/rice/detail/from_ruby_defn.hpp +0 -38
  234. data/rice/detail/to_ruby_defn.hpp +0 -48
  235. data/test/test_Jump_Tag.cpp +0 -17
  236. data/test/test_Stl_SmartPointer.cpp +0 -283
  237. data/test/test_To_From_Ruby.cpp +0 -399
@@ -0,0 +1,79 @@
1
+ require 'stringio'
2
+
3
+ LINE_ENDING = "\n"
4
+ RICE_INCLUDE_REGEX = %r{#include "(.*)"}
5
+ OTHER_INCLUDE_REGEX = %r{#include <(.*)>}
6
+
7
+ RICE_HEADER_GUARD_1 = %r{#ifndef Rice__}
8
+ RICE_HEADER_GUARD_2 = %r{#define Rice__}
9
+ RICE_HEADER_GUARD_3 = %r{#endif\s*//\s*Rice__}
10
+ SHARED_METHODS_REGEX = %r{#include "((?:cpp_api\/)?shared_methods.hpp)"}
11
+
12
+ def load_file(relative_path)
13
+ content = File.read(relative_path, mode: 'rb')
14
+
15
+ # Special case shared_methods.hpp which if requested we want to
16
+ # merge into the current file
17
+ match = content.match(SHARED_METHODS_REGEX)
18
+ if match
19
+ shared_path = File.join(File.dirname(relative_path), match[1])
20
+ content.gsub!(SHARED_METHODS_REGEX, File.read(shared_path, mode: 'rb'))
21
+ end
22
+
23
+ content
24
+ end
25
+
26
+ def strip_includes(content)
27
+ content.lines.find_all do |line|
28
+ !line.match(RICE_INCLUDE_REGEX)
29
+ end.join
30
+ end
31
+
32
+ def add_include(path, stream)
33
+ basename = File.basename(path)
34
+ basename_no_ext = File.basename(path, ".*")
35
+
36
+ stream << "\n" << "// ========= #{File.basename(path)} =========" << "\n"
37
+
38
+ load_file(path).each_line do |line|
39
+ if match = line.match(RICE_INCLUDE_REGEX)
40
+ # Check for related includes, ie., Object.hpp, Object_defn.hpp and Object.ipp
41
+ sub_include = File.basename(match[1])
42
+ if ["#{basename_no_ext}_defn.hpp", "#{basename_no_ext}.ipp"].include?(sub_include)
43
+ sub_include_path = File.join(File.dirname(path), match[1])
44
+ stream << "\n" << "// --------- #{File.basename(sub_include_path)} ---------" << "\n"
45
+ stream << strip_includes(load_file(sub_include_path))
46
+ end
47
+ elsif line.match(RICE_HEADER_GUARD_1) || line.match(RICE_HEADER_GUARD_2) || line.match(RICE_HEADER_GUARD_3)
48
+ # Skip the header guard
49
+ else
50
+ # Include the line in the output
51
+ stream << line
52
+ end
53
+ end
54
+ end
55
+
56
+ def combine_headers(filename)
57
+ stream = StringIO.new
58
+
59
+ load_file("rice/#{filename}").each_line do |line|
60
+ if matches = line.match(RICE_INCLUDE_REGEX)
61
+ path = File.join("rice", matches[1])
62
+ add_include(path, stream)
63
+ else
64
+ stream << line
65
+ end
66
+ end
67
+
68
+ File.open("include/rice/#{filename}", 'wb') do |file|
69
+ file << stream.string
70
+ end
71
+ end
72
+
73
+ puts "Building rice.hpp"
74
+ combine_headers('rice.hpp')
75
+
76
+ puts "Building stl.hpp"
77
+ combine_headers('stl.hpp')
78
+
79
+ puts "Success"
data/lib/mkmf-rice.rb CHANGED
@@ -1,93 +1,12 @@
1
1
  require 'mkmf'
2
+ require 'rice/version'
2
3
 
3
- IS_MSWIN = !RbConfig::CONFIG['host_os'].match(/mswin/).nil?
4
- IS_MINGW = !RbConfig::CONFIG['host_os'].match(/mingw/).nil?
5
- IS_DARWIN = !RbConfig::CONFIG['host_os'].match(/darwin/).nil?
4
+ major, minor, patch = Rice::VERSION.split(".")
5
+ $CXXFLAGS += " -DRICE_VERSION_MAJOR=#{major} -DRICE_VERSION_MINOR=#{minor} -DRICE_VERSION_PATCH=#{patch}"
6
6
 
7
- # If we are on versions of Ruby before 2.7 then we need to copy in the experimental C++ support
8
- # added in Ruby 2.7
9
- unless MakeMakefile.methods.include?(:[])
10
-
11
- # Ruby 2.6 makes this declaration which is not valid with C++17
12
- # void rb_mem_clear(register VALUE*, register long);
13
- if !IS_MSWIN
14
- $CXXFLAGS += " " << "-Wno-register"
15
- end
16
-
17
- MakeMakefile::CONFTEST_C = "#{CONFTEST}.cc"
18
-
19
- MakeMakefile.module_eval do
20
- CONFTEST_C = "#{CONFTEST}.cc"
21
- def cc_config(opt="")
22
- conf = RbConfig::CONFIG.merge('hdrdir' => $hdrdir.quote, 'srcdir' => $srcdir.quote,
23
- 'arch_hdrdir' => $arch_hdrdir.quote,
24
- 'top_srcdir' => $top_srcdir.quote)
25
- conf
26
- end
27
-
28
- def link_config(ldflags, opt="", libpath=$DEFLIBPATH|$LIBPATH)
29
- librubyarg = $extmk ? $LIBRUBYARG_STATIC : "$(LIBRUBYARG)"
30
- conf = RbConfig::CONFIG.merge('hdrdir' => $hdrdir.quote,
31
- 'src' => "#{conftest_source}",
32
- 'arch_hdrdir' => $arch_hdrdir.quote,
33
- 'top_srcdir' => $top_srcdir.quote,
34
- 'INCFLAGS' => "#$INCFLAGS",
35
- 'CPPFLAGS' => "#$CPPFLAGS",
36
- 'CFLAGS' => "#$CFLAGS",
37
- 'ARCH_FLAG' => "#$ARCH_FLAG",
38
- 'LDFLAGS' => "#$LDFLAGS #{ldflags}",
39
- 'LOCAL_LIBS' => "#$LOCAL_LIBS #$libs",
40
- 'LIBS' => "#{librubyarg} #{opt} #$LIBS")
41
- conf['LIBPATH'] = libpathflag(libpath.map {|s| RbConfig::expand(s.dup, conf)})
42
- conf
43
- end
44
-
45
- @lang = Hash.new(self)
46
-
47
- def self.[](name)
48
- @lang.fetch(name)
49
- end
50
-
51
- def self.[]=(name, mod)
52
- @lang[name] = mod
53
- end
54
-
55
- MakeMakefile["C++"] = Module.new do
56
- include MakeMakefile
57
- extend self
58
-
59
- CONFTEST_CXX = "#{CONFTEST}.#{config_string('CXX_EXT') || CXX_EXT[0]}"
60
-
61
- TRY_LINK_CXX = config_string('TRY_LINK_CXX') ||
62
- ((cmd = TRY_LINK.gsub(/\$\(C(?:C|(FLAGS))\)/, '$(CXX\1)')) != TRY_LINK && cmd) ||
63
- "$(CXX) #{OUTFLAG}#{CONFTEST}#{$EXEEXT} $(INCFLAGS) $(CPPFLAGS) " \
64
- "$(CXXFLAGS) $(src) $(LIBPATH) $(LDFLAGS) $(ARCH_FLAG) $(LOCAL_LIBS) $(LIBS)"
65
-
66
- def have_devel?
67
- unless defined? @have_devel
68
- @have_devel = true
69
- @have_devel = try_link(MAIN_DOES_NOTHING)
70
- end
71
- @have_devel
72
- end
73
-
74
- def conftest_source
75
- CONFTEST_CXX
76
- end
77
-
78
- def cc_command(opt="")
79
- conf = cc_config(opt)
80
- RbConfig::expand("$(CXX) #$INCFLAGS #$CPPFLAGS #$CXXFLAGS #$ARCH_FLAG #{opt} -c #{CONFTEST_CXX}",
81
- conf)
82
- end
83
-
84
- def link_command(ldflags, *opts)
85
- conf = link_config(ldflags, *opts)
86
- RbConfig::expand(TRY_LINK_CXX.dup, conf)
87
- end
88
- end
89
- end
90
- end
7
+ IS_MSWIN = /mswin/ =~ RUBY_PLATFORM
8
+ IS_MINGW = /mingw/ =~ RUBY_PLATFORM
9
+ IS_DARWIN = RbConfig::CONFIG['host_os'].match?(/darwin/)
91
10
 
92
11
  # The cpp_command is not overwritten in the experimental mkmf C++ support.
93
12
  # See https://bugs.ruby-lang.org/issues/17578
@@ -107,7 +26,7 @@ include MakeMakefile['C++']
107
26
 
108
27
  # Rice needs c++17.
109
28
  if IS_MSWIN
110
- $CXXFLAGS += " /std:c++17 /EHsc /permissive- /bigobj"
29
+ $CXXFLAGS += " /std:c++17 /EHs /permissive- /bigobj /utf-8"
111
30
  $CPPFLAGS += " -D_ALLOW_KEYWORD_MACROS -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE"
112
31
  elsif IS_MINGW
113
32
  $CXXFLAGS += " -std=c++17 -Wa,-mbig-obj"
@@ -123,10 +42,37 @@ unless find_header('rice/rice.hpp', path)
123
42
  raise("Could not find rice/rice.hpp header")
124
43
  end
125
44
 
126
- if IS_DARWIN
127
- have_library('c++')
128
- elsif !IS_MSWIN
129
- if !have_library('stdc++fs')
130
- have_library('stdc++')
45
+ if !IS_DARWIN && !IS_MSWIN && !have_library('stdc++fs')
46
+ have_library('stdc++')
47
+ end
48
+
49
+ # Copied from Ruby FFI bindings - see
50
+ # https://github.com/ffi/ffi/blob/1715332d553d53fae13fd9fcbbd9d2c1982a5c2f/ext/ffi_c/extconf.rb#L7C1-L27C6
51
+ def system_libffi_usable?
52
+ # We need pkg_config or ffi.h
53
+ libffi_ok = pkg_config("libffi") ||
54
+ have_header("ffi.h") ||
55
+ find_header("ffi.h", "/usr/local/include", "/usr/include/ffi",
56
+ "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/ffi",
57
+ "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/ffi") ||
58
+ (find_header("ffi.h", `xcrun --sdk macosx --show-sdk-path`.strip + "/usr/include/ffi") rescue false)
59
+
60
+ # Ensure we can link to ffi_prep_closure_loc
61
+ libffi_ok &&= have_library("ffi", "ffi_prep_closure_loc", [ "ffi.h" ]) ||
62
+ have_library("libffi", "ffi_prep_closure_loc", [ "ffi.h" ]) ||
63
+ have_library("libffi-8", "ffi_prep_closure_loc", [ "ffi.h" ])
64
+
65
+ if RbConfig::CONFIG['host_os'] =~ /mswin/
66
+ have_library('libffi_convenience')
67
+ have_library('shlwapi')
131
68
  end
132
- end
69
+
70
+ libffi_ok
71
+ end
72
+
73
+ def have_libffi
74
+ # Check for libffi to support C style callacks.
75
+ libffi_usable = system_libffi_usable?
76
+ $CPPFLAGS += " -DHAVE_LIBFFI" if libffi_usable
77
+ libffi_usable
78
+ end
@@ -0,0 +1,3 @@
1
+ module Rice
2
+ VERSION = "4.6.0"
3
+ end
data/lib/rice.rb ADDED
@@ -0,0 +1 @@
1
+ require_relative "rice/version"
@@ -0,0 +1,11 @@
1
+ class Gem::Ext::Builder
2
+ alias :builder_for_original :builder_for
3
+ def builder_for(extension)
4
+ case extension
5
+ when /CMakeLists.txt/ then
6
+ Gem::Ext::CmakeBuilder.new
7
+ else
8
+ builder_for_original(extension)
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,113 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This builder creates extensions defined using CMake. Its is invoked if a Gem's spec file
4
+ # sets the `extension` property to a string that contains `CMakeLists.txt`.
5
+ #
6
+ # In general, CMake projects are built in two steps:
7
+ #
8
+ # * configure
9
+ # * build
10
+ #
11
+ # The builder follow this convention. First it runs a configuration step and then it runs a build step.
12
+ #
13
+ # CMake projects can be quite configurable - it is likely you will want to specify options when
14
+ # installing a gem. To pass options to CMake specify them after `--` in the gem install command. For example:
15
+ #
16
+ # gem install <gem_name> -- --preset <preset_name>
17
+ #
18
+ # Note that options are ONLY sent to the configure step - it is not currently possible to specify
19
+ # options for the build step. If this becomes and issue then the CMake builder can be updated to
20
+ # support build options.
21
+ #
22
+ # Useful options to know are:
23
+ #
24
+ # -G to specify a generator (-G Ninja is recommended)
25
+ # -D<CMAKE_VARIABLE> to set a CMake variable (for example -DCMAKE_BUILD_TYPE=Release)
26
+ # --preset <preset_name> to use a preset
27
+ #
28
+ # If the Gem author provides presets, via CMakePresets.json file, you will likely want to us use one of them.
29
+ # If not, then you may wish to specify a generator (Ninja is recommended since it can build projects in parallel
30
+ # versus a Make generator which build ins serial and thus is *much* slower).
31
+
32
+ require "fileutils"
33
+
34
+ class Gem::Ext::CmakeBuilder
35
+ attr_accessor :runner, :profile
36
+
37
+ def initialize
38
+ @runner = self.class.method(:run)
39
+ @profile = :release
40
+ end
41
+
42
+ def build(extension, gem_dir, results, args = [], lib_dir = nil, cmake_dir = Dir.pwd, target_rbconfig = Gem.target_rbconfig)
43
+ if target_rbconfig.path
44
+ warn "--target-rbconfig is not yet supported for CMake extensions. Ignoring"
45
+ end
46
+
47
+ # Make sure lib dir is set
48
+ lib_dir ||= File.join(gem_dir, "lib")
49
+
50
+ # Figure the build dir
51
+ build_dir = File.join(cmake_dir, "build")
52
+
53
+ # Check if the gem defined presets
54
+ check_presets(cmake_dir, args)
55
+
56
+ # Configure
57
+ configure(cmake_dir, build_dir, lib_dir, args, results)
58
+
59
+ # Compile
60
+ compile(cmake_dir, build_dir, args, results)
61
+
62
+ results
63
+ end
64
+
65
+ def configure(cmake_dir, build_dir, lib_dir, args, results)
66
+ cmd = ["cmake",
67
+ cmake_dir,
68
+ "-B #{build_dir}",
69
+ "-DCMAKE_RUNTIME_OUTPUT_DIRECTORY=#{lib_dir}", # Windows
70
+ "-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=#{lib_dir}", # Not Windows
71
+ *Gem::Command.build_args,
72
+ *args]
73
+
74
+ runner.call(cmd, results, "cmake", cmake_dir)
75
+ end
76
+
77
+ def compile(cmake_dir, build_dir, args, results)
78
+ cmd = ["cmake",
79
+ "--build",
80
+ build_dir.to_s,
81
+ "--config",
82
+ @profile.to_s]
83
+ runner.call(cmd, results, "cmake", cmake_dir)
84
+ end
85
+
86
+ private
87
+
88
+ def check_presets(cmake_dir, args)
89
+ # Return if the user specified a preset
90
+ return unless args.grep(/--preset/i).empty?
91
+
92
+ cmd = ["cmake",
93
+ "--list-presets"]
94
+
95
+ begin
96
+ require "open3"
97
+ build_env = { "SOURCE_DATE_EPOCH" => Gem.source_date_epoch_string }
98
+ stdout, _, _ = Open3.capture3(build_env, *cmd, chdir: cmake_dir)
99
+ message = <<~EOS
100
+ The gem author provided a list of presets that can be used to build the gem. To use a preset specify it on the command line:
101
+
102
+ gem install <gem_name> -- --preset <preset_name>
103
+
104
+ #{stdout}
105
+ EOS
106
+
107
+ STDOUT << message << "\n"
108
+ STDOUT.flush
109
+ rescue Gem::InstallError
110
+ # Do nothing, CMakePresets.json was not included in the Gem
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,9 @@
1
+ # Create RubyGems hook so we can replace the default CMakeBuilder with our own version
2
+ Gem.pre_install do |installer|
3
+ extensions = installer.package&.spec&.extensions
4
+ if extensions && extensions.grep(/CMakeLists/)
5
+ require_relative 'rubygems/builder'
6
+ require_relative 'rubygems/cmake_builder'
7
+ end
8
+ true
9
+ end
@@ -1,7 +1,76 @@
1
1
  #ifndef Rice__Address_Registration_Guard__hpp_
2
2
  #define Rice__Address_Registration_Guard__hpp_
3
3
 
4
- #include "Address_Registration_Guard_defn.hpp"
5
- #include "Address_Registration_Guard.ipp"
4
+ namespace Rice
5
+ {
6
+ //! A guard to register a given address with the GC.
7
+ /*! Calls rb_gc_register_address upon construction and
8
+ * rb_gc_unregister_address upon destruction.
9
+ * For example:
10
+ * \code
11
+ * Class Foo
12
+ * {
13
+ * public:
14
+ * Foo()
15
+ * : string_(rb_str_new2())
16
+ * , guard_(&string_);
17
+ *
18
+ * private:
19
+ * VALUE string_;
20
+ * Address_Registration_Guard guard_;
21
+ * };
22
+ * \endcode
23
+ */
24
+ class Address_Registration_Guard
25
+ {
26
+ public:
27
+ //! Register an address with the GC.
28
+ /* \param address The address to register with the GC. The address
29
+ * must point to a valid ruby object (RObject).
30
+ */
31
+ Address_Registration_Guard(VALUE* address);
6
32
 
7
- #endif // Rice__Address_Registration_Guard__hpp_
33
+ //! Register an Object with the GC.
34
+ /*! \param object The Object to register with the GC. The object must
35
+ * not be destroyed before the Address_Registration_Guard is
36
+ * destroyed.
37
+ */
38
+ Address_Registration_Guard(Object* object);
39
+
40
+ //! Unregister an address/Object with the GC.
41
+ /*! Destruct an Address_Registration_Guard. The address registered
42
+ * with the Address_Registration_Guard when it was constructed will
43
+ * be unregistered from the GC.
44
+ */
45
+ ~Address_Registration_Guard();
46
+
47
+ // Disable copying
48
+ Address_Registration_Guard(Address_Registration_Guard const& other) = delete;
49
+ Address_Registration_Guard& operator=(Address_Registration_Guard const& other) = delete;
50
+
51
+ // Enable moving
52
+ Address_Registration_Guard(Address_Registration_Guard&& other);
53
+ Address_Registration_Guard& operator=(Address_Registration_Guard&& other);
54
+
55
+ //! Get the address that is registered with the GC.
56
+ VALUE* address() const;
57
+
58
+ /** Called during Ruby's exit process since we should not call
59
+ * rb_gc unregister_address there
60
+ */
61
+ static void disable();
62
+
63
+ private:
64
+ inline static bool enabled = true;
65
+ inline static bool exit_handler_registered = false;
66
+ static void registerExitHandler();
67
+
68
+ private:
69
+ void registerAddress() const;
70
+ void unregisterAddress();
71
+
72
+ VALUE* address_ = nullptr;
73
+ };
74
+ } // namespace Rice
75
+
76
+ #endif // Rice__Address_Registration_Guard__hpp_
data/rice/Arg.hpp CHANGED
@@ -35,6 +35,9 @@ namespace Rice
35
35
  */
36
36
  Arg(std::string name);
37
37
 
38
+ // Make Arg polymorphic so dynamic_cast works
39
+ virtual ~Arg() = default;
40
+
38
41
  //! Set the default value for this Arg
39
42
  /*! Set the default value for this argument.
40
43
  * If this isn't called on this Arg, then this
@@ -52,23 +55,38 @@ namespace Rice
52
55
  /*! \return the type saved to this Arg
53
56
  */
54
57
  template<typename Arg_Type>
55
- Arg_Type& defaultValue();
58
+ Arg_Type defaultValue();
56
59
 
57
60
  //! Tell the receiving object to keep this argument alive
58
61
  //! until the receiving object is freed.
59
- Arg& keepAlive();
62
+ virtual Arg& keepAlive();
60
63
 
61
64
  //! Returns if the argument should be kept alive
62
65
  bool isKeepAlive() const;
63
66
 
64
67
  //! Specifies if the argument should be treated as a value
65
- Arg& setValue();
68
+ virtual Arg& setValue();
66
69
 
67
70
  //! Returns if the argument should be treated as a value
68
71
  bool isValue() const;
69
72
 
73
+ //! Specifies if the argument is opaque and Rice should not convert it from Ruby to C++ or vice versa.
74
+ //! This is useful for callbacks and user provided data paramameters.
75
+ virtual Arg& setOpaque();
76
+
77
+ //! Returns if the argument should be treated as a value
78
+ bool isOpaque() const;
79
+
80
+ //! Specifies C++ will take ownership of this value and Ruby should not free it
81
+ virtual Arg& takeOwnership();
82
+ bool isOwner();
83
+
84
+ //! Is the parameter a C style array
85
+ virtual Arg& setArray();
86
+ bool isArray();
87
+
70
88
  public:
71
- const std::string name;
89
+ std::string name;
72
90
  int32_t position = -1;
73
91
 
74
92
  private:
@@ -76,9 +94,11 @@ namespace Rice
76
94
  std::any defaultValue_;
77
95
  bool isValue_ = false;
78
96
  bool isKeepAlive_ = false;
97
+ bool isOwner_ = false;
98
+ bool isOpaque_ = false;
99
+ bool isArray_ = false;
100
+
79
101
  };
80
102
  } // Rice
81
103
 
82
- #include "Arg.ipp"
83
-
84
104
  #endif // Rice__Arg__hpp_
data/rice/Arg.ipp CHANGED
@@ -21,9 +21,9 @@ namespace Rice
21
21
  /*! \return the type saved to this Arg
22
22
  */
23
23
  template<typename Arg_Type>
24
- inline Arg_Type& Arg::defaultValue()
24
+ inline Arg_Type Arg::defaultValue()
25
25
  {
26
- return std::any_cast<Arg_Type&>(this->defaultValue_);
26
+ return std::any_cast<Arg_Type>(this->defaultValue_);
27
27
  }
28
28
 
29
29
  inline Arg& Arg::keepAlive()
@@ -47,4 +47,37 @@ namespace Rice
47
47
  {
48
48
  return isValue_;
49
49
  }
50
+
51
+ inline Arg& Arg::setOpaque()
52
+ {
53
+ isOpaque_ = true;
54
+ return *this;
55
+ }
56
+
57
+ inline bool Arg::isOpaque() const
58
+ {
59
+ return isOpaque_;
60
+ }
61
+
62
+ inline Arg& Arg::takeOwnership()
63
+ {
64
+ this->isOwner_ = true;
65
+ return *this;
66
+ }
67
+
68
+ inline bool Arg::isOwner()
69
+ {
70
+ return this->isOwner_;
71
+ }
72
+
73
+ inline Arg& Arg::setArray()
74
+ {
75
+ this->isArray_ = true;
76
+ return *this;
77
+ }
78
+
79
+ inline bool Arg::isArray()
80
+ {
81
+ return this->isArray_;
82
+ }
50
83
  } // Rice
data/rice/Buffer.hpp ADDED
@@ -0,0 +1,123 @@
1
+ #ifndef Rice__Buffer__hpp_
2
+ #define Rice__Buffer__hpp_
3
+
4
+ namespace Rice
5
+ {
6
+ template<typename T>
7
+ class Buffer
8
+ {
9
+ public:
10
+ using type = T;
11
+
12
+ Buffer(T* pointer);
13
+ Buffer(T* pointer, size_t size);
14
+ Buffer(VALUE value);
15
+
16
+ ~Buffer();
17
+
18
+ Buffer(const Buffer& other) = delete;
19
+ Buffer(Buffer&& other);
20
+
21
+ Buffer& operator=(const Buffer& other) = delete;
22
+ Buffer& operator=(Buffer&& other);
23
+
24
+ T* ptr();
25
+ T& reference();
26
+ void release();
27
+
28
+ size_t size() const;
29
+ void setSize(size_t value);
30
+
31
+ // Ruby API
32
+ // VALUE toString() const;
33
+
34
+ VALUE bytes() const;
35
+ VALUE bytes(size_t count) const;
36
+
37
+ Array toArray() const;
38
+ Array toArray(size_t count) const;
39
+
40
+ T get(size_t index) const;
41
+ void set(size_t index, T value);
42
+
43
+ bool isOwner() const;
44
+ void setOwner(bool value);
45
+
46
+ private:
47
+ void fromRubyType(VALUE value);
48
+ void fromDataType(VALUE value);
49
+
50
+ bool m_owner = false;
51
+ size_t m_size = 0;
52
+ // std::unique_ptr would be greate but std::unique_ptr<void> isn't allowed
53
+ T* m_buffer = nullptr;
54
+ };
55
+
56
+ template<typename T>
57
+ class Buffer<T*>
58
+ {
59
+ public:
60
+ using type = T*;
61
+
62
+ Buffer(T** pointer);
63
+ Buffer(T** pointer, size_t size);
64
+ Buffer(VALUE value);
65
+
66
+ ~Buffer();
67
+
68
+ Buffer(const Buffer& other) = delete;
69
+ Buffer(Buffer&& other);
70
+
71
+ Buffer& operator=(const Buffer& other) = delete;
72
+ Buffer& operator=(Buffer&& other);
73
+
74
+ const Buffer<T>& operator[](size_t index);
75
+
76
+ T** ptr();
77
+ void release();
78
+
79
+ size_t size() const;
80
+ void setSize(size_t value);
81
+
82
+ // Ruby API
83
+ // VALUE toString() const;
84
+
85
+ VALUE bytes() const;
86
+ VALUE bytes(size_t count) const;
87
+
88
+ Array toArray() const;
89
+ Array toArray(size_t count) const;
90
+
91
+ void setOwner(bool value);
92
+ bool isOwner() const;
93
+
94
+ private:
95
+ bool m_owner = false;
96
+ size_t m_size = 0;
97
+ T** m_outer = nullptr;
98
+ std::vector<Buffer<T>> m_inner;
99
+ };
100
+
101
+ template<>
102
+ class Buffer<void>
103
+ {
104
+ public:
105
+ Buffer(void* pointer);
106
+ Buffer(const Buffer& other) = delete;
107
+ Buffer(Buffer&& other);
108
+
109
+ Buffer& operator=(const Buffer& other) = delete;
110
+ Buffer& operator=(Buffer&& other);
111
+
112
+ void* ptr();
113
+
114
+ private:
115
+ void* m_buffer = nullptr;
116
+ };
117
+
118
+ template<typename T>
119
+ Data_Type<Buffer<T>> define_buffer(std::string klassName = "");
120
+
121
+ void define_fundamental_buffer_types();
122
+ }
123
+ #endif // Rice__Buffer__hpp_