rice 4.3.2 → 4.5.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 (151) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +66 -25
  3. data/README.md +7 -2
  4. data/Rakefile +7 -1
  5. data/include/rice/rice.hpp +7321 -4470
  6. data/include/rice/stl.hpp +769 -222
  7. data/lib/mkmf-rice.rb +37 -95
  8. data/rice/Address_Registration_Guard.hpp +72 -3
  9. data/rice/Arg.hpp +19 -5
  10. data/rice/Arg.ipp +24 -0
  11. data/rice/Callback.hpp +21 -0
  12. data/rice/Callback.ipp +13 -0
  13. data/rice/Constructor.hpp +4 -27
  14. data/rice/Constructor.ipp +79 -0
  15. data/rice/Data_Object.hpp +74 -3
  16. data/rice/Data_Object.ipp +324 -32
  17. data/rice/Data_Type.hpp +215 -3
  18. data/rice/Data_Type.ipp +125 -64
  19. data/rice/Director.hpp +0 -2
  20. data/rice/Enum.hpp +4 -6
  21. data/rice/Enum.ipp +101 -57
  22. data/rice/Exception.hpp +62 -2
  23. data/rice/Exception.ipp +7 -12
  24. data/rice/JumpException.hpp +44 -0
  25. data/rice/JumpException.ipp +48 -0
  26. data/rice/MemoryView.hpp +11 -0
  27. data/rice/MemoryView.ipp +43 -0
  28. data/rice/Return.hpp +6 -26
  29. data/rice/Return.ipp +10 -16
  30. data/rice/detail/DefaultHandler.hpp +12 -0
  31. data/rice/detail/DefaultHandler.ipp +8 -0
  32. data/rice/detail/HandlerRegistry.hpp +5 -35
  33. data/rice/detail/HandlerRegistry.ipp +7 -11
  34. data/rice/detail/InstanceRegistry.hpp +1 -4
  35. data/rice/detail/MethodInfo.hpp +15 -5
  36. data/rice/detail/MethodInfo.ipp +78 -6
  37. data/rice/detail/Native.hpp +32 -0
  38. data/rice/detail/Native.ipp +129 -0
  39. data/rice/detail/NativeAttributeGet.hpp +51 -0
  40. data/rice/detail/NativeAttributeGet.ipp +51 -0
  41. data/rice/detail/NativeAttributeSet.hpp +43 -0
  42. data/rice/detail/NativeAttributeSet.ipp +82 -0
  43. data/rice/detail/NativeCallbackFFI.hpp +55 -0
  44. data/rice/detail/NativeCallbackFFI.ipp +151 -0
  45. data/rice/detail/NativeCallbackSimple.hpp +30 -0
  46. data/rice/detail/NativeCallbackSimple.ipp +29 -0
  47. data/rice/detail/NativeFunction.hpp +20 -21
  48. data/rice/detail/NativeFunction.ipp +199 -64
  49. data/rice/detail/NativeIterator.hpp +8 -11
  50. data/rice/detail/NativeIterator.ipp +27 -31
  51. data/rice/detail/NativeRegistry.hpp +24 -17
  52. data/rice/detail/NativeRegistry.ipp +23 -56
  53. data/rice/detail/Proc.hpp +4 -0
  54. data/rice/detail/Proc.ipp +85 -0
  55. data/rice/detail/Registries.hpp +0 -7
  56. data/rice/detail/Registries.ipp +0 -18
  57. data/rice/detail/RubyFunction.hpp +0 -3
  58. data/rice/detail/RubyFunction.ipp +4 -8
  59. data/rice/detail/RubyType.hpp +19 -0
  60. data/rice/detail/RubyType.ipp +187 -0
  61. data/rice/detail/TupleIterator.hpp +14 -0
  62. data/rice/detail/Type.hpp +5 -6
  63. data/rice/detail/Type.ipp +150 -33
  64. data/rice/detail/TypeRegistry.hpp +15 -7
  65. data/rice/detail/TypeRegistry.ipp +105 -12
  66. data/rice/detail/Wrapper.hpp +6 -5
  67. data/rice/detail/Wrapper.ipp +45 -23
  68. data/rice/detail/cpp_protect.hpp +5 -6
  69. data/rice/detail/default_allocation_func.ipp +0 -2
  70. data/rice/detail/from_ruby.hpp +37 -3
  71. data/rice/detail/from_ruby.ipp +911 -454
  72. data/rice/detail/ruby.hpp +18 -0
  73. data/rice/detail/to_ruby.hpp +41 -3
  74. data/rice/detail/to_ruby.ipp +437 -113
  75. data/rice/global_function.hpp +0 -4
  76. data/rice/global_function.ipp +1 -2
  77. data/rice/rice.hpp +105 -22
  78. data/rice/ruby_mark.hpp +4 -3
  79. data/rice/stl.hpp +4 -0
  80. data/test/embed_ruby.cpp +4 -1
  81. data/test/extconf.rb +2 -0
  82. data/test/ruby/test_multiple_extensions_same_class.rb +14 -14
  83. data/test/test_Address_Registration_Guard.cpp +5 -0
  84. data/test/test_Array.cpp +12 -1
  85. data/test/test_Attribute.cpp +103 -21
  86. data/test/test_Builtin_Object.cpp +5 -0
  87. data/test/test_Callback.cpp +231 -0
  88. data/test/test_Class.cpp +5 -31
  89. data/test/test_Constructor.cpp +69 -6
  90. data/test/test_Data_Object.cpp +9 -4
  91. data/test/test_Data_Type.cpp +428 -64
  92. data/test/test_Director.cpp +10 -5
  93. data/test/test_Enum.cpp +152 -40
  94. data/test/test_Exception.cpp +235 -0
  95. data/test/test_File.cpp +70 -0
  96. data/test/test_From_Ruby.cpp +542 -0
  97. data/test/test_Hash.cpp +5 -0
  98. data/test/test_Identifier.cpp +5 -0
  99. data/test/test_Inheritance.cpp +6 -1
  100. data/test/test_Iterator.cpp +5 -0
  101. data/test/test_JumpException.cpp +22 -0
  102. data/test/test_Keep_Alive.cpp +6 -1
  103. data/test/test_Keep_Alive_No_Wrapper.cpp +5 -0
  104. data/test/test_Memory_Management.cpp +5 -0
  105. data/test/test_Module.cpp +118 -64
  106. data/test/test_Native_Registry.cpp +2 -33
  107. data/test/test_Object.cpp +5 -0
  108. data/test/test_Overloads.cpp +631 -0
  109. data/test/test_Ownership.cpp +67 -4
  110. data/test/test_Proc.cpp +45 -0
  111. data/test/test_Self.cpp +5 -0
  112. data/test/test_Stl_Exception.cpp +109 -0
  113. data/test/test_Stl_Map.cpp +22 -8
  114. data/test/test_Stl_Optional.cpp +5 -0
  115. data/test/test_Stl_Pair.cpp +7 -2
  116. data/test/test_Stl_Reference_Wrapper.cpp +5 -0
  117. data/test/test_Stl_SmartPointer.cpp +210 -5
  118. data/test/test_Stl_String.cpp +5 -0
  119. data/test/test_Stl_String_View.cpp +5 -0
  120. data/test/test_Stl_Type.cpp +147 -0
  121. data/test/test_Stl_Unordered_Map.cpp +18 -7
  122. data/test/test_Stl_Variant.cpp +5 -0
  123. data/test/test_Stl_Vector.cpp +130 -8
  124. data/test/test_String.cpp +5 -0
  125. data/test/test_Struct.cpp +5 -0
  126. data/test/test_Symbol.cpp +5 -0
  127. data/test/test_Template.cpp +192 -0
  128. data/test/test_To_Ruby.cpp +152 -0
  129. data/test/test_Tracking.cpp +1 -0
  130. data/test/test_Type.cpp +100 -0
  131. data/test/test_global_functions.cpp +53 -6
  132. data/test/unittest.cpp +8 -0
  133. metadata +37 -20
  134. data/lib/version.rb +0 -3
  135. data/rice/Address_Registration_Guard_defn.hpp +0 -79
  136. data/rice/Data_Object_defn.hpp +0 -84
  137. data/rice/Data_Type_defn.hpp +0 -190
  138. data/rice/Exception_defn.hpp +0 -68
  139. data/rice/HandlerRegistration.hpp +0 -15
  140. data/rice/Identifier.hpp +0 -50
  141. data/rice/Identifier.ipp +0 -29
  142. data/rice/detail/ExceptionHandler.hpp +0 -8
  143. data/rice/detail/ExceptionHandler.ipp +0 -28
  144. data/rice/detail/ExceptionHandler_defn.hpp +0 -77
  145. data/rice/detail/Jump_Tag.hpp +0 -21
  146. data/rice/detail/NativeAttribute.hpp +0 -64
  147. data/rice/detail/NativeAttribute.ipp +0 -112
  148. data/rice/detail/from_ruby_defn.hpp +0 -38
  149. data/rice/detail/to_ruby_defn.hpp +0 -48
  150. data/test/test_Jump_Tag.cpp +0 -17
  151. data/test/test_To_From_Ruby.cpp +0 -399
