rice 3.0.0 → 4.0.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 +121 -0
- data/CONTRIBUTORS.md +19 -0
- data/Gemfile +3 -0
- data/README.md +44 -1025
- data/Rakefile +95 -12
- data/include/rice/rice.hpp +7766 -0
- data/lib/mkmf-rice.rb +127 -0
- data/lib/version.rb +3 -0
- data/rice/Address_Registration_Guard.ipp +75 -32
- data/rice/Address_Registration_Guard_defn.hpp +60 -56
- data/rice/Arg.hpp +80 -4
- data/rice/Arg.ipp +51 -0
- data/rice/Constructor.hpp +12 -14
- data/rice/Data_Object.ipp +234 -107
- data/rice/Data_Object_defn.hpp +77 -117
- data/rice/Data_Type.hpp +1 -2
- data/rice/Data_Type.ipp +251 -295
- data/rice/Data_Type_defn.hpp +175 -243
- data/rice/Director.hpp +11 -6
- data/rice/Enum.hpp +54 -104
- data/rice/Enum.ipp +104 -230
- data/rice/Exception.hpp +2 -8
- data/rice/Exception.ipp +65 -0
- data/rice/Exception_defn.hpp +46 -47
- data/rice/Identifier.hpp +28 -28
- data/rice/Identifier.ipp +23 -27
- data/rice/Return.hpp +39 -0
- data/rice/Return.ipp +33 -0
- data/rice/detail/Exception_Handler.ipp +22 -62
- data/rice/detail/Exception_Handler_defn.hpp +76 -91
- data/rice/detail/Iterator.hpp +18 -88
- data/rice/detail/Iterator.ipp +47 -0
- data/rice/detail/Jump_Tag.hpp +21 -0
- data/rice/detail/MethodInfo.hpp +44 -0
- data/rice/detail/MethodInfo.ipp +78 -0
- data/rice/detail/NativeAttribute.hpp +53 -0
- data/rice/detail/NativeAttribute.ipp +83 -0
- data/rice/detail/NativeFunction.hpp +69 -0
- data/rice/detail/NativeFunction.ipp +248 -0
- data/rice/detail/RubyFunction.hpp +39 -0
- data/rice/detail/RubyFunction.ipp +92 -0
- data/rice/detail/Type.hpp +29 -0
- data/rice/detail/Type.ipp +138 -0
- data/rice/detail/TypeRegistry.hpp +50 -0
- data/rice/detail/TypeRegistry.ipp +106 -0
- data/rice/detail/Wrapper.hpp +51 -0
- data/rice/detail/Wrapper.ipp +151 -0
- data/rice/detail/default_allocation_func.hpp +8 -19
- data/rice/detail/default_allocation_func.ipp +9 -8
- data/rice/detail/from_ruby.hpp +2 -37
- data/rice/detail/from_ruby.ipp +1020 -46
- data/rice/detail/from_ruby_defn.hpp +38 -0
- data/rice/detail/function_traits.hpp +124 -0
- data/rice/detail/method_data.hpp +23 -15
- data/rice/detail/method_data.ipp +53 -0
- data/rice/detail/rice_traits.hpp +116 -0
- data/rice/detail/ruby.hpp +9 -46
- data/rice/detail/to_ruby.hpp +3 -17
- data/rice/detail/to_ruby.ipp +409 -31
- data/rice/detail/to_ruby_defn.hpp +48 -0
- data/rice/forward_declares.ipp +82 -0
- data/rice/global_function.hpp +16 -20
- data/rice/global_function.ipp +8 -17
- data/rice/rice.hpp +59 -0
- data/rice/ruby_mark.hpp +5 -3
- data/rice/ruby_try_catch.hpp +4 -4
- data/rice/stl.hpp +11 -0
- data/sample/callbacks/extconf.rb +3 -0
- data/sample/callbacks/sample_callbacks.cpp +10 -13
- data/sample/enum/extconf.rb +3 -0
- data/sample/enum/sample_enum.cpp +3 -17
- data/sample/enum/test.rb +2 -2
- data/sample/inheritance/animals.cpp +8 -24
- data/sample/inheritance/extconf.rb +3 -0
- data/sample/inheritance/test.rb +1 -1
- data/sample/map/extconf.rb +3 -0
- data/sample/map/map.cpp +10 -18
- data/sample/map/test.rb +1 -1
- data/test/embed_ruby.cpp +18 -5
- data/test/ext/t1/extconf.rb +3 -0
- data/test/ext/t1/t1.cpp +1 -3
- data/test/ext/t2/extconf.rb +3 -0
- data/test/ext/t2/t2.cpp +1 -1
- data/test/extconf.rb +23 -0
- data/test/ruby/test_callbacks_sample.rb +28 -0
- data/test/ruby/test_multiple_extensions.rb +18 -0
- data/test/ruby/test_multiple_extensions_same_class.rb +14 -0
- data/test/ruby/test_multiple_extensions_with_inheritance.rb +20 -0
- data/test/test_Address_Registration_Guard.cpp +23 -10
- data/test/test_Array.cpp +129 -73
- data/test/test_Attribute.cpp +147 -0
- data/test/test_Builtin_Object.cpp +34 -14
- data/test/test_Class.cpp +149 -275
- data/test/test_Constructor.cpp +10 -9
- data/test/test_Data_Object.cpp +133 -192
- data/test/test_Data_Type.cpp +322 -252
- data/test/test_Director.cpp +54 -41
- data/test/test_Enum.cpp +228 -103
- data/test/test_Exception.cpp +5 -6
- data/test/test_Hash.cpp +31 -30
- data/test/test_Identifier.cpp +4 -5
- data/test/test_Inheritance.cpp +221 -0
- data/test/test_Iterator.cpp +161 -0
- data/test/test_Jump_Tag.cpp +1 -1
- data/test/test_Keep_Alive.cpp +161 -0
- data/test/test_Memory_Management.cpp +2 -4
- data/test/test_Module.cpp +167 -110
- data/test/test_Object.cpp +41 -21
- data/test/test_Ownership.cpp +275 -0
- data/test/test_Self.cpp +205 -0
- data/test/test_Stl_Optional.cpp +90 -0
- data/test/test_Stl_Pair.cpp +144 -0
- data/test/test_Stl_SmartPointer.cpp +200 -0
- data/test/test_Stl_String.cpp +74 -0
- data/test/test_Stl_Vector.cpp +652 -0
- data/test/test_String.cpp +1 -2
- data/test/test_Struct.cpp +29 -39
- data/test/test_Symbol.cpp +1 -2
- data/test/test_To_From_Ruby.cpp +249 -285
- data/test/test_global_functions.cpp +39 -19
- data/test/unittest.hpp +0 -4
- metadata +63 -139
- data/Doxyfile +0 -2268
- data/Makefile.am +0 -26
- data/Makefile.in +0 -931
- data/README.mingw +0 -8
- data/aclocal.m4 +0 -1085
- data/ax_cxx_compile_stdcxx.m4 +0 -951
- data/bootstrap +0 -8
- data/config.guess +0 -1421
- data/config.sub +0 -1807
- data/configure +0 -7792
- data/configure.ac +0 -55
- data/depcomp +0 -791
- data/doxygen.ac +0 -314
- data/doxygen.am +0 -186
- data/extconf.rb +0 -70
- data/install-sh +0 -501
- data/missing +0 -215
- data/post-autoconf.rb +0 -22
- data/post-automake.rb +0 -28
- data/rice/Address_Registration_Guard.cpp +0 -22
- data/rice/Arg_impl.hpp +0 -129
- data/rice/Arg_operators.cpp +0 -21
- data/rice/Arg_operators.hpp +0 -19
- data/rice/Array.hpp +0 -214
- data/rice/Array.ipp +0 -256
- data/rice/Builtin_Object.hpp +0 -8
- data/rice/Builtin_Object.ipp +0 -50
- data/rice/Builtin_Object_defn.hpp +0 -50
- data/rice/Class.cpp +0 -57
- data/rice/Class.hpp +0 -8
- data/rice/Class.ipp +0 -6
- data/rice/Class_defn.hpp +0 -84
- data/rice/Data_Type.cpp +0 -54
- data/rice/Data_Type_fwd.hpp +0 -12
- data/rice/Director.cpp +0 -13
- data/rice/Exception.cpp +0 -54
- data/rice/Exception_Base.hpp +0 -8
- data/rice/Exception_Base.ipp +0 -13
- data/rice/Exception_Base_defn.hpp +0 -27
- data/rice/Hash.hpp +0 -230
- data/rice/Hash.ipp +0 -329
- data/rice/Identifier.cpp +0 -8
- data/rice/Jump_Tag.hpp +0 -24
- data/rice/Makefile.am +0 -121
- data/rice/Makefile.in +0 -884
- data/rice/Module.cpp +0 -84
- data/rice/Module.hpp +0 -8
- data/rice/Module.ipp +0 -6
- data/rice/Module_defn.hpp +0 -88
- data/rice/Module_impl.hpp +0 -281
- data/rice/Module_impl.ipp +0 -345
- data/rice/Object.cpp +0 -169
- data/rice/Object.hpp +0 -8
- data/rice/Object.ipp +0 -33
- data/rice/Object_defn.hpp +0 -214
- data/rice/Require_Guard.hpp +0 -21
- data/rice/String.cpp +0 -89
- data/rice/String.hpp +0 -91
- data/rice/Struct.cpp +0 -117
- data/rice/Struct.hpp +0 -162
- data/rice/Struct.ipp +0 -26
- data/rice/Symbol.cpp +0 -25
- data/rice/Symbol.hpp +0 -66
- data/rice/Symbol.ipp +0 -44
- data/rice/config.hpp +0 -47
- data/rice/config.hpp.in +0 -46
- data/rice/detail/Arguments.hpp +0 -118
- data/rice/detail/Auto_Function_Wrapper.hpp +0 -898
- data/rice/detail/Auto_Function_Wrapper.ipp +0 -3181
- data/rice/detail/Auto_Member_Function_Wrapper.hpp +0 -897
- data/rice/detail/Auto_Member_Function_Wrapper.ipp +0 -2501
- data/rice/detail/Caster.hpp +0 -103
- data/rice/detail/Not_Copyable.hpp +0 -25
- data/rice/detail/Wrapped_Function.hpp +0 -33
- data/rice/detail/cfp.hpp +0 -24
- data/rice/detail/cfp.ipp +0 -51
- data/rice/detail/check_ruby_type.cpp +0 -27
- data/rice/detail/check_ruby_type.hpp +0 -23
- data/rice/detail/creation_funcs.hpp +0 -37
- data/rice/detail/creation_funcs.ipp +0 -36
- data/rice/detail/define_method_and_auto_wrap.hpp +0 -31
- data/rice/detail/define_method_and_auto_wrap.ipp +0 -30
- data/rice/detail/demangle.cpp +0 -56
- data/rice/detail/demangle.hpp +0 -19
- data/rice/detail/env.hpp +0 -11
- data/rice/detail/method_data.cpp +0 -92
- data/rice/detail/node.hpp +0 -13
- data/rice/detail/protect.cpp +0 -29
- data/rice/detail/protect.hpp +0 -34
- data/rice/detail/ruby_version_code.hpp +0 -6
- data/rice/detail/ruby_version_code.hpp.in +0 -6
- data/rice/detail/st.hpp +0 -22
- data/rice/detail/win32.hpp +0 -16
- data/rice/detail/wrap_function.hpp +0 -66
- data/rice/protect.hpp +0 -38
- data/rice/protect.ipp +0 -1134
- data/rice/rubypp.rb +0 -97
- data/rice/to_from_ruby.hpp +0 -8
- data/rice/to_from_ruby.ipp +0 -418
- data/rice/to_from_ruby_defn.hpp +0 -70
- data/ruby.ac +0 -135
- data/ruby/Makefile.am +0 -1
- data/ruby/Makefile.in +0 -628
- data/ruby/lib/Makefile.am +0 -3
- data/ruby/lib/Makefile.in +0 -506
- data/ruby/lib/mkmf-rice.rb.in +0 -217
- data/ruby/lib/version.rb +0 -3
- data/sample/Makefile.am +0 -53
- data/sample/Makefile.in +0 -495
- data/test/Makefile.am +0 -73
- data/test/Makefile.in +0 -1219
- data/test/ext/Makefile.am +0 -41
- data/test/ext/Makefile.in +0 -483
- data/test/test_rice.rb +0 -45
data/rice/Data_Object_defn.hpp
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
#ifndef Rice__Data_Object_defn__hpp_
|
2
2
|
#define Rice__Data_Object_defn__hpp_
|
3
3
|
|
4
|
-
#include
|
5
|
-
|
6
|
-
#include "ruby_mark.hpp"
|
4
|
+
#include <optional>
|
5
|
+
|
7
6
|
#include "detail/to_ruby.hpp"
|
8
7
|
#include "detail/ruby.hpp"
|
8
|
+
#include "cpp_api/Object_defn.hpp"
|
9
9
|
|
10
10
|
/*! \file
|
11
11
|
* \brief Provides a helper class for wrapping and unwrapping C++
|
@@ -14,124 +14,84 @@
|
|
14
14
|
|
15
15
|
namespace Rice
|
16
16
|
{
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
{
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
* Example:
|
41
|
-
* \code
|
42
|
-
* class Foo { };
|
43
|
-
* ...
|
44
|
-
* Data_Type<Foo> rb_cFoo = define_class("Foo");
|
45
|
-
* ...
|
46
|
-
* // Wrap:
|
47
|
-
* Data_Object<Foo> foo1(new Foo);
|
48
|
-
*
|
49
|
-
* // Get value to return:
|
50
|
-
* VALUE v = foo1.value()
|
51
|
-
*
|
52
|
-
* // Unwrap:
|
53
|
-
* Data_Object<Foo> foo2(v, rb_cFoo);
|
54
|
-
* \endcode
|
55
|
-
*/
|
56
|
-
template<typename T>
|
57
|
-
class Data_Object
|
58
|
-
: public Object
|
59
|
-
{
|
60
|
-
public:
|
61
|
-
//! A function that takes a T* and returns void.
|
62
|
-
typedef void (*Ruby_Data_Func)(T * obj);
|
63
|
-
|
64
|
-
//! Wrap a C++ object.
|
65
|
-
/*! This constructor is analogous to calling Data_Wrap_Struct. Be
|
66
|
-
* careful not to call this function more than once for the same
|
67
|
-
* pointer (in general, it should only be called for newly
|
68
|
-
* constructed objects that need to be managed by Ruby's garbage
|
69
|
-
* collector).
|
70
|
-
* \param obj the object to wrap.
|
71
|
-
* \param klass the Ruby class to use for the newly created Ruby
|
72
|
-
* object.
|
73
|
-
* \param mark_func a function that gets called by the garbage
|
74
|
-
* collector to mark the object's children.
|
75
|
-
* \param free_func a function that gets called by the garbage
|
76
|
-
* collector to free the object.
|
77
|
-
*/
|
78
|
-
Data_Object(
|
79
|
-
T * obj,
|
80
|
-
VALUE klass = Data_Type<T>::klass(),
|
81
|
-
Ruby_Data_Func mark_func = Default_Mark_Function<T>::mark,
|
82
|
-
Ruby_Data_Func free_func = Default_Free_Function<T>::free);
|
83
|
-
|
84
|
-
//! Unwrap a Ruby object.
|
85
|
-
/*! This constructor is analogous to calling Data_Get_Struct. Uses
|
86
|
-
* Data_Type<T>::klass as the class of the object.
|
87
|
-
* \param value the Ruby object to unwrap.
|
17
|
+
//! A smartpointer-like wrapper for Ruby data objects.
|
18
|
+
/*! A data object is a ruby object of type T_DATA, which is usually
|
19
|
+
* created by using the Data_Wrap_Struct or Data_Make_Struct macro.
|
20
|
+
* This class wraps creation of the data structure, providing a
|
21
|
+
* type-safe object-oriented interface to the underlying C interface.
|
22
|
+
* This class works in conjunction with the Data_Type class to ensure
|
23
|
+
* type safety.
|
24
|
+
*
|
25
|
+
* Example:
|
26
|
+
* \code
|
27
|
+
* class Foo { };
|
28
|
+
* ...
|
29
|
+
* Data_Type<Foo> rb_cFoo = define_class("Foo");
|
30
|
+
* ...
|
31
|
+
* // Wrap:
|
32
|
+
* Data_Object<Foo> foo1(new Foo);
|
33
|
+
*
|
34
|
+
* // Get value to return:
|
35
|
+
* VALUE v = foo1.value()
|
36
|
+
*
|
37
|
+
* // Unwrap:
|
38
|
+
* Data_Object<Foo> foo2(v, rb_cFoo);
|
39
|
+
* \endcode
|
88
40
|
*/
|
89
|
-
Data_Object(
|
90
|
-
Object value);
|
91
|
-
|
92
|
-
//! Unwrap a Ruby object.
|
93
|
-
/*! This constructor is analogous to calling Data_Get_Struct. Will
|
94
|
-
* throw an exception if the class of the object differs from the
|
95
|
-
* specified class.
|
96
|
-
* \param value the Ruby object to unwrap.
|
97
|
-
* \param klass the expected class of the object.
|
98
|
-
*/
|
99
|
-
template<typename U>
|
100
|
-
Data_Object(
|
101
|
-
Object value,
|
102
|
-
Data_Type<U> const & klass = Data_Type<T>::klass());
|
103
|
-
|
104
|
-
//! Make a copy of a Data_Object
|
105
|
-
/*! \param other the Data_Object to copy.
|
106
|
-
*/
|
107
|
-
Data_Object(Data_Object const & other);
|
108
|
-
|
109
|
-
T & operator*() const { return *obj_; } //!< Return a reference to obj_
|
110
|
-
T * operator->() const { return obj_; } //!< Return a pointer to obj_
|
111
|
-
T * get() const { return obj_; } //!< Return a pointer to obj_
|
112
|
-
|
113
|
-
//! Swap with another data object of the same type
|
114
|
-
/*! \param ref the object with which to swap.
|
115
|
-
*/
|
116
|
-
template<typename U>
|
117
|
-
void swap(Data_Object<U> & ref);
|
118
|
-
|
119
|
-
private:
|
120
|
-
static void check_cpp_type(Data_Type<T> const & klass);
|
121
|
-
|
122
|
-
private:
|
123
|
-
T * obj_;
|
124
|
-
};
|
125
|
-
|
126
|
-
namespace detail
|
127
|
-
{
|
128
41
|
template<typename T>
|
129
|
-
|
42
|
+
class Data_Object : public Object
|
130
43
|
{
|
131
|
-
|
44
|
+
static_assert(!std::is_pointer_v<T>);
|
45
|
+
static_assert(!std::is_reference_v<T>);
|
46
|
+
static_assert(!std::is_const_v<T>);
|
47
|
+
static_assert(!std::is_volatile_v<T>);
|
48
|
+
|
49
|
+
public:
|
50
|
+
static T* from_ruby(VALUE value);
|
51
|
+
static std::optional<T> implicit_from_ruby(VALUE value);
|
52
|
+
|
53
|
+
public:
|
54
|
+
//! Wrap a C++ object.
|
55
|
+
/*! This constructor is analogous to calling Data_Wrap_Struct. Be
|
56
|
+
* careful not to call this function more than once for the same
|
57
|
+
* pointer (in general, it should only be called for newly
|
58
|
+
* constructed objects that need to be managed by Ruby's garbage
|
59
|
+
* collector).
|
60
|
+
* \param obj the object to wrap.
|
61
|
+
* \param klass the Ruby class to use for the newly created Ruby
|
62
|
+
* object.
|
63
|
+
* \param mark_func a function that gets called by the garbage
|
64
|
+
* collector to mark the object's children.
|
65
|
+
* \param free_func a function that gets called by the garbage
|
66
|
+
* collector to free the object.
|
67
|
+
*/
|
68
|
+
Data_Object(T* obj, bool isOwner = false, Class klass = Data_Type<T>::klass());
|
69
|
+
Data_Object(T& obj, bool isOwner = false, Class klass = Data_Type<T>::klass());
|
70
|
+
|
71
|
+
//! Unwrap a Ruby object.
|
72
|
+
/*! This constructor is analogous to calling Data_Get_Struct. Uses
|
73
|
+
* Data_Type<T>::klass as the class of the object.
|
74
|
+
* \param value the Ruby object to unwrap.
|
75
|
+
*/
|
76
|
+
Data_Object(Object value);
|
77
|
+
|
78
|
+
//! Unwrap a Ruby object.
|
79
|
+
/*! This constructor is analogous to calling Data_Get_Struct. Will
|
80
|
+
* throw an exception if the class of the object differs from the
|
81
|
+
* specified class.
|
82
|
+
* \param value the Ruby object to unwrap.
|
83
|
+
* \param klass the expected class of the object.
|
84
|
+
*/
|
85
|
+
template<typename U>
|
86
|
+
Data_Object(Object value);
|
87
|
+
|
88
|
+
T& operator*() const; //!< Return a reference to obj_
|
89
|
+
T* operator->() const; //!< Return a pointer to obj_
|
90
|
+
T* get() const; //!< Return a pointer to obj_
|
91
|
+
|
92
|
+
private:
|
93
|
+
static void check_ruby_type(VALUE value);
|
132
94
|
};
|
133
|
-
}
|
134
|
-
|
135
95
|
} // namespace Rice
|
136
96
|
|
137
97
|
#endif // Rice__Data_Object_defn__hpp_
|
data/rice/Data_Type.hpp
CHANGED
data/rice/Data_Type.ipp
CHANGED
@@ -1,365 +1,321 @@
|
|
1
1
|
#ifndef Rice__Data_Type__ipp_
|
2
2
|
#define Rice__Data_Type__ipp_
|
3
3
|
|
4
|
+
#include "detail/method_data.hpp"
|
5
|
+
#include "detail/NativeAttribute.hpp"
|
6
|
+
#include "detail/default_allocation_func.hpp"
|
7
|
+
#include "detail/TypeRegistry.hpp"
|
8
|
+
#include "detail/Wrapper.hpp"
|
9
|
+
#include "detail/Iterator.hpp"
|
4
10
|
#include "Class.hpp"
|
5
11
|
#include "String.hpp"
|
6
|
-
#include "Data_Object.hpp"
|
7
|
-
#include "detail/default_allocation_func.hpp"
|
8
|
-
#include "detail/creation_funcs.hpp"
|
9
|
-
#include "detail/method_data.hpp"
|
10
|
-
#include "detail/Caster.hpp"
|
11
|
-
#include "detail/demangle.hpp"
|
12
12
|
|
13
13
|
#include <stdexcept>
|
14
|
-
#include <typeinfo>
|
15
14
|
|
16
|
-
|
17
|
-
|
15
|
+
namespace Rice
|
16
|
+
{
|
17
|
+
template<typename T>
|
18
|
+
void ruby_mark_internal(detail::Wrapper* wrapper)
|
19
|
+
{
|
20
|
+
// Tell the wrapper to mark the objects its keeping alive
|
21
|
+
wrapper->ruby_mark();
|
18
22
|
|
19
|
-
|
20
|
-
|
23
|
+
// Get the underlying data and call custom mark function (if any)
|
24
|
+
T* data = static_cast<T*>(wrapper->get());
|
25
|
+
ruby_mark<T>(data);
|
26
|
+
}
|
21
27
|
|
22
|
-
template<typename T>
|
23
|
-
|
24
|
-
inline Rice::Data_Type<T> Rice::Data_Type<T>::
|
25
|
-
bind(Module const & klass)
|
26
|
-
{
|
27
|
-
if(klass.value() == klass_)
|
28
|
+
template<typename T>
|
29
|
+
void ruby_free_internal(detail::Wrapper* wrapper)
|
28
30
|
{
|
29
|
-
|
31
|
+
delete wrapper;
|
30
32
|
}
|
31
33
|
|
32
|
-
|
34
|
+
template<typename T>
|
35
|
+
size_t ruby_size_internal(const T* data)
|
33
36
|
{
|
34
|
-
|
35
|
-
s = "Data type ";
|
36
|
-
s += detail::demangle(typeid(T).name());
|
37
|
-
s += " is already bound to a different type";
|
38
|
-
throw std::runtime_error(s.c_str());
|
37
|
+
return sizeof(T);
|
39
38
|
}
|
40
39
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
40
|
+
template<typename T>
|
41
|
+
template <typename Base_T>
|
42
|
+
inline Data_Type<T> Data_Type<T>::bind(Module const& klass)
|
43
|
+
{
|
44
|
+
if (is_bound())
|
45
|
+
{
|
46
|
+
std::string message = "Type " + detail::typeName(typeid(T)) + " is already bound to a different type";
|
47
|
+
throw std::runtime_error(message.c_str());
|
48
|
+
}
|
49
|
+
|
50
|
+
klass_ = klass;
|
45
51
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
+
rb_type_ = new rb_data_type_t();
|
53
|
+
rb_type_->wrap_struct_name = strdup(Rice::detail::protect(rb_class2name, klass_));
|
54
|
+
rb_type_->function.dmark = reinterpret_cast<void(*)(void*)>(&Rice::ruby_mark_internal<T>);
|
55
|
+
rb_type_->function.dfree = reinterpret_cast<void(*)(void*)>(&Rice::ruby_free_internal<T>);
|
56
|
+
rb_type_->function.dsize = reinterpret_cast<size_t(*)(const void*)>(&Rice::ruby_size_internal<T>);
|
57
|
+
rb_type_->data = nullptr;
|
58
|
+
rb_type_->flags = RUBY_TYPED_FREE_IMMEDIATELY;
|
52
59
|
|
53
|
-
|
60
|
+
if constexpr (!std::is_void_v<Base_T>)
|
61
|
+
{
|
62
|
+
rb_type_->parent = Data_Type<Base_T>::rb_type();
|
63
|
+
}
|
64
|
+
|
65
|
+
// Now register with the type registry
|
66
|
+
detail::TypeRegistry::add<T>(klass_, rb_type_);
|
67
|
+
|
68
|
+
for (typename Instances::iterator it = unbound_instances().begin(),
|
54
69
|
end = unbound_instances().end();
|
55
70
|
it != end;
|
56
71
|
unbound_instances().erase(it++))
|
72
|
+
{
|
73
|
+
(*it)->set_value(klass);
|
74
|
+
}
|
75
|
+
|
76
|
+
return Data_Type<T>();
|
77
|
+
}
|
78
|
+
|
79
|
+
template<typename T>
|
80
|
+
inline void Data_Type<T>::unbind()
|
57
81
|
{
|
58
|
-
(
|
82
|
+
detail::TypeRegistry::remove<T>();
|
83
|
+
|
84
|
+
if (klass_ != Qnil)
|
85
|
+
{
|
86
|
+
klass_ = Qnil;
|
87
|
+
}
|
88
|
+
|
89
|
+
// There could be objects floating around using the existing rb_type so
|
90
|
+
// do not delete it. This is of course a memory leak.
|
91
|
+
rb_type_ = nullptr;
|
59
92
|
}
|
60
93
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
94
|
+
template<typename T>
|
95
|
+
inline Data_Type<T>::Data_Type() : Class(klass_ == Qnil ? rb_cObject : klass_)
|
96
|
+
{
|
97
|
+
if (!is_bound())
|
98
|
+
{
|
99
|
+
unbound_instances().insert(this);
|
100
|
+
}
|
101
|
+
}
|
66
102
|
|
67
|
-
template<typename T>
|
68
|
-
inline
|
69
|
-
Data_Type()
|
70
|
-
: Module_impl<Data_Type_Base, Data_Type<T> >(
|
71
|
-
klass_ == Qnil ? rb_cObject : klass_)
|
72
|
-
{
|
73
|
-
if(!is_bound())
|
103
|
+
template<typename T>
|
104
|
+
inline Data_Type<T>::Data_Type(Module const& klass) : Class(klass)
|
74
105
|
{
|
75
|
-
|
106
|
+
this->bind(klass);
|
76
107
|
}
|
77
|
-
}
|
78
108
|
|
79
|
-
template<typename T>
|
80
|
-
inline
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
{
|
85
|
-
this->bind<void>(klass);
|
86
|
-
}
|
109
|
+
template<typename T>
|
110
|
+
inline Data_Type<T>::~Data_Type()
|
111
|
+
{
|
112
|
+
unbound_instances().erase(this);
|
113
|
+
}
|
87
114
|
|
88
|
-
template<typename T>
|
89
|
-
inline
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
}
|
115
|
+
template<typename T>
|
116
|
+
inline rb_data_type_t* Data_Type<T>::rb_type()
|
117
|
+
{
|
118
|
+
check_is_bound();
|
119
|
+
return rb_type_;
|
120
|
+
}
|
94
121
|
|
95
|
-
template<typename T>
|
96
|
-
|
97
|
-
Rice::Data_Type<T>::
|
98
|
-
klass() {
|
99
|
-
if(is_bound())
|
122
|
+
template<typename T>
|
123
|
+
inline Class Data_Type<T>::klass()
|
100
124
|
{
|
125
|
+
check_is_bound();
|
101
126
|
return klass_;
|
102
127
|
}
|
103
|
-
|
128
|
+
|
129
|
+
template<typename T>
|
130
|
+
inline Data_Type<T>& Data_Type<T>::operator=(Module const& klass)
|
104
131
|
{
|
105
|
-
|
106
|
-
|
107
|
-
s += " is unbound";
|
108
|
-
throw std::runtime_error(s.c_str());
|
132
|
+
this->bind(klass);
|
133
|
+
return *this;
|
109
134
|
}
|
110
|
-
}
|
111
135
|
|
112
|
-
template<typename T>
|
113
|
-
|
114
|
-
|
115
|
-
{
|
116
|
-
|
117
|
-
return *this;
|
118
|
-
}
|
119
|
-
|
120
|
-
template<typename T>
|
121
|
-
template<typename Constructor_T>
|
122
|
-
inline Rice::Data_Type<T> & Rice::Data_Type<T>::
|
123
|
-
define_constructor(
|
124
|
-
Constructor_T /* constructor */,
|
125
|
-
Arguments* arguments)
|
126
|
-
{
|
127
|
-
check_is_bound();
|
128
|
-
|
129
|
-
// Normal constructor pattern with new/initialize
|
130
|
-
rb_define_alloc_func(
|
131
|
-
static_cast<VALUE>(*this),
|
132
|
-
detail::default_allocation_func<T>);
|
133
|
-
this->define_method(
|
134
|
-
"initialize",
|
135
|
-
&Constructor_T::construct,
|
136
|
-
arguments
|
137
|
-
);
|
138
|
-
|
139
|
-
return *this;
|
140
|
-
}
|
136
|
+
template<typename T>
|
137
|
+
template<typename Constructor_T>
|
138
|
+
inline Data_Type<T>& Data_Type<T>::define_constructor(Constructor_T, MethodInfo* methodInfo)
|
139
|
+
{
|
140
|
+
check_is_bound();
|
141
141
|
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
define_constructor(
|
146
|
-
Constructor_T constructor,
|
147
|
-
Arg const& arg)
|
148
|
-
{
|
149
|
-
Arguments* args = new Arguments();
|
150
|
-
args->add(arg);
|
151
|
-
return define_constructor(constructor, args);
|
152
|
-
}
|
142
|
+
// Normal constructor pattern with new/initialize
|
143
|
+
detail::protect(rb_define_alloc_func, static_cast<VALUE>(*this), detail::default_allocation_func<T>);
|
144
|
+
this->define_method("initialize", &Constructor_T::construct, methodInfo);
|
153
145
|
|
146
|
+
return *this;
|
147
|
+
}
|
154
148
|
|
155
|
-
template<typename T>
|
156
|
-
template<typename
|
157
|
-
inline
|
158
|
-
|
159
|
-
|
160
|
-
Rice::Data_Type<Director_T>::template bind<T>(*this);
|
161
|
-
return *this;
|
162
|
-
}
|
149
|
+
template<typename T>
|
150
|
+
template<typename Constructor_T, typename...Arg_Ts>
|
151
|
+
inline Data_Type<T>& Data_Type<T>::define_constructor(Constructor_T constructor, Arg_Ts const& ...args)
|
152
|
+
{
|
153
|
+
check_is_bound();
|
163
154
|
|
164
|
-
|
165
|
-
|
166
|
-
from_ruby(Object x)
|
167
|
-
{
|
168
|
-
check_is_bound();
|
155
|
+
// Define a Ruby allocator which creates the Ruby object
|
156
|
+
detail::protect(rb_define_alloc_func, static_cast<VALUE>(*this), detail::default_allocation_func<T>);
|
169
157
|
|
170
|
-
|
171
|
-
|
158
|
+
// Define an initialize function that will create the C++ object
|
159
|
+
this->define_method("initialize", &Constructor_T::construct, args...);
|
172
160
|
|
173
|
-
|
174
|
-
{
|
175
|
-
// Great, not converting to a base/derived type
|
176
|
-
Data_Type<T> data_klass;
|
177
|
-
Data_Object<T> obj(x, data_klass);
|
178
|
-
return obj.get();
|
161
|
+
return *this;
|
179
162
|
}
|
180
163
|
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
// 1) casters that handle this direct type
|
189
|
-
// 2) casters that handle types that are ancestors of klass
|
190
|
-
//
|
191
|
-
// Step 2 allows us to handle the case where a Rice-wrapped class
|
192
|
-
// is subclassed in Ruby but then an instance of that class is passed
|
193
|
-
// back into C++ (say, in a Listener / callback construction)
|
194
|
-
//
|
195
|
-
|
196
|
-
VALUE ancestors = rb_mod_ancestors(klass.value());
|
197
|
-
|
198
|
-
long earliest = RARRAY_LEN(ancestors) + 1;
|
199
|
-
|
200
|
-
int index;
|
201
|
-
VALUE indexFound;
|
202
|
-
Data_Type_Base::Casters::const_iterator toUse = end;
|
203
|
-
|
204
|
-
for(; it != end; it++) {
|
205
|
-
// Do we match directly?
|
206
|
-
if(klass.value() == it->first) {
|
207
|
-
toUse = it;
|
208
|
-
break;
|
164
|
+
template<typename T>
|
165
|
+
template<typename Director_T>
|
166
|
+
inline Data_Type<T>& Data_Type<T>::define_director()
|
167
|
+
{
|
168
|
+
if (!detail::TypeRegistry::isDefined<Director_T>())
|
169
|
+
{
|
170
|
+
Data_Type<Director_T>::bind(*this);
|
209
171
|
}
|
210
172
|
|
211
|
-
//
|
212
|
-
//
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
indexFound = rb_funcall(ancestors, rb_intern("index"), 1, it->first);
|
173
|
+
// TODO - hack to fake Ruby into thinking that a Director is
|
174
|
+
// the same as the base data type
|
175
|
+
Data_Type<Director_T>::rb_type_ = Data_Type<T>::rb_type_;
|
176
|
+
return *this;
|
177
|
+
}
|
217
178
|
|
218
|
-
|
219
|
-
|
179
|
+
template<typename T>
|
180
|
+
inline bool Data_Type<T>::is_bound()
|
181
|
+
{
|
182
|
+
return klass_ != Qnil;
|
183
|
+
}
|
220
184
|
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
185
|
+
template<typename T>
|
186
|
+
inline bool Data_Type<T>::is_descendant(VALUE value)
|
187
|
+
{
|
188
|
+
check_is_bound();
|
189
|
+
return detail::protect(rb_obj_is_kind_of, value, klass_) == Qtrue;
|
190
|
+
}
|
191
|
+
|
192
|
+
template<typename T>
|
193
|
+
inline void Data_Type<T>::check_is_bound()
|
194
|
+
{
|
195
|
+
if (!is_bound())
|
196
|
+
{
|
197
|
+
std::string message = "Type " + detail::typeName(typeid(T)) + " is not bound";
|
198
|
+
throw std::runtime_error(message.c_str());
|
225
199
|
}
|
226
200
|
}
|
227
|
-
|
228
|
-
|
201
|
+
|
202
|
+
template<typename T, typename Base_T>
|
203
|
+
inline Data_Type<T> define_class_under(Object module, char const* name)
|
229
204
|
{
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
205
|
+
if (detail::TypeRegistry::isDefined<T>())
|
206
|
+
{
|
207
|
+
return Data_Type<T>();
|
208
|
+
}
|
209
|
+
|
210
|
+
Class superKlass;
|
211
|
+
|
212
|
+
if constexpr (std::is_void_v<Base_T>)
|
213
|
+
{
|
214
|
+
superKlass = rb_cObject;
|
215
|
+
}
|
216
|
+
else
|
217
|
+
{
|
218
|
+
superKlass = Data_Type<Base_T>::klass();
|
219
|
+
}
|
220
|
+
|
221
|
+
Class c = define_class_under(module, name, superKlass);
|
222
|
+
c.undef_creation_funcs();
|
223
|
+
return Data_Type<T>::template bind<Base_T>(c);
|
234
224
|
}
|
235
225
|
|
236
|
-
|
237
|
-
|
226
|
+
template<typename T, typename Base_T>
|
227
|
+
inline Data_Type<T> define_class(char const* name)
|
238
228
|
{
|
239
|
-
|
240
|
-
|
229
|
+
if (detail::TypeRegistry::isDefined<T>())
|
230
|
+
{
|
231
|
+
return Data_Type<T>();
|
232
|
+
}
|
233
|
+
|
234
|
+
Class superKlass;
|
235
|
+
if constexpr (std::is_void_v<Base_T>)
|
236
|
+
{
|
237
|
+
superKlass = rb_cObject;
|
238
|
+
}
|
239
|
+
else
|
240
|
+
{
|
241
|
+
superKlass = Data_Type<Base_T>::klass();
|
242
|
+
}
|
243
|
+
|
244
|
+
Class c = define_class(name, superKlass);
|
245
|
+
c.undef_creation_funcs();
|
246
|
+
return Data_Type<T>::template bind<Base_T>(c);
|
241
247
|
}
|
242
|
-
|
248
|
+
|
249
|
+
template<typename T>
|
250
|
+
template<typename U, typename Iterator_T>
|
251
|
+
inline Data_Type<T>& Data_Type<T>::define_iterator(Iterator_T(U::* begin)(), Iterator_T(U::* end)(), Identifier name)
|
243
252
|
{
|
244
|
-
|
253
|
+
using Iter_T = detail::Iterator<U, Iterator_T>;
|
254
|
+
Iter_T* iterator = new Iter_T(begin, end);
|
255
|
+
detail::MethodData::define_method(Data_Type<T>::klass(), name,
|
256
|
+
(RUBY_METHOD_FUNC)iterator->call, 0, iterator);
|
257
|
+
|
258
|
+
return *this;
|
245
259
|
}
|
246
|
-
}
|
247
260
|
|
248
|
-
template<typename T>
|
249
|
-
|
250
|
-
|
251
|
-
{
|
252
|
-
|
253
|
-
|
261
|
+
template <typename T>
|
262
|
+
template <typename Attr_T>
|
263
|
+
inline Data_Type<T>& Data_Type<T>::define_attr(std::string name, Attr_T attr, AttrAccess access)
|
264
|
+
{
|
265
|
+
auto* native = detail::Make_Native_Attribute(attr, access);
|
266
|
+
using Native_T = typename std::remove_pointer_t<decltype(native)>;
|
254
267
|
|
255
|
-
|
256
|
-
inline Rice::detail::Abstract_Caster * Rice::Data_Type<T>::
|
257
|
-
caster() const
|
258
|
-
{
|
259
|
-
check_is_bound();
|
260
|
-
return caster_.get();
|
261
|
-
}
|
268
|
+
detail::verifyType<typename Native_T::Native_Return_T>();
|
262
269
|
|
263
|
-
|
264
|
-
{
|
270
|
+
if (access == AttrAccess::ReadWrite || access == AttrAccess::Read)
|
271
|
+
{
|
272
|
+
detail::MethodData::define_method( klass_, Identifier(name).id(),
|
273
|
+
RUBY_METHOD_FUNC(&Native_T::get), 0, native);
|
274
|
+
}
|
265
275
|
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
{
|
270
|
-
|
271
|
-
}
|
276
|
+
if (access == AttrAccess::ReadWrite || access == AttrAccess::Write)
|
277
|
+
{
|
278
|
+
if (std::is_const_v<std::remove_pointer_t<Attr_T>>)
|
279
|
+
{
|
280
|
+
throw std::runtime_error(name + " is readonly");
|
281
|
+
}
|
272
282
|
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
{
|
279
|
-
std::string s;
|
280
|
-
s = "Data type ";
|
281
|
-
s += detail::demangle(typeid(T).name());
|
282
|
-
s += " is not bound";
|
283
|
-
throw std::runtime_error(s.c_str());
|
283
|
+
detail::MethodData::define_method( klass_, Identifier(name + "=").id(),
|
284
|
+
RUBY_METHOD_FUNC(&Native_T::set), 1, native);
|
285
|
+
}
|
286
|
+
|
287
|
+
return *this;
|
284
288
|
}
|
285
|
-
}
|
286
289
|
|
287
|
-
|
290
|
+
template <typename T>
|
291
|
+
template <typename Attr_T>
|
292
|
+
inline Data_Type<T>& Data_Type<T>::define_singleton_attr(std::string name, Attr_T attr, AttrAccess access)
|
293
|
+
{
|
294
|
+
auto* native = detail::Make_Native_Attribute(attr, access);
|
295
|
+
using Native_T = typename std::remove_pointer_t<decltype(native)>;
|
288
296
|
|
289
|
-
|
290
|
-
inline Rice::Data_Type<T> Rice::
|
291
|
-
define_class_under(
|
292
|
-
Object module,
|
293
|
-
char const * name)
|
294
|
-
{
|
295
|
-
Class c(define_class_under(module, name, rb_cObject));
|
296
|
-
c.undef_creation_funcs();
|
297
|
-
return Data_Type<T>::template bind<void>(c);
|
298
|
-
}
|
297
|
+
detail::verifyType<typename Native_T::Native_Return_T>();
|
299
298
|
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
Data_Type<Base_T> base_dt;
|
307
|
-
Class c(define_class_under(module, name, base_dt));
|
308
|
-
c.undef_creation_funcs();
|
309
|
-
return Data_Type<T>::template bind<Base_T>(c);
|
310
|
-
}
|
299
|
+
if (access == AttrAccess::ReadWrite || access == AttrAccess::Read)
|
300
|
+
{
|
301
|
+
VALUE singleton = detail::protect(rb_singleton_class, this->value());
|
302
|
+
detail::MethodData::define_method(singleton, Identifier(name).id(),
|
303
|
+
RUBY_METHOD_FUNC(&Native_T::get), 0, native);
|
304
|
+
}
|
311
305
|
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
c.undef_creation_funcs();
|
319
|
-
return Data_Type<T>::template bind<void>(c);
|
320
|
-
}
|
306
|
+
if (access == AttrAccess::ReadWrite || access == AttrAccess::Write)
|
307
|
+
{
|
308
|
+
if (std::is_const_v<std::remove_pointer_t<Attr_T>>)
|
309
|
+
{
|
310
|
+
throw std::runtime_error(name + " is readonly");
|
311
|
+
}
|
321
312
|
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
{
|
327
|
-
Data_Type<Base_T> base_dt;
|
328
|
-
Class c(define_class(name, base_dt));
|
329
|
-
c.undef_creation_funcs();
|
330
|
-
return Data_Type<T>::template bind<Base_T>(c);
|
331
|
-
}
|
313
|
+
VALUE singleton = detail::protect(rb_singleton_class, this->value());
|
314
|
+
detail::MethodData::define_method(singleton, Identifier(name + "=").id(),
|
315
|
+
RUBY_METHOD_FUNC(&Native_T::set), 1, native);
|
316
|
+
}
|
332
317
|
|
333
|
-
|
334
|
-
|
335
|
-
Rice::define_implicit_cast()
|
336
|
-
{
|
337
|
-
// As Rice currently expects only one entry into
|
338
|
-
// this list for a given klass VALUE, we need to get
|
339
|
-
// the current caster for From_T and insert in our
|
340
|
-
// new caster as the head of the caster list
|
341
|
-
|
342
|
-
Class from_class = Data_Type<From_T>::klass().value();
|
343
|
-
Class to_class = Data_Type<To_T>::klass().value();
|
344
|
-
|
345
|
-
detail::Abstract_Caster* from_caster =
|
346
|
-
Data_Type<From_T>::caster_.release();
|
347
|
-
|
348
|
-
detail::Abstract_Caster* new_caster =
|
349
|
-
new detail::Implicit_Caster<To_T, From_T>(from_caster, to_class);
|
350
|
-
|
351
|
-
// Insert our new caster into the list for the from class
|
352
|
-
Data_Type_Base::casters().erase(from_class);
|
353
|
-
Data_Type_Base::casters().insert(
|
354
|
-
std::make_pair(
|
355
|
-
from_class,
|
356
|
-
new_caster
|
357
|
-
)
|
358
|
-
);
|
359
|
-
|
360
|
-
// And make sure the from_class has direct access to the
|
361
|
-
// updated caster list
|
362
|
-
Data_Type<From_T>::caster_.reset(new_caster);
|
318
|
+
return *this;
|
319
|
+
}
|
363
320
|
}
|
364
|
-
|
365
|
-
#endif // Rice__Data_Type__ipp_
|
321
|
+
#endif
|