rice 4.6.1 → 4.7.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 +31 -0
- data/CMakeLists.txt +0 -4
- data/Rakefile +2 -8
- data/bin/rice-doc.rb +212 -0
- data/bin/rice-rbs.rb +93 -0
- data/include/rice/rice.hpp +4972 -4015
- data/include/rice/stl.hpp +822 -294
- data/lib/rice/doc/cpp_reference.rb +166 -0
- data/lib/rice/doc/doxygen.rb +294 -0
- data/lib/rice/doc/mkdocs.rb +298 -0
- data/lib/rice/doc/rice.rb +29 -0
- data/lib/rice/doc/ruby.rb +37 -0
- data/lib/rice/doc.rb +5 -0
- data/lib/{make_rice_headers.rb → rice/make_rice_headers.rb} +3 -0
- data/lib/rice/native.rb +18 -0
- data/lib/rice/native_registry.rb +21 -0
- data/lib/rice/parameter.rb +7 -0
- data/lib/rice/rbs.rb +104 -0
- data/lib/rice/version.rb +1 -1
- data/lib/rice.rb +4 -0
- data/lib/rubygems/cmake_builder.rb +24 -27
- data/rice/Arg.hpp +4 -4
- data/rice/Arg.ipp +4 -4
- data/rice/Buffer.hpp +32 -28
- data/rice/Buffer.ipp +306 -178
- data/rice/Data_Object.ipp +101 -82
- data/rice/Data_Type.hpp +5 -7
- data/rice/Data_Type.ipp +48 -29
- data/rice/Enum.ipp +15 -21
- data/rice/Function.hpp +17 -0
- data/rice/Function.ipp +13 -0
- data/rice/Pointer.hpp +15 -0
- data/rice/Pointer.ipp +49 -0
- data/rice/Return.hpp +1 -1
- data/rice/Return.ipp +2 -2
- data/rice/api.hpp +30 -0
- data/rice/cpp_api/Array.hpp +2 -2
- data/rice/cpp_api/Array.ipp +50 -5
- data/rice/cpp_api/Class.hpp +0 -5
- data/rice/cpp_api/Class.ipp +19 -0
- data/rice/cpp_api/Hash.ipp +20 -0
- data/rice/cpp_api/Module.hpp +6 -3
- data/rice/cpp_api/Module.ipp +49 -11
- data/rice/cpp_api/Object.ipp +31 -2
- data/rice/cpp_api/String.hpp +1 -2
- data/rice/cpp_api/String.ipp +21 -1
- data/rice/cpp_api/Struct.ipp +5 -0
- data/rice/cpp_api/Symbol.ipp +34 -0
- data/rice/cpp_api/shared_methods.hpp +12 -12
- data/rice/detail/MethodInfo.hpp +4 -2
- data/rice/detail/MethodInfo.ipp +19 -3
- data/rice/detail/ModuleRegistry.hpp +18 -0
- data/rice/detail/ModuleRegistry.ipp +25 -0
- data/rice/detail/Native.hpp +45 -2
- data/rice/detail/Native.ipp +196 -2
- data/rice/detail/NativeAttributeGet.hpp +9 -4
- data/rice/detail/NativeAttributeGet.ipp +65 -11
- data/rice/detail/NativeAttributeSet.hpp +4 -0
- data/rice/detail/NativeAttributeSet.ipp +30 -2
- data/rice/detail/NativeCallbackFFI.ipp +2 -2
- data/rice/detail/NativeCallbackSimple.ipp +1 -1
- data/rice/detail/NativeFunction.hpp +11 -49
- data/rice/detail/NativeFunction.ipp +82 -379
- data/rice/detail/NativeInvoker.hpp +74 -0
- data/rice/detail/NativeInvoker.ipp +197 -0
- data/rice/detail/NativeIterator.hpp +4 -0
- data/rice/detail/NativeIterator.ipp +19 -0
- data/rice/detail/NativeMethod.hpp +97 -0
- data/rice/detail/NativeMethod.ipp +332 -0
- data/rice/detail/NativeProc.hpp +51 -0
- data/rice/detail/NativeProc.ipp +133 -0
- data/rice/detail/NativeRegistry.hpp +8 -0
- data/rice/detail/NativeRegistry.ipp +27 -0
- data/rice/detail/Parameter.hpp +47 -0
- data/rice/detail/Parameter.ipp +105 -0
- data/rice/detail/Proc.ipp +14 -13
- data/rice/detail/Registries.hpp +1 -0
- data/rice/detail/RubyType.hpp +0 -2
- data/rice/detail/RubyType.ipp +15 -33
- data/rice/detail/Type.hpp +44 -8
- data/rice/detail/Type.ipp +151 -49
- data/rice/detail/TypeRegistry.hpp +3 -0
- data/rice/detail/TypeRegistry.ipp +17 -27
- data/rice/detail/Types.ipp +430 -0
- data/rice/detail/Wrapper.hpp +12 -0
- data/rice/detail/Wrapper.ipp +45 -2
- data/rice/detail/from_ruby.ipp +567 -1073
- data/rice/detail/ruby.hpp +1 -0
- data/rice/detail/to_ruby.ipp +4 -635
- data/rice/libc/file.ipp +3 -6
- data/rice/rice.hpp +22 -12
- data/rice/rice_api/Arg.hpp +7 -0
- data/rice/rice_api/Arg.ipp +9 -0
- data/rice/rice_api/ModuleRegistry.hpp +7 -0
- data/rice/rice_api/ModuleRegistry.ipp +10 -0
- data/rice/rice_api/Native.hpp +7 -0
- data/rice/rice_api/Native.ipp +52 -0
- data/rice/rice_api/NativeRegistry.hpp +7 -0
- data/rice/rice_api/NativeRegistry.ipp +21 -0
- data/rice/rice_api/Parameter.hpp +7 -0
- data/rice/rice_api/Parameter.ipp +11 -0
- data/rice/rice_api/Registries.hpp +6 -0
- data/rice/rice_api/Registries.ipp +12 -0
- data/rice/rice_api/TypeRegistry.hpp +7 -0
- data/rice/rice_api/TypeRegistry.ipp +10 -0
- data/rice/stl/complex.ipp +35 -0
- data/rice/stl/exception.ipp +20 -7
- data/rice/stl/filesystem.hpp +6 -0
- data/rice/stl/filesystem.ipp +34 -0
- data/rice/stl/map.ipp +13 -21
- data/rice/stl/monostate.ipp +37 -1
- data/rice/stl/multimap.ipp +17 -24
- data/rice/stl/optional.ipp +47 -2
- data/rice/stl/pair.ipp +23 -58
- data/rice/stl/reference_wrapper.ipp +22 -1
- data/rice/stl/set.ipp +17 -9
- data/rice/stl/shared_ptr.ipp +44 -17
- data/rice/stl/string.ipp +175 -7
- data/rice/stl/string_view.ipp +5 -0
- data/rice/stl/tuple.ipp +38 -9
- data/rice/stl/unique_ptr.ipp +46 -2
- data/rice/stl/unordered_map.ipp +13 -21
- data/rice/stl/variant.ipp +47 -11
- data/rice/stl/vector.ipp +183 -104
- data/rice/stl.hpp +1 -0
- data/rice/traits/function_traits.hpp +2 -2
- data/rice/traits/method_traits.hpp +5 -16
- data/rice/traits/rice_traits.hpp +24 -4
- data/rice.gemspec +11 -22
- data/test/embed_ruby.cpp +0 -3
- data/test/test_Array.cpp +38 -38
- data/test/test_Attribute.cpp +187 -2
- data/test/test_Buffer.cpp +302 -26
- data/test/test_Callback.cpp +2 -3
- data/test/test_Class.cpp +5 -5
- data/test/test_Data_Object.cpp +0 -55
- data/test/test_Data_Type.cpp +19 -30
- data/test/test_Enum.cpp +4 -46
- data/test/test_From_Ruby.cpp +88 -81
- data/test/test_GVL.cpp +109 -0
- data/test/test_Iterator.cpp +1 -1
- data/test/test_Keep_Alive_No_Wrapper.cpp +5 -3
- data/test/test_Module.cpp +8 -9
- data/test/test_Object.cpp +1 -1
- data/test/test_Overloads.cpp +3 -3
- data/test/test_Stl_Map.cpp +8 -8
- data/test/test_Stl_Multimap.cpp +4 -4
- data/test/test_Stl_Pair.cpp +5 -3
- data/test/test_Stl_SharedPtr.cpp +24 -12
- data/test/test_Stl_Tuple.cpp +1 -1
- data/test/test_Stl_UniquePtr.cpp +8 -0
- data/test/test_Stl_Unordered_Map.cpp +9 -9
- data/test/test_Stl_Variant.cpp +9 -3
- data/test/test_Stl_Vector.cpp +118 -13
- data/test/test_To_Ruby.cpp +35 -28
- data/test/test_Type.cpp +256 -53
- data/test/unittest.hpp +35 -0
- metadata +66 -34
- data/rice/Init.hpp +0 -8
- data/rice/Init.ipp +0 -8
- data/rice/detail/RubyFunction.hpp +0 -31
- data/rice/detail/RubyFunction.ipp +0 -77
- data/sample/callbacks/extconf.rb +0 -5
- data/sample/callbacks/sample_callbacks.cpp +0 -35
- data/sample/callbacks/test.rb +0 -28
- data/sample/enum/extconf.rb +0 -5
- data/sample/enum/sample_enum.cpp +0 -40
- data/sample/enum/test.rb +0 -8
- data/sample/inheritance/animals.cpp +0 -82
- data/sample/inheritance/extconf.rb +0 -5
- data/sample/inheritance/test.rb +0 -7
- data/sample/map/extconf.rb +0 -5
- data/sample/map/map.cpp +0 -73
- data/sample/map/test.rb +0 -7
- data/test/ext/t1/Foo.hpp +0 -10
- data/test/ext/t1/extconf.rb +0 -4
- data/test/ext/t1/t1.cpp +0 -13
- data/test/ext/t2/extconf.rb +0 -4
- data/test/ext/t2/t2.cpp +0 -11
- data/test/ruby/test_callbacks_sample.rb +0 -28
- data/test/ruby/test_multiple_extensions.rb +0 -18
- data/test/ruby/test_multiple_extensions_same_class.rb +0 -14
- data/test/ruby/test_multiple_extensions_with_inheritance.rb +0 -20
- /data/test/{test_Stl_Type.cpp → test_Stl_Type_Info.cpp} +0 -0
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
#ifndef Rice__detail__native_invoker__hpp_
|
|
2
|
+
#define Rice__detail__native_invoker__hpp_
|
|
3
|
+
|
|
4
|
+
#include <optional>
|
|
5
|
+
|
|
6
|
+
namespace Rice::detail
|
|
7
|
+
{
|
|
8
|
+
template<typename Return_T>
|
|
9
|
+
class ResultWrapper
|
|
10
|
+
{
|
|
11
|
+
public:
|
|
12
|
+
std::exception_ptr exception;
|
|
13
|
+
Return_T getResult();
|
|
14
|
+
void setResult(Return_T&& value);
|
|
15
|
+
private:
|
|
16
|
+
std::optional<Return_T> result_;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
template<typename Return_T>
|
|
20
|
+
class ResultWrapper<Return_T&>
|
|
21
|
+
{
|
|
22
|
+
public:
|
|
23
|
+
std::exception_ptr exception;
|
|
24
|
+
Return_T& getResult();
|
|
25
|
+
void setResult(Return_T& value);
|
|
26
|
+
private:
|
|
27
|
+
std::optional<std::reference_wrapper<Return_T>> result_;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
template<typename Return_T>
|
|
31
|
+
class ResultWrapper<Return_T*>
|
|
32
|
+
{
|
|
33
|
+
public:
|
|
34
|
+
std::exception_ptr exception;
|
|
35
|
+
|
|
36
|
+
Return_T* getResult();
|
|
37
|
+
void setResult(Return_T* value);
|
|
38
|
+
private:
|
|
39
|
+
Return_T* result_;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
template<>
|
|
43
|
+
class ResultWrapper<void>
|
|
44
|
+
{
|
|
45
|
+
public:
|
|
46
|
+
std::exception_ptr exception;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
template<typename Return_T, typename Function_T, typename Tuple_T>
|
|
50
|
+
class NativeInvoker
|
|
51
|
+
{
|
|
52
|
+
public:
|
|
53
|
+
const Function_T func;
|
|
54
|
+
Tuple_T args;
|
|
55
|
+
public:
|
|
56
|
+
NativeInvoker(const Function_T func, Tuple_T&& args);
|
|
57
|
+
void invoke();
|
|
58
|
+
Return_T result();
|
|
59
|
+
std::exception_ptr exception();
|
|
60
|
+
private:
|
|
61
|
+
ResultWrapper<Return_T> resultWrapper;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
template<typename Function_T, typename ...Arg_Ts>
|
|
65
|
+
auto protect(Function_T func, Arg_Ts...args);
|
|
66
|
+
|
|
67
|
+
template<typename Function_T, typename ...Arg_Ts>
|
|
68
|
+
typename function_traits<Function_T>::return_type no_gvl(Function_T func, Arg_Ts...args);
|
|
69
|
+
|
|
70
|
+
template<typename Function_T, typename Tuple_T>
|
|
71
|
+
typename function_traits<Function_T>::return_type no_gvl(Function_T func, Tuple_T&& args);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
#endif // Rice__detail__native_invoker__hpp_
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
namespace Rice::detail
|
|
2
|
+
{
|
|
3
|
+
// ----- ResultWrapper -------
|
|
4
|
+
template<typename Return_T>
|
|
5
|
+
inline Return_T ResultWrapper<Return_T>::getResult()
|
|
6
|
+
{
|
|
7
|
+
if constexpr (!std::is_copy_constructible_v<Return_T> && std::is_move_constructible_v<Return_T>)
|
|
8
|
+
{
|
|
9
|
+
return std::move(this->result_.value());
|
|
10
|
+
}
|
|
11
|
+
// std::is_copy_constructible_v<std::vector<std::unique_ptr<T>>>> return true. Sigh.
|
|
12
|
+
else if constexpr (detail::is_std_vector_v<Return_T> && std::is_copy_constructible_v<Return_T>)
|
|
13
|
+
{
|
|
14
|
+
if constexpr (!std::is_copy_constructible_v<typename Return_T::value_type>)
|
|
15
|
+
{
|
|
16
|
+
return std::move(this->result_.value());
|
|
17
|
+
}
|
|
18
|
+
else
|
|
19
|
+
{
|
|
20
|
+
return this->result_.value();
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
else
|
|
24
|
+
{
|
|
25
|
+
return this->result_.value();
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
template<typename Return_T>
|
|
30
|
+
inline void ResultWrapper<Return_T>::setResult(Return_T&& value)
|
|
31
|
+
{
|
|
32
|
+
if constexpr(std::is_copy_assignable_v<Return_T> || std::is_move_assignable_v<Return_T>)
|
|
33
|
+
{
|
|
34
|
+
this->result_ = std::forward<Return_T>(value);
|
|
35
|
+
}
|
|
36
|
+
else if constexpr (std::is_copy_constructible_v<Return_T>)
|
|
37
|
+
{
|
|
38
|
+
this->result_.emplace(value);
|
|
39
|
+
}
|
|
40
|
+
else if constexpr (std::is_move_constructible_v<Return_T>)
|
|
41
|
+
{
|
|
42
|
+
this->result_.emplace(std::move(value));
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
template<typename Return_T>
|
|
47
|
+
inline Return_T& ResultWrapper<Return_T&>::getResult()
|
|
48
|
+
{
|
|
49
|
+
return this->result_.value().get();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
template<typename Return_T>
|
|
53
|
+
inline void ResultWrapper<Return_T&>::setResult(Return_T& value)
|
|
54
|
+
{
|
|
55
|
+
this->result_ = value;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
template<typename Return_T>
|
|
59
|
+
inline Return_T* ResultWrapper<Return_T*>::getResult()
|
|
60
|
+
{
|
|
61
|
+
return this->result_;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
template<typename Return_T>
|
|
65
|
+
inline void ResultWrapper<Return_T*>::setResult(Return_T* value)
|
|
66
|
+
{
|
|
67
|
+
this->result_ = value;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// ----- Invoker -------
|
|
71
|
+
template<typename Return_T, typename Function_T, typename Tuple_T>
|
|
72
|
+
inline NativeInvoker<Return_T, Function_T, Tuple_T>::NativeInvoker(const Function_T func, Tuple_T&& args)
|
|
73
|
+
: func(func), args(std::forward<Tuple_T>(args))
|
|
74
|
+
{
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
template<typename Return_T, typename Function_T, typename Tuple_T>
|
|
78
|
+
inline void NativeInvoker<Return_T, Function_T, Tuple_T>::invoke()
|
|
79
|
+
{
|
|
80
|
+
try
|
|
81
|
+
{
|
|
82
|
+
if constexpr (std::is_void_v<Return_T>)
|
|
83
|
+
{
|
|
84
|
+
std::apply(this->func, std::forward<Tuple_T>(this->args));
|
|
85
|
+
}
|
|
86
|
+
else if constexpr (!std::is_pointer_v<Return_T> && !std::is_reference_v<Return_T> && !std::is_copy_assignable_v<Return_T> && std::is_move_assignable_v<Return_T>)
|
|
87
|
+
{
|
|
88
|
+
this->resultWrapper.setResult(std::move(std::apply(this->func, std::forward<Tuple_T>(this->args))));
|
|
89
|
+
}
|
|
90
|
+
else
|
|
91
|
+
{
|
|
92
|
+
this->resultWrapper.setResult(std::forward<Return_T>(std::apply(this->func, std::forward<Tuple_T>(this->args))));
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
catch (...)
|
|
96
|
+
{
|
|
97
|
+
this->resultWrapper.exception = std::current_exception();
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
template<typename Return_T, typename Function_T, typename Tuple_T>
|
|
102
|
+
inline Return_T NativeInvoker<Return_T, Function_T, Tuple_T>::result()
|
|
103
|
+
{
|
|
104
|
+
return this->resultWrapper.getResult();
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
template<typename Return_T, typename Function_T, typename Tuple_T>
|
|
108
|
+
inline std::exception_ptr NativeInvoker<Return_T, Function_T, Tuple_T>::exception()
|
|
109
|
+
{
|
|
110
|
+
return this->resultWrapper.exception;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// ------- Helper Methods --------
|
|
114
|
+
// Create a functor for calling a Ruby function and define some aliases for readability.
|
|
115
|
+
template<typename Function_T, typename ...Arg_Ts>
|
|
116
|
+
auto protect(Function_T func, Arg_Ts...args)
|
|
117
|
+
{
|
|
118
|
+
using Return_T = typename function_traits<Function_T>::return_type;
|
|
119
|
+
using Tuple_T = std::tuple<Arg_Ts...>;
|
|
120
|
+
using Invoker_T = NativeInvoker<Return_T, Function_T, Tuple_T>;
|
|
121
|
+
|
|
122
|
+
Tuple_T argsTuple = std::forward_as_tuple(args...);
|
|
123
|
+
Invoker_T invoker(func, std::forward<Tuple_T>(argsTuple));
|
|
124
|
+
|
|
125
|
+
auto trampoline = [](VALUE value) -> VALUE
|
|
126
|
+
{
|
|
127
|
+
Invoker_T* function = (Invoker_T*)value;
|
|
128
|
+
|
|
129
|
+
function->invoke();
|
|
130
|
+
return Qnil;
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
// Create Invoker and call it via ruby
|
|
134
|
+
int state = (int)JumpException::RUBY_TAG_NONE;
|
|
135
|
+
rb_protect(trampoline, (VALUE)(&invoker), &state);
|
|
136
|
+
|
|
137
|
+
// Did anything go wrong?
|
|
138
|
+
if (state == JumpException::RUBY_TAG_NONE)
|
|
139
|
+
{
|
|
140
|
+
if constexpr (!std::is_same_v<Return_T, void>)
|
|
141
|
+
{
|
|
142
|
+
return invoker.result();
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
else
|
|
146
|
+
{
|
|
147
|
+
VALUE err = rb_errinfo();
|
|
148
|
+
if (state == JumpException::RUBY_TAG_RAISE && RB_TEST(err))
|
|
149
|
+
{
|
|
150
|
+
rb_set_errinfo(Qnil);
|
|
151
|
+
throw Rice::Exception(err);
|
|
152
|
+
}
|
|
153
|
+
else
|
|
154
|
+
{
|
|
155
|
+
throw Rice::JumpException((Rice::JumpException::ruby_tag_type)state);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
template<typename Function_T, typename ...Arg_Ts>
|
|
161
|
+
typename function_traits<Function_T>::return_type no_gvl(Function_T func, Arg_Ts...args)
|
|
162
|
+
{
|
|
163
|
+
using Tuple_T = std::tuple<Arg_Ts...>;
|
|
164
|
+
Tuple_T argsTuple = std::forward_as_tuple(args...);
|
|
165
|
+
return no_gvl(func, argsTuple);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
template<typename Function_T, typename Tuple_T>
|
|
169
|
+
typename function_traits<Function_T>::return_type no_gvl(Function_T func, Tuple_T&& args)
|
|
170
|
+
{
|
|
171
|
+
using Return_T = typename function_traits<Function_T>::return_type;
|
|
172
|
+
using Invoker_T = NativeInvoker<Return_T, Function_T, Tuple_T>;
|
|
173
|
+
|
|
174
|
+
Invoker_T invoker(func, std::forward<Tuple_T>(args));
|
|
175
|
+
|
|
176
|
+
auto trampoline = [](void* functor) -> void*
|
|
177
|
+
{
|
|
178
|
+
Invoker_T* function = (Invoker_T*)functor;
|
|
179
|
+
function->invoke();
|
|
180
|
+
|
|
181
|
+
if (function->exception())
|
|
182
|
+
{
|
|
183
|
+
std::rethrow_exception(function->exception());
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
return nullptr;
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
// Create Invoker and call it via ruby
|
|
190
|
+
rb_thread_call_without_gvl(trampoline, &invoker, nullptr, nullptr);
|
|
191
|
+
|
|
192
|
+
if constexpr (!std::is_same_v<Return_T, void>)
|
|
193
|
+
{
|
|
194
|
+
return invoker.result();
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
@@ -30,6 +30,10 @@ namespace Rice::detail
|
|
|
30
30
|
VALUE operator()(size_t argc, const VALUE* argv, VALUE self) override;
|
|
31
31
|
std::string toString() override;
|
|
32
32
|
|
|
33
|
+
std::string name() override;
|
|
34
|
+
NativeKind kind() override;
|
|
35
|
+
VALUE returnKlass() override;
|
|
36
|
+
|
|
33
37
|
protected:
|
|
34
38
|
NativeIterator(VALUE klass, std::string method_name, Iterator_Func_T begin, Iterator_Func_T end);
|
|
35
39
|
|
|
@@ -101,4 +101,23 @@ namespace Rice::detail
|
|
|
101
101
|
{
|
|
102
102
|
return "";
|
|
103
103
|
}
|
|
104
|
+
|
|
105
|
+
template<typename T, typename Iterator_Func_T>
|
|
106
|
+
inline std::string NativeIterator<T, Iterator_Func_T>::name()
|
|
107
|
+
{
|
|
108
|
+
return this->method_name_;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
template<typename T, typename Iterator_Func_T>
|
|
112
|
+
inline NativeKind NativeIterator<T, Iterator_Func_T>::kind()
|
|
113
|
+
{
|
|
114
|
+
return NativeKind::Iterator;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
template<typename T, typename Iterator_Func_T>
|
|
118
|
+
inline VALUE NativeIterator<T, Iterator_Func_T>::returnKlass()
|
|
119
|
+
{
|
|
120
|
+
TypeMapper<Value_T> typeMapper;
|
|
121
|
+
return typeMapper.rubyKlass();
|
|
122
|
+
}
|
|
104
123
|
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
#ifndef Rice__detail__Native_Method__hpp_
|
|
2
|
+
#define Rice__detail__Native_Method__hpp_
|
|
3
|
+
|
|
4
|
+
namespace Rice::detail
|
|
5
|
+
{
|
|
6
|
+
//! The NativeMethod class calls C++ functions/methods/lambdas on behalf of Ruby
|
|
7
|
+
/*! The NativeMethod class is an intermediate between Ruby and C++. Every method
|
|
8
|
+
* defined in Rice is associated with a NativeFuntion instance that is stored in
|
|
9
|
+
* a unordered_map maintained by the MethodData class. The key is the Ruby class
|
|
10
|
+
* and method.
|
|
11
|
+
*
|
|
12
|
+
* When Ruby calls into C++ it invokes the static NativeMethod.call method. This
|
|
13
|
+
* method then looks up the NativeMethod instance and calls its ->() operator.
|
|
14
|
+
*
|
|
15
|
+
* The instance then converts each of the arguments passed from Ruby into their
|
|
16
|
+
* C++ equivalents. It then retrieves the C++ object (if there is one, Ruby could
|
|
17
|
+
* be calling a free standing method or lambda). Then it calls the C++ method
|
|
18
|
+
* and gets back the result. If there is a result (so not void), it is converted
|
|
19
|
+
* from a C++ object to a Ruby object and returned back to Ruby.
|
|
20
|
+
*
|
|
21
|
+
* This class make heavy use of C++ Template metaprogramming to determine
|
|
22
|
+
* the types and parameters a method takes. It then uses that information
|
|
23
|
+
* to perform type conversion Ruby to C++.
|
|
24
|
+
*
|
|
25
|
+
* @tparam Receiver_T - The type of C++ class wrapped by Ruby. Althought NativeMethod
|
|
26
|
+
* can derive the C++ class (Receiver_T), it can differ per member function. For example,
|
|
27
|
+
* std::map has a size() method but that is actually implemented on an ancestor class _Tree.
|
|
28
|
+
* Thus Receiver_T is std::map but Method_T::Receiver_T is _Tree. This breaks Rice in two ways.
|
|
29
|
+
* First, _Tree is not a registered type. Second, Rice would return a _Tree instance back to
|
|
30
|
+
* C++ and not a std::map.
|
|
31
|
+
* @tparam Method_T - A template that represents the C++ function
|
|
32
|
+
* to call. This typename is automatically deduced by the compiler.
|
|
33
|
+
* @tparam IsMethod - A boolean specifying whether the function has
|
|
34
|
+
* a self parameter or not. Rice differentiates these two cases by
|
|
35
|
+
* calling them methods (self) or functions (no self).
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
template<typename Class_T, typename Method_T>
|
|
39
|
+
class NativeMethod: Native
|
|
40
|
+
{
|
|
41
|
+
public:
|
|
42
|
+
using NativeMethod_T = NativeMethod<Class_T, Method_T>;
|
|
43
|
+
|
|
44
|
+
// We remove const to avoid an explosion of To_Ruby specializations and Ruby doesn't
|
|
45
|
+
// have the concept of constants anyways
|
|
46
|
+
using Return_T = typename method_traits<Method_T>::Return_T;
|
|
47
|
+
using Receiver_T = typename method_traits<Method_T>::Class_T;
|
|
48
|
+
using Arg_Ts = typename method_traits<Method_T>::Arg_Ts;
|
|
49
|
+
using Apply_Args_T = typename tuple_unshift<Receiver_T, Arg_Ts>::type;
|
|
50
|
+
|
|
51
|
+
using To_Ruby_T = remove_cv_recursive_t<Return_T>;
|
|
52
|
+
|
|
53
|
+
// Register method with Ruby
|
|
54
|
+
static void define(VALUE klass, std::string method_name, Method_T method, MethodInfo* methodInfo);
|
|
55
|
+
|
|
56
|
+
public:
|
|
57
|
+
NativeMethod(VALUE klass, std::string method_name, Method_T method, MethodInfo* methodInfo);
|
|
58
|
+
|
|
59
|
+
VALUE operator()(size_t argc, const VALUE* argv, VALUE self) override;
|
|
60
|
+
std::string toString() override;
|
|
61
|
+
|
|
62
|
+
std::string name() override;
|
|
63
|
+
NativeKind kind() override;
|
|
64
|
+
VALUE returnKlass() override;
|
|
65
|
+
|
|
66
|
+
private:
|
|
67
|
+
|
|
68
|
+
template<std::size_t...I>
|
|
69
|
+
std::vector<std::string> argTypeNames(std::ostringstream& stream, std::index_sequence<I...>& indices);
|
|
70
|
+
|
|
71
|
+
// Convert Ruby values to C++ values
|
|
72
|
+
template<typename std::size_t...I>
|
|
73
|
+
Apply_Args_T getNativeValues(VALUE self, std::vector<std::optional<VALUE>>& values, std::index_sequence<I...>& indices);
|
|
74
|
+
|
|
75
|
+
// Figure out what self is
|
|
76
|
+
Receiver_T getReceiver(VALUE self);
|
|
77
|
+
|
|
78
|
+
// Throw an exception when wrapper cannot be extracted
|
|
79
|
+
[[noreturn]] void noWrapper(const VALUE klass, const std::string& wrapper);
|
|
80
|
+
|
|
81
|
+
// Do we need to keep alive any arguments?
|
|
82
|
+
void checkKeepAlive(VALUE self, VALUE returnValue, std::vector<std::optional<VALUE>>& rubyValues);
|
|
83
|
+
|
|
84
|
+
// Call the underlying C++ method
|
|
85
|
+
VALUE invoke(VALUE self, Apply_Args_T&& nativeArgs);
|
|
86
|
+
VALUE invokeNoGVL(VALUE self, Apply_Args_T&& nativeArgs);
|
|
87
|
+
|
|
88
|
+
private:
|
|
89
|
+
VALUE klass_;
|
|
90
|
+
std::string method_name_;
|
|
91
|
+
Method_T method_;
|
|
92
|
+
std::unique_ptr<MethodInfo> methodInfo_;
|
|
93
|
+
To_Ruby<To_Ruby_T> toRuby_;
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
#endif // Rice__detail__Native_Method__hpp_
|