rice 4.3.3 → 4.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (151) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +63 -26
  3. data/README.md +7 -2
  4. data/Rakefile +7 -1
  5. data/include/rice/rice.hpp +7291 -4430
  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 -15
  52. data/rice/detail/NativeRegistry.ipp +23 -48
  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_