rice 4.3.3 → 4.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +86 -26
- data/CMakeLists.txt +31 -0
- data/CMakePresets.json +75 -0
- data/COPYING +3 -2
- data/FindRuby.cmake +437 -0
- data/README.md +7 -2
- data/Rakefile +12 -5
- data/include/rice/rice.hpp +9522 -4426
- data/include/rice/stl.hpp +2831 -1198
- data/lib/make_rice_headers.rb +79 -0
- data/lib/mkmf-rice.rb +40 -94
- data/lib/rice/version.rb +3 -0
- data/lib/rice.rb +1 -0
- data/lib/rubygems/builder.rb +11 -0
- data/lib/rubygems/cmake_builder.rb +113 -0
- data/lib/rubygems_plugin.rb +9 -0
- data/rice/Address_Registration_Guard.hpp +72 -3
- data/rice/Arg.hpp +26 -6
- data/rice/Arg.ipp +35 -2
- data/rice/Buffer.hpp +123 -0
- data/rice/Buffer.ipp +599 -0
- data/rice/Callback.hpp +21 -0
- data/rice/Callback.ipp +13 -0
- data/rice/Constructor.hpp +4 -27
- data/rice/Constructor.ipp +79 -0
- data/rice/Data_Object.hpp +73 -3
- data/rice/Data_Object.ipp +388 -96
- data/rice/Data_Type.hpp +214 -3
- data/rice/Data_Type.ipp +144 -67
- data/rice/Director.hpp +0 -2
- data/rice/Enum.hpp +4 -7
- data/rice/Enum.ipp +102 -55
- data/rice/Exception.hpp +62 -2
- data/rice/Exception.ipp +7 -12
- data/rice/Init.hpp +8 -0
- data/rice/Init.ipp +8 -0
- data/rice/JumpException.hpp +44 -0
- data/rice/JumpException.ipp +48 -0
- data/rice/MemoryView.hpp +11 -0
- data/rice/MemoryView.ipp +3 -0
- data/rice/Return.hpp +7 -27
- data/rice/Return.ipp +13 -13
- data/rice/cpp_api/Array.hpp +209 -0
- data/rice/cpp_api/Array.ipp +304 -0
- data/rice/cpp_api/Builtin_Object.hpp +31 -0
- data/rice/cpp_api/Builtin_Object.ipp +37 -0
- data/rice/cpp_api/Class.hpp +70 -0
- data/rice/cpp_api/Class.ipp +97 -0
- data/rice/cpp_api/Encoding.hpp +32 -0
- data/rice/cpp_api/Encoding.ipp +59 -0
- data/rice/cpp_api/Hash.hpp +194 -0
- data/rice/cpp_api/Hash.ipp +257 -0
- data/rice/{Identifier.hpp → cpp_api/Identifier.hpp} +2 -6
- data/rice/{Identifier.ipp → cpp_api/Identifier.ipp} +4 -2
- data/rice/cpp_api/Module.hpp +72 -0
- data/rice/cpp_api/Module.ipp +101 -0
- data/rice/cpp_api/Object.hpp +272 -0
- data/rice/cpp_api/Object.ipp +235 -0
- data/rice/cpp_api/String.hpp +74 -0
- data/rice/cpp_api/String.ipp +120 -0
- data/rice/cpp_api/Struct.hpp +113 -0
- data/rice/cpp_api/Struct.ipp +92 -0
- data/rice/cpp_api/Symbol.hpp +46 -0
- data/rice/cpp_api/Symbol.ipp +93 -0
- data/rice/cpp_api/shared_methods.hpp +134 -0
- data/rice/detail/DefaultHandler.hpp +12 -0
- data/rice/detail/DefaultHandler.ipp +8 -0
- data/rice/detail/HandlerRegistry.hpp +5 -35
- data/rice/detail/HandlerRegistry.ipp +7 -11
- data/rice/detail/InstanceRegistry.hpp +1 -4
- data/rice/detail/MethodInfo.hpp +12 -10
- data/rice/detail/MethodInfo.ipp +26 -21
- data/rice/detail/Native.hpp +33 -0
- data/rice/detail/Native.ipp +157 -0
- data/rice/detail/NativeAttributeGet.hpp +52 -0
- data/rice/detail/NativeAttributeGet.ipp +57 -0
- data/rice/detail/NativeAttributeSet.hpp +44 -0
- data/rice/detail/NativeAttributeSet.ipp +88 -0
- data/rice/detail/NativeCallbackFFI.hpp +55 -0
- data/rice/detail/NativeCallbackFFI.ipp +151 -0
- data/rice/detail/NativeCallbackSimple.hpp +30 -0
- data/rice/detail/NativeCallbackSimple.ipp +29 -0
- data/rice/detail/NativeFunction.hpp +33 -23
- data/rice/detail/NativeFunction.ipp +309 -70
- data/rice/detail/NativeIterator.hpp +9 -11
- data/rice/detail/NativeIterator.ipp +33 -31
- data/rice/detail/NativeRegistry.hpp +24 -15
- data/rice/detail/NativeRegistry.ipp +23 -48
- data/rice/detail/Proc.hpp +4 -0
- data/rice/detail/Proc.ipp +85 -0
- data/rice/detail/Registries.hpp +0 -7
- data/rice/detail/Registries.ipp +0 -18
- data/rice/detail/RubyFunction.hpp +0 -3
- data/rice/detail/RubyFunction.ipp +4 -8
- data/rice/detail/RubyType.hpp +16 -0
- data/rice/detail/RubyType.ipp +232 -0
- data/rice/detail/Type.hpp +7 -6
- data/rice/detail/Type.ipp +192 -45
- data/rice/detail/TypeRegistry.hpp +15 -7
- data/rice/detail/TypeRegistry.ipp +105 -12
- data/rice/detail/Wrapper.hpp +68 -32
- data/rice/detail/Wrapper.ipp +121 -109
- data/rice/detail/cpp_protect.hpp +5 -6
- data/rice/detail/default_allocation_func.ipp +0 -2
- data/rice/detail/from_ruby.hpp +38 -3
- data/rice/detail/from_ruby.ipp +1321 -492
- data/rice/detail/ruby.hpp +18 -0
- data/rice/detail/to_ruby.hpp +41 -3
- data/rice/detail/to_ruby.ipp +1424 -194
- data/rice/global_function.hpp +0 -4
- data/rice/global_function.ipp +0 -1
- data/rice/libc/file.hpp +11 -0
- data/rice/libc/file.ipp +32 -0
- data/rice/rice.hpp +116 -26
- data/rice/ruby_mark.hpp +4 -3
- data/rice/stl/complex.hpp +6 -0
- data/rice/stl/complex.ipp +93 -0
- data/rice/stl/exception.hpp +11 -0
- data/rice/stl/exception.ipp +29 -0
- data/rice/stl/exception_ptr.hpp +6 -0
- data/rice/stl/exception_ptr.ipp +27 -0
- data/rice/stl/map.hpp +12 -0
- data/rice/stl/map.ipp +469 -0
- data/rice/stl/monostate.hpp +6 -0
- data/rice/stl/monostate.ipp +80 -0
- data/rice/stl/multimap.hpp +14 -0
- data/rice/stl/multimap.ipp +448 -0
- data/rice/stl/optional.hpp +6 -0
- data/rice/stl/optional.ipp +118 -0
- data/rice/stl/pair.hpp +13 -0
- data/rice/stl/pair.ipp +155 -0
- data/rice/stl/reference_wrapper.hpp +6 -0
- data/rice/stl/reference_wrapper.ipp +41 -0
- data/rice/stl/set.hpp +12 -0
- data/rice/stl/set.ipp +495 -0
- data/rice/stl/shared_ptr.hpp +28 -0
- data/rice/stl/shared_ptr.ipp +224 -0
- data/rice/stl/string.hpp +6 -0
- data/rice/stl/string.ipp +158 -0
- data/rice/stl/string_view.hpp +6 -0
- data/rice/stl/string_view.ipp +65 -0
- data/rice/stl/tuple.hpp +6 -0
- data/rice/stl/tuple.ipp +128 -0
- data/rice/stl/type_index.hpp +6 -0
- data/rice/stl/type_index.ipp +30 -0
- data/rice/stl/type_info.hpp +6 -0
- data/rice/stl/type_info.ipp +29 -0
- data/rice/stl/unique_ptr.hpp +22 -0
- data/rice/stl/unique_ptr.ipp +139 -0
- data/rice/stl/unordered_map.hpp +12 -0
- data/rice/stl/unordered_map.ipp +469 -0
- data/rice/stl/variant.hpp +6 -0
- data/rice/stl/variant.ipp +242 -0
- data/rice/stl/vector.hpp +12 -0
- data/rice/stl/vector.ipp +590 -0
- data/rice/stl.hpp +11 -3
- data/rice/traits/attribute_traits.hpp +26 -0
- data/rice/traits/function_traits.hpp +95 -0
- data/rice/traits/method_traits.hpp +47 -0
- data/rice/traits/rice_traits.hpp +160 -0
- data/rice.gemspec +85 -0
- data/test/embed_ruby.cpp +7 -1
- data/test/extconf.rb +2 -0
- data/test/test_Address_Registration_Guard.cpp +5 -0
- data/test/test_Array.cpp +18 -4
- data/test/test_Attribute.cpp +136 -21
- data/test/test_Buffer.cpp +285 -0
- data/test/test_Builtin_Object.cpp +5 -0
- data/test/test_Callback.cpp +230 -0
- data/test/test_Class.cpp +5 -31
- data/test/test_Constructor.cpp +69 -6
- data/test/test_Data_Object.cpp +97 -38
- data/test/test_Data_Type.cpp +470 -65
- data/test/test_Director.cpp +17 -8
- data/test/test_Enum.cpp +155 -40
- data/test/test_Exception.cpp +235 -0
- data/test/test_File.cpp +70 -0
- data/test/test_From_Ruby.cpp +609 -0
- data/test/test_Hash.cpp +5 -0
- data/test/test_Identifier.cpp +5 -0
- data/test/test_Inheritance.cpp +6 -1
- data/test/test_Iterator.cpp +6 -1
- data/test/test_Jump_Exception.cpp +23 -0
- data/test/test_Keep_Alive.cpp +13 -19
- data/test/test_Keep_Alive_No_Wrapper.cpp +5 -1
- data/test/test_Memory_Management.cpp +5 -0
- data/test/test_Module.cpp +128 -67
- data/test/test_Native_Registry.cpp +2 -34
- data/test/test_Object.cpp +5 -0
- data/test/test_Overloads.cpp +806 -0
- data/test/test_Ownership.cpp +160 -54
- data/test/test_Proc.cpp +44 -0
- data/test/test_Self.cpp +9 -4
- data/test/test_Stl_Exception.cpp +109 -0
- data/test/test_Stl_Map.cpp +54 -42
- data/test/test_Stl_Multimap.cpp +693 -0
- data/test/test_Stl_Optional.cpp +5 -0
- data/test/test_Stl_Pair.cpp +14 -9
- data/test/test_Stl_Reference_Wrapper.cpp +9 -2
- data/test/test_Stl_Set.cpp +790 -0
- data/test/test_Stl_SharedPtr.cpp +458 -0
- data/test/test_Stl_String.cpp +5 -0
- data/test/test_Stl_String_View.cpp +5 -0
- data/test/test_Stl_Tuple.cpp +116 -0
- data/test/test_Stl_Type.cpp +147 -0
- data/test/test_Stl_UniquePtr.cpp +202 -0
- data/test/test_Stl_Unordered_Map.cpp +43 -38
- data/test/test_Stl_Variant.cpp +217 -84
- data/test/test_Stl_Vector.cpp +306 -58
- data/test/test_String.cpp +5 -0
- data/test/test_Struct.cpp +5 -0
- data/test/test_Symbol.cpp +5 -0
- data/test/test_Template.cpp +192 -0
- data/test/test_To_Ruby.cpp +524 -0
- data/test/test_Tracking.cpp +1 -0
- data/test/test_Type.cpp +171 -0
- data/test/test_global_functions.cpp +67 -7
- data/test/unittest.cpp +8 -0
- metadata +127 -26
- data/lib/version.rb +0 -3
- data/rice/Address_Registration_Guard_defn.hpp +0 -79
- data/rice/Data_Object_defn.hpp +0 -84
- data/rice/Data_Type_defn.hpp +0 -190
- data/rice/Exception_defn.hpp +0 -68
- data/rice/HandlerRegistration.hpp +0 -15
- data/rice/detail/ExceptionHandler.hpp +0 -8
- data/rice/detail/ExceptionHandler.ipp +0 -28
- data/rice/detail/ExceptionHandler_defn.hpp +0 -77
- data/rice/detail/Jump_Tag.hpp +0 -21
- data/rice/detail/NativeAttribute.hpp +0 -64
- data/rice/detail/NativeAttribute.ipp +0 -112
- data/rice/detail/from_ruby_defn.hpp +0 -38
- data/rice/detail/to_ruby_defn.hpp +0 -48
- data/test/test_Jump_Tag.cpp +0 -17
- data/test/test_Stl_SmartPointer.cpp +0 -283
- data/test/test_To_From_Ruby.cpp +0 -399
@@ -1,51 +1,21 @@
|
|
1
1
|
#ifndef Rice__detail__HandlerRegistry__hpp_
|
2
2
|
#define Rice__detail__HandlerRegistry__hpp_
|
3
3
|
|
4
|
-
#include
|
4
|
+
#include <functional>
|
5
5
|
|
6
6
|
namespace Rice::detail
|
7
7
|
{
|
8
8
|
class HandlerRegistry
|
9
9
|
{
|
10
10
|
public:
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
* translate the exception into a ruby exception.
|
15
|
-
* \param Exception_T a template parameter indicating the type of
|
16
|
-
* exception to be translated.
|
17
|
-
* \param functor a functor to be called to translate the exception
|
18
|
-
* into a ruby exception. This functor should re-throw the exception
|
19
|
-
* as an Exception.
|
20
|
-
* Example:
|
21
|
-
* \code
|
22
|
-
* Class rb_cFoo;
|
23
|
-
*
|
24
|
-
* void translate_my_exception(MyException const& ex)
|
25
|
-
* {
|
26
|
-
* throw Rice::Exception(rb_eRuntimeError, ex.what_without_backtrace());
|
27
|
-
* }
|
28
|
-
*
|
29
|
-
* extern "C"
|
30
|
-
* void Init_MyExtension()
|
31
|
-
* {
|
32
|
-
* rb_cFoo = define_class("Foo");
|
33
|
-
* register_handler<MyException>(translate_my_exception);
|
34
|
-
* }
|
35
|
-
* \endcode
|
36
|
-
*/
|
37
|
-
template<typename Exception_T, typename Functor_T>
|
38
|
-
HandlerRegistry& add(Functor_T functor);
|
39
|
-
|
40
|
-
std::shared_ptr<detail::ExceptionHandler> handler() const;
|
11
|
+
HandlerRegistry();
|
12
|
+
void set(std::function<void()> handler);
|
13
|
+
std::function<void()> handler() const;
|
41
14
|
|
42
15
|
private:
|
43
|
-
|
44
|
-
|
16
|
+
std::function<void()> handler_;
|
45
17
|
};
|
46
18
|
} // namespace Rice::detail
|
47
19
|
|
48
|
-
#include "HandlerRegistry.ipp"
|
49
|
-
|
50
20
|
#endif // Rice__detail__HandlerRegistry__hpp_
|
51
21
|
|
@@ -1,20 +1,16 @@
|
|
1
|
-
#include <memory>
|
2
|
-
|
3
1
|
namespace Rice::detail
|
4
2
|
{
|
5
|
-
|
6
|
-
inline HandlerRegistry& HandlerRegistry::add(Functor_T functor)
|
3
|
+
inline HandlerRegistry::HandlerRegistry() : handler_(DefaultHandler())
|
7
4
|
{
|
8
|
-
|
9
|
-
// get chained together). Then take ownership of the new handler.
|
10
|
-
this->handler_ = std::make_shared<detail::CustomExceptionHandler<Exception_T, Functor_T>>(
|
11
|
-
functor, std::move(this->handler_));
|
5
|
+
}
|
12
6
|
|
13
|
-
|
7
|
+
inline void HandlerRegistry::set(std::function<void()> handler)
|
8
|
+
{
|
9
|
+
this->handler_ = handler;
|
14
10
|
}
|
15
11
|
|
16
|
-
inline std::
|
12
|
+
inline std::function<void()> HandlerRegistry::handler() const
|
17
13
|
{
|
18
14
|
return this->handler_;
|
19
15
|
}
|
20
|
-
}
|
16
|
+
}
|
@@ -2,7 +2,6 @@
|
|
2
2
|
#define Rice__detail__InstanceRegistry__hpp_
|
3
3
|
|
4
4
|
#include <map>
|
5
|
-
#include "ruby.hpp"
|
6
5
|
|
7
6
|
namespace Rice::detail
|
8
7
|
{
|
@@ -14,6 +13,7 @@ namespace Rice::detail
|
|
14
13
|
|
15
14
|
template <typename T>
|
16
15
|
VALUE lookup(T* cppInstance);
|
16
|
+
VALUE lookup(void* cppInstance);
|
17
17
|
|
18
18
|
void add(void* cppInstance, VALUE rubyInstance);
|
19
19
|
void remove(void* cppInstance);
|
@@ -23,12 +23,9 @@ namespace Rice::detail
|
|
23
23
|
bool isEnabled = false;
|
24
24
|
|
25
25
|
private:
|
26
|
-
VALUE lookup(void* cppInstance);
|
27
26
|
std::map<void*, VALUE> objectMap_;
|
28
27
|
};
|
29
28
|
} // namespace Rice::detail
|
30
29
|
|
31
|
-
#include "InstanceRegistry.ipp"
|
32
|
-
|
33
30
|
#endif // Rice__detail__InstanceRegistry__hpp_
|
34
31
|
|
data/rice/detail/MethodInfo.hpp
CHANGED
@@ -2,29 +2,33 @@
|
|
2
2
|
#define Rice__MethodInfo__hpp_
|
3
3
|
|
4
4
|
#include <vector>
|
5
|
-
#include "../Arg.hpp"
|
6
|
-
#include "../Return.hpp"
|
7
5
|
|
8
6
|
namespace Rice
|
9
7
|
{
|
10
8
|
class MethodInfo
|
11
9
|
{
|
12
10
|
public:
|
11
|
+
MethodInfo() = default;
|
12
|
+
|
13
13
|
template <typename...Arg_Ts>
|
14
14
|
MethodInfo(size_t argCount, const Arg_Ts&...args);
|
15
15
|
|
16
16
|
/**
|
17
|
-
*
|
18
|
-
* list of arguments.
|
17
|
+
* Add a defined Arg to this list of Arguments
|
19
18
|
*/
|
20
|
-
|
19
|
+
void addArg(const Arg& arg);
|
21
20
|
|
22
21
|
/**
|
23
|
-
*
|
22
|
+
* Get argument by position
|
24
23
|
*/
|
25
|
-
|
24
|
+
Arg* arg(size_t pos);
|
26
25
|
|
27
|
-
|
26
|
+
/**
|
27
|
+
* Get argument by name
|
28
|
+
*/
|
29
|
+
Arg* arg(std::string name);
|
30
|
+
|
31
|
+
int argCount();
|
28
32
|
|
29
33
|
// Iterator support
|
30
34
|
std::vector<Arg>::iterator begin();
|
@@ -39,6 +43,4 @@ namespace Rice
|
|
39
43
|
std::vector<Arg> args_;
|
40
44
|
};
|
41
45
|
}
|
42
|
-
#include "MethodInfo.ipp"
|
43
|
-
|
44
46
|
#endif // Rice__MethodInfo__hpp_
|
data/rice/detail/MethodInfo.ipp
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
#include <sstream>
|
2
|
-
#include "from_ruby_defn.hpp"
|
3
2
|
|
4
3
|
namespace Rice
|
5
4
|
{
|
@@ -26,13 +25,15 @@ namespace Rice
|
|
26
25
|
template <typename Arg_T>
|
27
26
|
inline void MethodInfo::processArg(const Arg_T& arg)
|
28
27
|
{
|
29
|
-
|
28
|
+
static_assert(std::is_same_v<Arg_T, Return> || std::is_same_v<Arg_T, Arg>, "Unknown argument type");
|
29
|
+
|
30
|
+
if constexpr (std::is_same_v<Arg_T, Return>)
|
30
31
|
{
|
31
|
-
this->
|
32
|
+
this->returnInfo = arg;
|
32
33
|
}
|
33
|
-
else
|
34
|
+
else if constexpr (std::is_same_v<Arg_T, Arg>)
|
34
35
|
{
|
35
|
-
this->
|
36
|
+
this->addArg(arg);
|
36
37
|
}
|
37
38
|
}
|
38
39
|
|
@@ -41,29 +42,33 @@ namespace Rice
|
|
41
42
|
this->args_.push_back(arg);
|
42
43
|
}
|
43
44
|
|
44
|
-
inline
|
45
|
+
inline int MethodInfo::argCount()
|
45
46
|
{
|
46
|
-
|
47
|
-
|
47
|
+
return this->args_.size();
|
48
|
+
}
|
48
49
|
|
49
|
-
|
50
|
+
inline Arg* MethodInfo::arg(size_t pos)
|
51
|
+
{
|
52
|
+
if (pos < this->args_.size())
|
50
53
|
{
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
{
|
57
|
-
required++;
|
58
|
-
}
|
54
|
+
return &this->args_[pos];
|
55
|
+
}
|
56
|
+
else
|
57
|
+
{
|
58
|
+
return nullptr;
|
59
59
|
}
|
60
|
-
|
61
|
-
return std::to_string(required) + std::to_string(optional);
|
62
60
|
}
|
63
61
|
|
64
|
-
inline Arg
|
62
|
+
inline Arg* MethodInfo::arg(std::string name)
|
65
63
|
{
|
66
|
-
|
64
|
+
for (Arg& arg : this->args_)
|
65
|
+
{
|
66
|
+
if (arg.name == name)
|
67
|
+
{
|
68
|
+
return &arg;
|
69
|
+
}
|
70
|
+
}
|
71
|
+
return nullptr;
|
67
72
|
}
|
68
73
|
|
69
74
|
inline std::vector<Arg>::iterator MethodInfo::begin()
|
@@ -0,0 +1,33 @@
|
|
1
|
+
#ifndef Rice__detail__Native__hpp_
|
2
|
+
#define Rice__detail__Native__hpp_
|
3
|
+
|
4
|
+
namespace Rice::detail
|
5
|
+
{
|
6
|
+
class Native;
|
7
|
+
|
8
|
+
class Resolved
|
9
|
+
{
|
10
|
+
public:
|
11
|
+
inline bool operator<(Resolved other);
|
12
|
+
inline bool operator>(Resolved other);
|
13
|
+
|
14
|
+
Convertible convertible;
|
15
|
+
double parameterMatch;
|
16
|
+
Native* native;
|
17
|
+
};
|
18
|
+
|
19
|
+
class Native
|
20
|
+
{
|
21
|
+
public:
|
22
|
+
static VALUE resolve(int argc, VALUE* argv, VALUE self);
|
23
|
+
public:
|
24
|
+
virtual ~Native() = default;
|
25
|
+
VALUE call(int argc, VALUE* argv, VALUE self);
|
26
|
+
|
27
|
+
virtual Resolved matches(size_t argc, const VALUE* argv, VALUE self) = 0;
|
28
|
+
virtual VALUE operator()(size_t argc, const VALUE* argv, VALUE self) = 0;
|
29
|
+
virtual std::string toString() = 0;
|
30
|
+
};
|
31
|
+
}
|
32
|
+
|
33
|
+
#endif // Rice__detail__Native__hpp_
|
@@ -0,0 +1,157 @@
|
|
1
|
+
|
2
|
+
namespace Rice::detail
|
3
|
+
{
|
4
|
+
inline bool Resolved::operator<(Resolved other)
|
5
|
+
{
|
6
|
+
if (this->convertible != other.convertible)
|
7
|
+
{
|
8
|
+
return this->convertible < other.convertible;
|
9
|
+
}
|
10
|
+
else
|
11
|
+
{
|
12
|
+
return this->parameterMatch < other.parameterMatch;
|
13
|
+
}
|
14
|
+
}
|
15
|
+
|
16
|
+
inline bool Resolved::operator>(Resolved other)
|
17
|
+
{
|
18
|
+
if (this->convertible != other.convertible)
|
19
|
+
{
|
20
|
+
return this->convertible > other.convertible;
|
21
|
+
}
|
22
|
+
else
|
23
|
+
{
|
24
|
+
return this->parameterMatch > other.parameterMatch;
|
25
|
+
}
|
26
|
+
}
|
27
|
+
|
28
|
+
inline VALUE Native::resolve(int argc, VALUE* argv, VALUE self)
|
29
|
+
{
|
30
|
+
/* This method is called from Ruby and is responsible for determining the correct
|
31
|
+
Native object (ie, NativeFunction, NativeIterator, NativeAttributeGet and
|
32
|
+
NativeAttributeSet) that shoudl be used to invoke the underlying C++ code.
|
33
|
+
Most of the time there will be a single Native object registered for a C++ function,
|
34
|
+
method, constructor, iterator or attribute. However, there can be multiple Natives
|
35
|
+
when a C++ function/method/construtor is overloaded.
|
36
|
+
|
37
|
+
In that case, the code iterates over each Native and calls its matches method. The matches
|
38
|
+
method returns a Resolved object which includes a Convertible field and parameterMatch field.
|
39
|
+
The Convertible field is an enum that specifies if the types of the values supplied by Ruby
|
40
|
+
match the types of the C++ function parameters. Allowed values include can be Exact (example Ruby into to C++ int),
|
41
|
+
TypeCast (example Ruby into to C++ float) or None (cannot be converted).
|
42
|
+
|
43
|
+
The parameterMatch field is simply the number or arguments provided by Ruby divided by the
|
44
|
+
number of arguments required by C++. These numbers can be different because C++ method
|
45
|
+
parameters can have default values.
|
46
|
+
|
47
|
+
Taking these two values into account, the method sorts the Natives and picks the one with the
|
48
|
+
highest score (Convertible::Exact and 1.0 for parameterMatch). Thus given these two C++ functions:
|
49
|
+
|
50
|
+
void some_method(int a);
|
51
|
+
void some_mtehod(int a, float b = 2.0).
|
52
|
+
|
53
|
+
A call from ruby of some_method(1) will exactly match both signatures, but the first one
|
54
|
+
will be chosen because the parameterMatch will be 1.0 for the first overload but 0.5
|
55
|
+
for the second. */
|
56
|
+
|
57
|
+
Native* native = nullptr;
|
58
|
+
|
59
|
+
ID methodId;
|
60
|
+
VALUE klass;
|
61
|
+
if (!rb_frame_method_id_and_class(&methodId, &klass))
|
62
|
+
{
|
63
|
+
rb_raise(rb_eRuntimeError, "Cannot get method id and class for function");
|
64
|
+
}
|
65
|
+
|
66
|
+
// Execute the function but make sure to catch any C++ exceptions!
|
67
|
+
return cpp_protect([&]
|
68
|
+
{
|
69
|
+
Identifier id(methodId);
|
70
|
+
std::string methodName = id.str();
|
71
|
+
std::string className = rb_class2name(klass);
|
72
|
+
|
73
|
+
const std::vector<std::unique_ptr<Native>>& natives = Registries::instance.natives.lookup(klass, methodId);
|
74
|
+
|
75
|
+
if (natives.size() == 1)
|
76
|
+
{
|
77
|
+
native = natives.front().get();
|
78
|
+
}
|
79
|
+
else if (natives.size() == 0)
|
80
|
+
{
|
81
|
+
Identifier identifier(methodId);
|
82
|
+
rb_raise(rb_eArgError, "Could not find method call for %s#%s", rb_class2name(klass), identifier.c_str());
|
83
|
+
}
|
84
|
+
else
|
85
|
+
{
|
86
|
+
Identifier identifier(methodId);
|
87
|
+
|
88
|
+
// Loop over every native to see how well they match the Ruby parameters
|
89
|
+
std::vector<Resolved> resolves;
|
90
|
+
std::transform(natives.begin(), natives.end(),
|
91
|
+
std::back_inserter(resolves),
|
92
|
+
[&](const std::unique_ptr<Native>& native)
|
93
|
+
{
|
94
|
+
return native->matches(argc, argv, self);
|
95
|
+
});
|
96
|
+
|
97
|
+
// Now sort from best to worst
|
98
|
+
std::sort(resolves.begin(), resolves.end(), std::greater{});
|
99
|
+
|
100
|
+
// Get the first one
|
101
|
+
Resolved resolved = resolves.front();
|
102
|
+
|
103
|
+
// Was there more than one match?
|
104
|
+
/*size_t count = std::count_if(resolves.begin(), resolves.end(),
|
105
|
+
[&resolved](Resolved& element)
|
106
|
+
{
|
107
|
+
return resolved.convertible == element.convertible;
|
108
|
+
});
|
109
|
+
|
110
|
+
if (count > 1)
|
111
|
+
{
|
112
|
+
std::ostringstream message;
|
113
|
+
message << "Could not resolve method call for %s#%s" << "\n"
|
114
|
+
<< " %d overloaded functions matched based on the types of Ruby parameters provided:";
|
115
|
+
|
116
|
+
for (int i = 0; i < count; i++)
|
117
|
+
{
|
118
|
+
message << "\n " << resolves[i].native->toString();
|
119
|
+
}
|
120
|
+
|
121
|
+
rb_raise(rb_eArgError, message.str().c_str(), rb_class2name(klass), identifier.c_str(), count);
|
122
|
+
}*/
|
123
|
+
|
124
|
+
// Did it match?
|
125
|
+
if (resolved.convertible != Convertible::None)
|
126
|
+
{
|
127
|
+
native = resolved.native;
|
128
|
+
}
|
129
|
+
else
|
130
|
+
{
|
131
|
+
// Special case == to make the RubyMine debugger work. It calls == with a Module as
|
132
|
+
// the other argument, thus breaking if C++ operator== is implemented.
|
133
|
+
if (identifier.str() == "==")
|
134
|
+
{
|
135
|
+
return detail::protect(rb_call_super, argc, argv);
|
136
|
+
}
|
137
|
+
else
|
138
|
+
{
|
139
|
+
std::ostringstream message;
|
140
|
+
message << "Could not resolve method call for %s#%s" << "\n"
|
141
|
+
<< " %d overload(s) were evaluated based on the types of Ruby parameters provided:";
|
142
|
+
|
143
|
+
for (Resolved& resolve: resolves)
|
144
|
+
{
|
145
|
+
message << "\n " << resolve.native->toString();
|
146
|
+
}
|
147
|
+
|
148
|
+
rb_raise(rb_eArgError, message.str().c_str(), rb_class2name(klass), identifier.c_str(), natives.size());
|
149
|
+
}
|
150
|
+
}
|
151
|
+
}
|
152
|
+
|
153
|
+
// Call the C++ function
|
154
|
+
return (*native)(argc, argv, self);
|
155
|
+
});
|
156
|
+
}
|
157
|
+
}
|
@@ -0,0 +1,52 @@
|
|
1
|
+
#ifndef Rice__detail__Native_Attribute_Get__hpp_
|
2
|
+
#define Rice__detail__Native_Attribute_Get__hpp_
|
3
|
+
|
4
|
+
namespace Rice
|
5
|
+
{
|
6
|
+
enum class AttrAccess
|
7
|
+
{
|
8
|
+
ReadWrite,
|
9
|
+
Read,
|
10
|
+
Write
|
11
|
+
};
|
12
|
+
|
13
|
+
namespace detail
|
14
|
+
{
|
15
|
+
template<typename Attribute_T>
|
16
|
+
class NativeAttributeGet: Native
|
17
|
+
{
|
18
|
+
public:
|
19
|
+
using NativeAttribute_T = NativeAttributeGet<Attribute_T>;
|
20
|
+
|
21
|
+
using T = typename attribute_traits<Attribute_T>::attr_type;
|
22
|
+
using Receiver_T = typename attribute_traits<Attribute_T>::class_type;
|
23
|
+
using To_Ruby_T = remove_cv_recursive_t<T>;
|
24
|
+
|
25
|
+
public:
|
26
|
+
// Register attribute getter with Ruby
|
27
|
+
static void define(VALUE klass, std::string name, Attribute_T attribute);
|
28
|
+
|
29
|
+
public:
|
30
|
+
// Disallow creating/copying/moving
|
31
|
+
NativeAttributeGet() = delete;
|
32
|
+
NativeAttributeGet(const NativeAttribute_T&) = delete;
|
33
|
+
NativeAttributeGet(NativeAttribute_T&&) = delete;
|
34
|
+
void operator=(const NativeAttribute_T&) = delete;
|
35
|
+
void operator=(NativeAttribute_T&&) = delete;
|
36
|
+
|
37
|
+
Resolved matches(size_t argc, const VALUE* argv, VALUE self) override;
|
38
|
+
VALUE operator()(size_t argc, const VALUE* argv, VALUE self) override;
|
39
|
+
std::string toString() override;
|
40
|
+
|
41
|
+
protected:
|
42
|
+
NativeAttributeGet(VALUE klass, std::string name, Attribute_T attr);
|
43
|
+
|
44
|
+
private:
|
45
|
+
VALUE klass_;
|
46
|
+
std::string name_;
|
47
|
+
Attribute_T attribute_;
|
48
|
+
};
|
49
|
+
} // detail
|
50
|
+
} // Rice
|
51
|
+
|
52
|
+
#endif // Rice__detail__Native_Attribute_Get__hpp_
|
@@ -0,0 +1,57 @@
|
|
1
|
+
#include <array>
|
2
|
+
#include <algorithm>
|
3
|
+
|
4
|
+
|
5
|
+
namespace Rice::detail
|
6
|
+
{
|
7
|
+
template<typename Attribute_T>
|
8
|
+
void NativeAttributeGet<Attribute_T>::define(VALUE klass, std::string name, Attribute_T attribute)
|
9
|
+
{
|
10
|
+
// Create a NativeAttributeGet that Ruby will call to read/write C++ variables
|
11
|
+
NativeAttribute_T* nativeAttribute = new NativeAttribute_T(klass, name, std::forward<Attribute_T>(attribute));
|
12
|
+
std::unique_ptr<Native> native(nativeAttribute);
|
13
|
+
|
14
|
+
detail::protect(rb_define_method, klass, name.c_str(), (RUBY_METHOD_FUNC)&Native::resolve, -1);
|
15
|
+
|
16
|
+
// Add to native registry. Since attributes cannot be overridden, there is no need to set the
|
17
|
+
// matches or calls function pointer. Instead Ruby can call the static call method defined on
|
18
|
+
// this class (&NativeAttribute_T::get).
|
19
|
+
Identifier identifier(name);
|
20
|
+
detail::Registries::instance.natives.add(klass, identifier.id(), native);
|
21
|
+
}
|
22
|
+
|
23
|
+
template<typename Attribute_T>
|
24
|
+
inline Resolved NativeAttributeGet<Attribute_T>::matches(size_t argc, const VALUE* argv, VALUE self)
|
25
|
+
{
|
26
|
+
if (argc == 0)
|
27
|
+
return Resolved { Convertible::Exact, 1, this };
|
28
|
+
else
|
29
|
+
return Resolved{ Convertible::None, 0, this };
|
30
|
+
}
|
31
|
+
|
32
|
+
template<typename Attribute_T>
|
33
|
+
NativeAttributeGet<Attribute_T>::NativeAttributeGet(VALUE klass, std::string name, Attribute_T attribute)
|
34
|
+
: klass_(klass), name_(name), attribute_(attribute)
|
35
|
+
{
|
36
|
+
}
|
37
|
+
|
38
|
+
template<typename Attribute_T>
|
39
|
+
inline VALUE NativeAttributeGet<Attribute_T>::operator()(size_t argc, const VALUE* argv, VALUE self)
|
40
|
+
{
|
41
|
+
if constexpr (std::is_member_object_pointer_v<Attribute_T>)
|
42
|
+
{
|
43
|
+
Receiver_T* nativeSelf = From_Ruby<Receiver_T*>().convert(self);
|
44
|
+
return To_Ruby<To_Ruby_T>().convert(nativeSelf->*attribute_);
|
45
|
+
}
|
46
|
+
else
|
47
|
+
{
|
48
|
+
return To_Ruby<To_Ruby_T>().convert(*attribute_);
|
49
|
+
}
|
50
|
+
}
|
51
|
+
|
52
|
+
template<typename Attribute_T>
|
53
|
+
inline std::string NativeAttributeGet<Attribute_T>::toString()
|
54
|
+
{
|
55
|
+
return "";
|
56
|
+
}
|
57
|
+
} // Rice
|
@@ -0,0 +1,44 @@
|
|
1
|
+
#ifndef Rice__detail__Native_Attribute_Set__hpp_
|
2
|
+
#define Rice__detail__Native_Attribute_Set__hpp_
|
3
|
+
|
4
|
+
namespace Rice
|
5
|
+
{
|
6
|
+
namespace detail
|
7
|
+
{
|
8
|
+
template<typename Attribute_T>
|
9
|
+
class NativeAttributeSet: Native
|
10
|
+
{
|
11
|
+
public:
|
12
|
+
using NativeAttribute_T = NativeAttributeSet<Attribute_T>;
|
13
|
+
using Attr_T = typename attribute_traits<Attribute_T>::attr_type;
|
14
|
+
using T_Unqualified = remove_cv_recursive_t<Attr_T>;
|
15
|
+
using Receiver_T = typename attribute_traits<Attribute_T>::class_type;
|
16
|
+
|
17
|
+
public:
|
18
|
+
// Register attribute getter/setter with Ruby
|
19
|
+
static void define(VALUE klass, std::string name, Attribute_T attribute);
|
20
|
+
|
21
|
+
public:
|
22
|
+
// Disallow creating/copying/moving
|
23
|
+
NativeAttributeSet() = delete;
|
24
|
+
NativeAttributeSet(const NativeAttribute_T&) = delete;
|
25
|
+
NativeAttributeSet(NativeAttribute_T&&) = delete;
|
26
|
+
void operator=(const NativeAttribute_T&) = delete;
|
27
|
+
void operator=(NativeAttribute_T&&) = delete;
|
28
|
+
|
29
|
+
Resolved matches(size_t argc, const VALUE* argv, VALUE self) override;
|
30
|
+
VALUE operator()(size_t argc, const VALUE* argv, VALUE self) override;
|
31
|
+
std::string toString() override;
|
32
|
+
|
33
|
+
protected:
|
34
|
+
NativeAttributeSet(VALUE klass, std::string name, Attribute_T attr);
|
35
|
+
|
36
|
+
private:
|
37
|
+
VALUE klass_;
|
38
|
+
std::string name_;
|
39
|
+
Attribute_T attribute_;
|
40
|
+
};
|
41
|
+
} // detail
|
42
|
+
} // Rice
|
43
|
+
|
44
|
+
#endif // Rice__detail__Native_Attribute_Set__hpp_
|
@@ -0,0 +1,88 @@
|
|
1
|
+
#include <array>
|
2
|
+
#include <algorithm>
|
3
|
+
|
4
|
+
|
5
|
+
namespace Rice::detail
|
6
|
+
{
|
7
|
+
template<typename Attribute_T>
|
8
|
+
void NativeAttributeSet<Attribute_T>::define(VALUE klass, std::string name, Attribute_T attribute)
|
9
|
+
{
|
10
|
+
// Create a NativeAttributeSet that Ruby will call to read/write C++ variables
|
11
|
+
NativeAttribute_T* nativeAttribute = new NativeAttribute_T(klass, name, std::forward<Attribute_T>(attribute));
|
12
|
+
std::unique_ptr<Native> native(nativeAttribute);
|
13
|
+
|
14
|
+
// Define the write method name
|
15
|
+
std::string setter = name + "=";
|
16
|
+
|
17
|
+
// Tell Ruby to invoke the static method write to get the attribute value
|
18
|
+
detail::protect(rb_define_method, klass, setter.c_str(), (RUBY_METHOD_FUNC)&Native::resolve, -1);
|
19
|
+
|
20
|
+
// Add to native registry. Since attributes cannot be overridden, there is no need to set the
|
21
|
+
// matches or calls function pointer. Instead Ruby can call the static call method defined on
|
22
|
+
// this class (&NativeAttribute_T::set).
|
23
|
+
Identifier identifier(setter);
|
24
|
+
detail::Registries::instance.natives.add(klass, identifier.id(), native);
|
25
|
+
}
|
26
|
+
|
27
|
+
template<typename Attribute_T>
|
28
|
+
NativeAttributeSet<Attribute_T>::NativeAttributeSet(VALUE klass, std::string name, Attribute_T attribute)
|
29
|
+
: klass_(klass), name_(name), attribute_(attribute)
|
30
|
+
{
|
31
|
+
}
|
32
|
+
|
33
|
+
template<typename Attribute_T>
|
34
|
+
inline Resolved NativeAttributeSet<Attribute_T>::matches(size_t argc, const VALUE* argv, VALUE self)
|
35
|
+
{
|
36
|
+
if (argc == 1)
|
37
|
+
return Resolved{ Convertible::Exact, 1, this };
|
38
|
+
else
|
39
|
+
return Resolved{ Convertible::None, 0, this };
|
40
|
+
}
|
41
|
+
|
42
|
+
template<typename Attribute_T>
|
43
|
+
inline VALUE NativeAttributeSet<Attribute_T>::operator()(size_t argc, const VALUE* argv, VALUE self)
|
44
|
+
{
|
45
|
+
if constexpr (std::is_fundamental_v<intrinsic_type<Attr_T>> && std::is_pointer_v<Attr_T>)
|
46
|
+
{
|
47
|
+
static_assert(true, "An fundamental value, such as an integer, cannot be assigned to an attribute that is a pointer.");
|
48
|
+
}
|
49
|
+
else if constexpr (std::is_same_v<intrinsic_type<Attr_T>, std::string> && std::is_pointer_v<Attr_T>)
|
50
|
+
{
|
51
|
+
static_assert(true, "An string cannot be assigned to an attribute that is a pointer.");
|
52
|
+
}
|
53
|
+
|
54
|
+
if (argc != 1)
|
55
|
+
{
|
56
|
+
throw std::runtime_error("Incorrect number of parameters for setting attribute. Attribute: " + this->name_);
|
57
|
+
}
|
58
|
+
|
59
|
+
VALUE value = argv[0];
|
60
|
+
|
61
|
+
if constexpr (!std::is_null_pointer_v<Receiver_T> &&
|
62
|
+
!std::is_const_v<Attr_T> &&
|
63
|
+
(std::is_fundamental_v<Attr_T> || std::is_assignable_v<Attr_T, Attr_T>))
|
64
|
+
{
|
65
|
+
Receiver_T* nativeSelf = From_Ruby<Receiver_T*>().convert(self);
|
66
|
+
nativeSelf->*attribute_ = From_Ruby<T_Unqualified>().convert(value);
|
67
|
+
}
|
68
|
+
else if constexpr (std::is_null_pointer_v<Receiver_T> &&
|
69
|
+
!std::is_const_v<Attr_T> &&
|
70
|
+
(std::is_fundamental_v<Attr_T> || std::is_assignable_v<Attr_T, Attr_T>))
|
71
|
+
{
|
72
|
+
*attribute_ = From_Ruby<T_Unqualified>().convert(value);
|
73
|
+
}
|
74
|
+
else
|
75
|
+
{
|
76
|
+
// Should never get here because define_attr won't compile this code, but just in case!
|
77
|
+
throw std::invalid_argument("Could not set attribute. Attribute: " + this->name_);
|
78
|
+
}
|
79
|
+
|
80
|
+
return value;
|
81
|
+
}
|
82
|
+
|
83
|
+
template<typename Attribute_T>
|
84
|
+
inline std::string NativeAttributeSet<Attribute_T>::toString()
|
85
|
+
{
|
86
|
+
return "";
|
87
|
+
}
|
88
|
+
} // Rice
|