data/lib/mkmf-rice.rb CHANGED
@@ -1,93 +1,8 @@
1
1
  require 'mkmf'
2
2
 
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?
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
3
+ IS_MSWIN = /mswin/ =~ RUBY_PLATFORM
4
+ IS_MINGW = /mingw/ =~ RUBY_PLATFORM
5
+ IS_DARWIN = RbConfig::CONFIG['host_os'].match?(/darwin/)
91
6
 
92
7
  # The cpp_command is not overwritten in the experimental mkmf C++ support.
93
8
  # See https://bugs.ruby-lang.org/issues/17578
@@ -107,7 +22,7 @@ include MakeMakefile['C++']
107
22
 
108
23
  # Rice needs c++17.
109
24
  if IS_MSWIN
110
- $CXXFLAGS += " /std:c++17 /EHsc /permissive- /bigobj"
25
+ $CXXFLAGS += " /std:c++17 /EHs /permissive- /bigobj /utf-8"
111
26
  $CPPFLAGS += " -D_ALLOW_KEYWORD_MACROS -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE"
112
27
  elsif IS_MINGW
113
28
  $CXXFLAGS += " -std=c++17 -Wa,-mbig-obj"
@@ -123,10 +38,37 @@ unless find_header('rice/rice.hpp', path)
123
38
  raise("Could not find rice/rice.hpp header")
