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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +86 -26
- data/CMakeLists.txt +31 -0
- data/CMakePresets.json +75 -0
- data/COPYING +3 -2
- data/FindRuby.cmake +437 -0
- data/README.md +7 -2
- data/Rakefile +12 -5
- data/include/rice/rice.hpp +9522 -4426
- data/include/rice/stl.hpp +2831 -1198
- data/lib/make_rice_headers.rb +79 -0
- data/lib/mkmf-rice.rb +40 -94
- data/lib/rice/version.rb +3 -0
- data/lib/rice.rb +1 -0
- data/lib/rubygems/builder.rb +11 -0
- data/lib/rubygems/cmake_builder.rb +113 -0
- data/lib/rubygems_plugin.rb +9 -0
- data/rice/Address_Registration_Guard.hpp +72 -3
- data/rice/Arg.hpp +26 -6
- data/rice/Arg.ipp +35 -2
- data/rice/Buffer.hpp +123 -0
- data/rice/Buffer.ipp +599 -0
- data/rice/Callback.hpp +21 -0
- data/rice/Callback.ipp +13 -0
- data/rice/Constructor.hpp +4 -27
- data/rice/Constructor.ipp +79 -0
- data/rice/Data_Object.hpp +73 -3
- data/rice/Data_Object.ipp +388 -96
- data/rice/Data_Type.hpp +214 -3
- data/rice/Data_Type.ipp +144 -67
- data/rice/Director.hpp +0 -2
- data/rice/Enum.hpp +4 -7
- data/rice/Enum.ipp +102 -55
- data/rice/Exception.hpp +62 -2
- data/rice/Exception.ipp +7 -12
- data/rice/Init.hpp +8 -0
- data/rice/Init.ipp +8 -0
- data/rice/JumpException.hpp +44 -0
- data/rice/JumpException.ipp +48 -0
- data/rice/MemoryView.hpp +11 -0
- data/rice/MemoryView.ipp +3 -0
- data/rice/Return.hpp +7 -27
- data/rice/Return.ipp +13 -13
- data/rice/cpp_api/Array.hpp +209 -0
- data/rice/cpp_api/Array.ipp +304 -0
- data/rice/cpp_api/Builtin_Object.hpp +31 -0
- data/rice/cpp_api/Builtin_Object.ipp +37 -0
- data/rice/cpp_api/Class.hpp +70 -0
- data/rice/cpp_api/Class.ipp +97 -0
- data/rice/cpp_api/Encoding.hpp +32 -0
- data/rice/cpp_api/Encoding.ipp +59 -0
- data/rice/cpp_api/Hash.hpp +194 -0
- data/rice/cpp_api/Hash.ipp +257 -0
- data/rice/{Identifier.hpp → cpp_api/Identifier.hpp} +2 -6
- data/rice/{Identifier.ipp → cpp_api/Identifier.ipp} +4 -2
- data/rice/cpp_api/Module.hpp +72 -0
- data/rice/cpp_api/Module.ipp +101 -0
- data/rice/cpp_api/Object.hpp +272 -0
- data/rice/cpp_api/Object.ipp +235 -0
- data/rice/cpp_api/String.hpp +74 -0
- data/rice/cpp_api/String.ipp +120 -0
- data/rice/cpp_api/Struct.hpp +113 -0
- data/rice/cpp_api/Struct.ipp +92 -0
- data/rice/cpp_api/Symbol.hpp +46 -0
- data/rice/cpp_api/Symbol.ipp +93 -0
- data/rice/cpp_api/shared_methods.hpp +134 -0
- data/rice/detail/DefaultHandler.hpp +12 -0
- data/rice/detail/DefaultHandler.ipp +8 -0
- data/rice/detail/HandlerRegistry.hpp +5 -35
- data/rice/detail/HandlerRegistry.ipp +7 -11
- data/rice/detail/InstanceRegistry.hpp +1 -4
- data/rice/detail/MethodInfo.hpp +12 -10
- data/rice/detail/MethodInfo.ipp +26 -21
- data/rice/detail/Native.hpp +33 -0
- data/rice/detail/Native.ipp +157 -0
- data/rice/detail/NativeAttributeGet.hpp +52 -0
- data/rice/detail/NativeAttributeGet.ipp +57 -0
- data/rice/detail/NativeAttributeSet.hpp +44 -0
- data/rice/detail/NativeAttributeSet.ipp +88 -0
- data/rice/detail/NativeCallbackFFI.hpp +55 -0
- data/rice/detail/NativeCallbackFFI.ipp +151 -0
- data/rice/detail/NativeCallbackSimple.hpp +30 -0
- data/rice/detail/NativeCallbackSimple.ipp +29 -0
- data/rice/detail/NativeFunction.hpp +33 -23
- data/rice/detail/NativeFunction.ipp +309 -70
- data/rice/detail/NativeIterator.hpp +9 -11
- data/rice/detail/NativeIterator.ipp +33 -31
- data/rice/detail/NativeRegistry.hpp +24 -15
- data/rice/detail/NativeRegistry.ipp +23 -48
- data/rice/detail/Proc.hpp +4 -0
- data/rice/detail/Proc.ipp +85 -0
- data/rice/detail/Registries.hpp +0 -7
- data/rice/detail/Registries.ipp +0 -18
- data/rice/detail/RubyFunction.hpp +0 -3
- data/rice/detail/RubyFunction.ipp +4 -8
- data/rice/detail/RubyType.hpp +16 -0
- data/rice/detail/RubyType.ipp +232 -0
- data/rice/detail/Type.hpp +7 -6
- data/rice/detail/Type.ipp +192 -45
- data/rice/detail/TypeRegistry.hpp +15 -7
- data/rice/detail/TypeRegistry.ipp +105 -12
- data/rice/detail/Wrapper.hpp +68 -32
- data/rice/detail/Wrapper.ipp +121 -109
- data/rice/detail/cpp_protect.hpp +5 -6
- data/rice/detail/default_allocation_func.ipp +0 -2
- data/rice/detail/from_ruby.hpp +38 -3
- data/rice/detail/from_ruby.ipp +1321 -492
- data/rice/detail/ruby.hpp +18 -0
- data/rice/detail/to_ruby.hpp +41 -3
- data/rice/detail/to_ruby.ipp +1424 -194
- data/rice/global_function.hpp +0 -4
- data/rice/global_function.ipp +0 -1
- data/rice/libc/file.hpp +11 -0
- data/rice/libc/file.ipp +32 -0
- data/rice/rice.hpp +116 -26
- data/rice/ruby_mark.hpp +4 -3
- data/rice/stl/complex.hpp +6 -0
- data/rice/stl/complex.ipp +93 -0
- data/rice/stl/exception.hpp +11 -0
- data/rice/stl/exception.ipp +29 -0
- data/rice/stl/exception_ptr.hpp +6 -0
- data/rice/stl/exception_ptr.ipp +27 -0
- data/rice/stl/map.hpp +12 -0
- data/rice/stl/map.ipp +469 -0
- data/rice/stl/monostate.hpp +6 -0
- data/rice/stl/monostate.ipp +80 -0
- data/rice/stl/multimap.hpp +14 -0
- data/rice/stl/multimap.ipp +448 -0
- data/rice/stl/optional.hpp +6 -0
- data/rice/stl/optional.ipp +118 -0
- data/rice/stl/pair.hpp +13 -0
- data/rice/stl/pair.ipp +155 -0
- data/rice/stl/reference_wrapper.hpp +6 -0
- data/rice/stl/reference_wrapper.ipp +41 -0
- data/rice/stl/set.hpp +12 -0
- data/rice/stl/set.ipp +495 -0
- data/rice/stl/shared_ptr.hpp +28 -0
- data/rice/stl/shared_ptr.ipp +224 -0
- data/rice/stl/string.hpp +6 -0
- data/rice/stl/string.ipp +158 -0
- data/rice/stl/string_view.hpp +6 -0
- data/rice/stl/string_view.ipp +65 -0
- data/rice/stl/tuple.hpp +6 -0
- data/rice/stl/tuple.ipp +128 -0
- data/rice/stl/type_index.hpp +6 -0
- data/rice/stl/type_index.ipp +30 -0
- data/rice/stl/type_info.hpp +6 -0
- data/rice/stl/type_info.ipp +29 -0
- data/rice/stl/unique_ptr.hpp +22 -0
- data/rice/stl/unique_ptr.ipp +139 -0
- data/rice/stl/unordered_map.hpp +12 -0
- data/rice/stl/unordered_map.ipp +469 -0
- data/rice/stl/variant.hpp +6 -0
- data/rice/stl/variant.ipp +242 -0
- data/rice/stl/vector.hpp +12 -0
- data/rice/stl/vector.ipp +590 -0
- data/rice/stl.hpp +11 -3
- data/rice/traits/attribute_traits.hpp +26 -0
- data/rice/traits/function_traits.hpp +95 -0
- data/rice/traits/method_traits.hpp +47 -0
- data/rice/traits/rice_traits.hpp +160 -0
- data/rice.gemspec +85 -0
- data/test/embed_ruby.cpp +7 -1
- data/test/extconf.rb +2 -0
- data/test/test_Address_Registration_Guard.cpp +5 -0
- data/test/test_Array.cpp +18 -4
- data/test/test_Attribute.cpp +136 -21
- data/test/test_Buffer.cpp +285 -0
- data/test/test_Builtin_Object.cpp +5 -0
- data/test/test_Callback.cpp +230 -0
- data/test/test_Class.cpp +5 -31
- data/test/test_Constructor.cpp +69 -6
- data/test/test_Data_Object.cpp +97 -38
- data/test/test_Data_Type.cpp +470 -65
- data/test/test_Director.cpp +17 -8
- data/test/test_Enum.cpp +155 -40
- data/test/test_Exception.cpp +235 -0
- data/test/test_File.cpp +70 -0
- data/test/test_From_Ruby.cpp +609 -0
- data/test/test_Hash.cpp +5 -0
- data/test/test_Identifier.cpp +5 -0
- data/test/test_Inheritance.cpp +6 -1
- data/test/test_Iterator.cpp +6 -1
- data/test/test_Jump_Exception.cpp +23 -0
- data/test/test_Keep_Alive.cpp +13 -19
- data/test/test_Keep_Alive_No_Wrapper.cpp +5 -1
- data/test/test_Memory_Management.cpp +5 -0
- data/test/test_Module.cpp +128 -67
- data/test/test_Native_Registry.cpp +2 -34
- data/test/test_Object.cpp +5 -0
- data/test/test_Overloads.cpp +806 -0
- data/test/test_Ownership.cpp +160 -54
- data/test/test_Proc.cpp +44 -0
- data/test/test_Self.cpp +9 -4
- data/test/test_Stl_Exception.cpp +109 -0
- data/test/test_Stl_Map.cpp +54 -42
- data/test/test_Stl_Multimap.cpp +693 -0
- data/test/test_Stl_Optional.cpp +5 -0
- data/test/test_Stl_Pair.cpp +14 -9
- data/test/test_Stl_Reference_Wrapper.cpp +9 -2
- data/test/test_Stl_Set.cpp +790 -0
- data/test/test_Stl_SharedPtr.cpp +458 -0
- data/test/test_Stl_String.cpp +5 -0
- data/test/test_Stl_String_View.cpp +5 -0
- data/test/test_Stl_Tuple.cpp +116 -0
- data/test/test_Stl_Type.cpp +147 -0
- data/test/test_Stl_UniquePtr.cpp +202 -0
- data/test/test_Stl_Unordered_Map.cpp +43 -38
- data/test/test_Stl_Variant.cpp +217 -84
- data/test/test_Stl_Vector.cpp +306 -58
- data/test/test_String.cpp +5 -0
- data/test/test_Struct.cpp +5 -0
- data/test/test_Symbol.cpp +5 -0
- data/test/test_Template.cpp +192 -0
- data/test/test_To_Ruby.cpp +524 -0
- data/test/test_Tracking.cpp +1 -0
- data/test/test_Type.cpp +171 -0
- data/test/test_global_functions.cpp +67 -7
- data/test/unittest.cpp +8 -0
- metadata +127 -26
- data/lib/version.rb +0 -3
- data/rice/Address_Registration_Guard_defn.hpp +0 -79
- data/rice/Data_Object_defn.hpp +0 -84
- data/rice/Data_Type_defn.hpp +0 -190
- data/rice/Exception_defn.hpp +0 -68
- data/rice/HandlerRegistration.hpp +0 -15
- data/rice/detail/ExceptionHandler.hpp +0 -8
- data/rice/detail/ExceptionHandler.ipp +0 -28
- data/rice/detail/ExceptionHandler_defn.hpp +0 -77
- data/rice/detail/Jump_Tag.hpp +0 -21
- data/rice/detail/NativeAttribute.hpp +0 -64
- data/rice/detail/NativeAttribute.ipp +0 -112
- data/rice/detail/from_ruby_defn.hpp +0 -38
- data/rice/detail/to_ruby_defn.hpp +0 -48
- data/test/test_Jump_Tag.cpp +0 -17
- data/test/test_Stl_SmartPointer.cpp +0 -283
- 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
|
-
|
4
|
-
|
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
|
-
|
8
|
-
|
9
|
-
|
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 /
|
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('
|
128
|
-
|
129
|
-
|
130
|
-
|
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
|
-
|
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
|
data/lib/rice/version.rb
ADDED
data/lib/rice.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require_relative "rice/version"
|
@@ -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
|
-
|
5
|
-
|
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
|
-
|
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
|
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
|
-
|
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
|
24
|
+
inline Arg_Type Arg::defaultValue()
|
25
25
|
{
|
26
|
-
return std::any_cast<Arg_Type
|
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_
|