124
39
  end
125
40
 
126
- if IS_DARWIN
127
- have_library('c++')
128
- elsif !IS_MSWIN
129
- if !have_library('stdc++fs')
130
- have_library('stdc++')
41
+ if !IS_DARWIN && !IS_MSWIN && !have_library('stdc++fs')
42
+ have_library('stdc++')
43
+ end
44
+
45
+ # Copied from Ruby FFI bindings - see
46
+ # https://github.com/ffi/ffi/blob/1715332d553d53fae13fd9fcbbd9d2c1982a5c2f/ext/ffi_c/extconf.rb#L7C1-L27C6
47
+ def system_libffi_usable?
48
+ # We need pkg_config or ffi.h
49
+ libffi_ok = pkg_config("libffi") ||
50
+ have_header("ffi.h") ||
51
+ find_header("ffi.h", "/usr/local/include", "/usr/include/ffi",
52
+ "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/ffi",
53
+ "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/ffi") ||
54
+ (find_header("ffi.h", `xcrun --sdk macosx --show-sdk-path`.strip + "/usr/include/ffi") rescue false)
55
+
56
+ # Ensure we can link to ffi_prep_closure_loc
57
+ libffi_ok &&= have_library("ffi", "ffi_prep_closure_loc", [ "ffi.h" ]) ||
58
+ have_library("libffi", "ffi_prep_closure_loc", [ "ffi.h" ]) ||
59
+ have_library("libffi-8", "ffi_prep_closure_loc", [ "ffi.h" ])
60
+
61
+ if RbConfig::CONFIG['host_os'] =~ /mswin/
62
+ have_library('libffi_convenience')
63
+ have_library('shlwapi')
131
64
  end
132
- end
65
+
66
+ libffi_ok
67
+ end
68
+
69
+ def have_libffi
70
+ # Check for libffi to support C style callacks.
71
+ libffi_usable = system_libffi_usable?
72
+ $CPPFLAGS += " -DHAVE_LIBFFI" if libffi_usable
73
+ libffi_usable
74
+ 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
@@ -56,19 +59,30 @@ namespace Rice
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
+
70
84
  public:
71
- const std::string name;
85
+ std::string name;
72
86
  int32_t position = -1;
73
87
 
74
88
  private:
@@ -76,9 +90,9 @@ namespace Rice
76
90
  std::any defaultValue_;
77
91
  bool isValue_ = false;
78
92
  bool isKeepAlive_ = false;
93
+ bool isOwner_ = false;
94
+ bool isOpaque_ = false;
79
95
  };
80
96
  } // Rice
81
97
 
82
- #include "Arg.ipp"
83
-
84
98
  #endif // Rice__Arg__hpp_
data/rice/Arg.ipp CHANGED
@@ -47,4 +47,28 @@ 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
+
50
74
  } // Rice
data/rice/Callback.hpp ADDED
@@ -0,0 +1,21 @@
1
+ #ifndef Rice__Callback__hpp_
2
+ #define Rice__Callback__hpp_
3
+
4
+ namespace Rice
5
+ {
6
+ //! Define a callback.
7
+ /*! When C++ invokes a C style callback, Rice automatically converts the C++ arguments
8
+ * to Ruby. However, there may be cases where you need to specify how individual arguments
9
+ * should be handled. For example, callbacks often have a user data parameter which is
10
+ * defined as a void pointer (void*). In this case, you need to tell Ruby that the parameter
11
+ * is opaque and should not be convered. For example:
12
+ *
13
+ * define_callback<void(*)(void*)>(Arg("user_data").setOpaque());
14
+ *
15
+ * \param args a list of Arg instance used to define default parameters (optional)
16
+ * \return nothing
17
+ */
18
+ template<typename Callback_T, typename...Arg_Ts>
19
+ void define_callback(const Arg_Ts&...args);
20
+ }
21
+ #endif // Rice__Callback__hpp_
data/rice/Callback.ipp ADDED
@@ -0,0 +1,13 @@
1
+ namespace Rice
2
+ {
3
+ template<typename Callback_T, typename...Arg_Ts>
4
+ void define_callback(const Arg_Ts&...args)
5
+ {
6
+ MethodInfo* methodInfo = new MethodInfo(detail::function_traits<Callback_T>::arity, args...);
7
+ #ifdef HAVE_LIBFFI
8
+ detail::NativeCallbackFFI<Callback_T>::setMethodInfo(methodInfo);
9
+ #else
10
+ detail::NativeCallbackSimple<Callback_T>::setMethodInfo(methodInfo);
11
+ #endif
12
+ }
13
+ }
data/rice/Constructor.hpp CHANGED
@@ -1,9 +1,6 @@
1
1
  #ifndef Rice__Constructor__hpp_
2
2
  #define Rice__Constructor__hpp_
3
3
 
4
- #include "detail/Wrapper.hpp"
5
- #include "cpp_api/Object_defn.hpp"
6
-
7
4
  namespace Rice
8
5
  {
9
6
  //! Define a Type's Constructor and it's arguments.
@@ -13,33 +10,13 @@ namespace Rice
13
10
  .define_constructor(Constructor<Test>());
14
11
  \endcode
15
12
  *
16
- * The first template type must be the type being wrapped.
17
- * Afterwards any extra types must match the appropriate constructor
18
- * to be used in C++ when constructing the object.
13
+ * The first template argument must be the type being wrapped.
14
+ * Additional arguments must be the types of the parameters sent
15
+ * to the constructor.
19
16
  *
20
17
  * For more information, see Rice::Data_Type::define_constructor.
21
18
  */
22
19
  template<typename T, typename...Arg_Ts>
23
- class Constructor
24
- {
25
- public:
26
- static void construct(VALUE self, Arg_Ts...args)
27
- {
28
- T* data = new T(args...);
29
- detail::replace<T>(self, Data_Type<T>::ruby_data_type(), data, true);
30
- }
31
- };
32
-
33
- //! Special-case Constructor used when defining Directors.
34
- template<typename T, typename...Arg_Ts>
35
- class Constructor<T, Object, Arg_Ts...>
36
- {
37
- public:
38
- static void construct(Object self, Arg_Ts...args)
39
- {
40
- T* data = new T(self, args...);
41
- detail::replace<T>(self.value(), Data_Type<T>::ruby_data_type(), data, true);
42
- }
43
- };
20
+ class Constructor;
44
21
  }
45
22
  #endif // Rice__Constructor__hpp_
@@ -0,0 +1,79 @@
1
+ namespace Rice
2
+ {
3
+ template<typename T, typename...Arg_Ts>
4
+ class Constructor
5
+ {
6
+ public:
7
+ static constexpr std::size_t arity = sizeof...(Arg_Ts);
8
+
9
+ static constexpr bool isCopyConstructor()
10
+ {
11
+ if constexpr (arity == 1)
12
+ {
13
+ using Arg_Types = std::tuple<Arg_Ts...>;
14
+ using First_Arg_T = std::tuple_element_t<0, Arg_Types>;
15
+ return (arity == 1 &&
16
+ std::is_lvalue_reference_v<First_Arg_T> &&
17
+ std::is_same_v<T, detail::intrinsic_type<First_Arg_T>>);
18
+ }
19
+ else
20
+ {
21
+ return false;
22
+ }
23
+ }
24
+
25
+ static constexpr bool isMoveConstructor()
26
+ {
27
+ if constexpr (arity == 1)
28
+ {
29
+ using Arg_Types = std::tuple<Arg_Ts...>;
30
+ using First_Arg_T = std::tuple_element_t<0, Arg_Types>;
31
+ return (arity == 1 &&
32
+ std::is_rvalue_reference_v<First_Arg_T> &&
33
+ std::is_same_v<T, detail::intrinsic_type<First_Arg_T>>);
34
+ }
35
+ else
36
+ {
37
+ return false;
38
+ }
39
+ }
40
+
41
+ static void initialize(VALUE self, Arg_Ts...args)
42
+ {
43
+ // Call C++ constructor
44
+ T* data = new T(args...);
45
+ detail::replace<T>(self, Data_Type<T>::ruby_data_type(), data, true);
46
+ }
47
+
48
+ static void initialize_copy(VALUE self, const T& other)
49
+ {
50
+ // Call C++ copy constructor
51
+ T* data = new T(other);
52
+ detail::replace<T>(self, Data_Type<T>::ruby_data_type(), data, true);
53
+ }
54
+
55
+ };
56
+
57
+ //! Special-case Constructor used when defining Directors.
58
+ template<typename T, typename...Arg_Ts>
59
+ class Constructor<T, Object, Arg_Ts...>
60
+ {
61
+ public:
62
+ static constexpr bool isCopyConstructor()
63
+ {
64
+ return false;
65
+ }
66
+
67
+ static constexpr bool isMoveConstructor()
68
+ {
69
+ return false;
70
+ }
71
+
72
+ static void initialize(Object self, Arg_Ts...args)
73
+ {
74
+ // Call C++ constructor
75
+ T* data = new T(self, args...);
76
+ detail::replace<T>(self.value(), Data_Type<T>::ruby_data_type(), data, true);
77
+ }
78
+ };
79
+ }
data/rice/Data_Object.hpp CHANGED
@@ -1,8 +1,79 @@
1
1
  #ifndef Rice__Data_Object__hpp_
2
2
  #define Rice__Data_Object__hpp_
3
3
 
4
- #include "Data_Object_defn.hpp"
5
- #include "Data_Object.ipp"
4
+ /*! \file
5
+ * \brief Provides a helper class for wrapping and unwrapping C++
6
+ * objects as Ruby objects.
7
+ */
6
8
 
7
- #endif // Rice__Data_Object__hpp_
9
+ namespace Rice
10
+ {
11
+ //! A smartpointer-like wrapper for Ruby data objects.
12
+ /*! A data object is a ruby object of type T_DATA, which is usually
13
+ * created by using the Data_Wrap_Struct or Data_Make_Struct macro.
14
+ * This class wraps creation of the data structure, providing a
15
+ * type-safe object-oriented interface to the underlying C interface.
16
+ * This class works in conjunction with the Data_Type class to ensure
17
+ * type safety.
18
+ *
19
+ * Example:
20
+ * \code
21
+ * class Foo { };
22
+ * ...
23
+ * Data_Type<Foo> rb_cFoo = define_class("Foo");
24
+ * ...
25
+ * // Wrap:
26
+ * Data_Object<Foo> foo1(new Foo);
27
+ *
28
+ * // Get value to return:
29
+ * VALUE v = foo1.value()
30
+ *
31
+ * // Unwrap:
32
+ * Data_Object<Foo> foo2(v, rb_cFoo);
33
+ * \endcode
34
+ */
35
+ template<typename T>
36
+ class Data_Object : public Object
37
+ {
38
+ static_assert(!std::is_pointer_v<T>);
39
+ static_assert(!std::is_reference_v<T>);
40
+ static_assert(!std::is_const_v<T>);
41
+ static_assert(!std::is_volatile_v<T>);
42
+ static_assert(!std::is_void_v<T>);
43
+
44
+ public:
45
+ static T* from_ruby(VALUE value, bool takeOwnership = false);
46
+
47
+ public:
48
+ //! Wrap a C++ object.
49
+ /*! This constructor is analogous to calling Data_Wrap_Struct. Be
50
+ * careful not to call this function more than once for the same
51
+ * pointer (in general, it should only be called for newly
52
+ * constructed objects that need to be managed by Ruby's garbage
53
+ * collector).
54
+ * \param obj the object to wrap.
55
+ * \param isOwner Should the Data_Object take ownership of the object?
56
+ * \param klass the Ruby class to use for the newly created Ruby
57
+ * object.
58
+ */
59
+ Data_Object(T* obj, bool isOwner = false, Class klass = Data_Type<T>::klass());
60
+ Data_Object(T& obj, bool isOwner = false, Class klass = Data_Type<T>::klass());
61
+ Data_Object(const T& obj, bool isOwner = false, Class klass = Data_Type<T>::klass());
62
+
63
+ //! Unwrap a Ruby object.
64
+ /*! This constructor is analogous to calling Data_Get_Struct. Uses
65
+ * Data_Type<T>::klass as the class of the object.
66
+ * \param value the Ruby object to unwrap.
67
+ */
68
+ Data_Object(Object value);
8
69
 
70
+ T& operator*() const; //!< Return a reference to obj_
71
+ T* operator->() const; //!< Return a pointer to obj_
72
+ T* get() const; //!< Return a pointer to obj_
73
+
74
+ private:
75
+ static void check_ruby_type(VALUE value);
76
+ };
77
+ } // namespace Rice
78
+
79
+ #endif // Rice__Data_Object__hpp_