rice 4.5.0 → 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 +23 -0
- data/CMakeLists.txt +31 -0
- data/CMakePresets.json +75 -0
- data/COPYING +3 -2
- data/FindRuby.cmake +437 -0
- data/Rakefile +5 -4
- data/include/rice/rice.hpp +5436 -3201
- data/include/rice/stl.hpp +2355 -1269
- data/lib/make_rice_headers.rb +79 -0
- data/lib/mkmf-rice.rb +4 -0
- 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/Arg.hpp +7 -1
- data/rice/Arg.ipp +11 -2
- data/rice/Buffer.hpp +123 -0
- data/rice/Buffer.ipp +599 -0
- data/rice/Constructor.ipp +3 -3
- data/rice/Data_Object.hpp +2 -3
- data/rice/Data_Object.ipp +188 -188
- data/rice/Data_Type.hpp +4 -5
- data/rice/Data_Type.ipp +42 -26
- data/rice/Enum.hpp +0 -1
- data/rice/Enum.ipp +26 -23
- data/rice/Init.hpp +8 -0
- data/rice/Init.ipp +8 -0
- data/rice/MemoryView.ipp +1 -41
- data/rice/Return.hpp +1 -1
- data/rice/Return.ipp +6 -0
- 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/cpp_api/Identifier.hpp +46 -0
- data/rice/cpp_api/Identifier.ipp +31 -0
- 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/MethodInfo.hpp +1 -9
- data/rice/detail/MethodInfo.ipp +5 -72
- data/rice/detail/Native.hpp +3 -2
- data/rice/detail/Native.ipp +32 -4
- data/rice/detail/NativeAttributeGet.hpp +3 -2
- data/rice/detail/NativeAttributeGet.ipp +8 -2
- data/rice/detail/NativeAttributeSet.hpp +3 -2
- data/rice/detail/NativeAttributeSet.ipp +8 -2
- data/rice/detail/NativeCallbackFFI.ipp +1 -1
- data/rice/detail/NativeFunction.hpp +17 -6
- data/rice/detail/NativeFunction.ipp +168 -64
- data/rice/detail/NativeIterator.hpp +3 -2
- data/rice/detail/NativeIterator.ipp +8 -2
- data/rice/detail/RubyType.hpp +2 -5
- data/rice/detail/RubyType.ipp +50 -5
- data/rice/detail/Type.hpp +3 -1
- data/rice/detail/Type.ipp +61 -31
- data/rice/detail/Wrapper.hpp +68 -33
- data/rice/detail/Wrapper.ipp +103 -113
- data/rice/detail/from_ruby.hpp +5 -4
- data/rice/detail/from_ruby.ipp +737 -365
- data/rice/detail/to_ruby.ipp +1092 -186
- data/rice/global_function.ipp +1 -1
- data/rice/libc/file.hpp +11 -0
- data/rice/libc/file.ipp +32 -0
- data/rice/rice.hpp +23 -16
- 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 +7 -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 +3 -0
- data/test/ruby/test_multiple_extensions_same_class.rb +14 -14
- data/test/test_Array.cpp +6 -3
- data/test/test_Attribute.cpp +34 -1
- data/test/test_Buffer.cpp +285 -0
- data/test/test_Callback.cpp +2 -3
- data/test/test_Data_Object.cpp +88 -34
- data/test/test_Data_Type.cpp +106 -65
- data/test/test_Director.cpp +7 -3
- data/test/test_Enum.cpp +5 -2
- data/test/test_File.cpp +1 -1
- data/test/test_From_Ruby.cpp +181 -114
- data/test/test_Iterator.cpp +1 -1
- data/test/{test_JumpException.cpp → test_Jump_Exception.cpp} +1 -0
- data/test/test_Keep_Alive.cpp +7 -18
- data/test/test_Keep_Alive_No_Wrapper.cpp +0 -1
- data/test/test_Module.cpp +13 -6
- data/test/test_Native_Registry.cpp +0 -1
- data/test/test_Overloads.cpp +180 -5
- data/test/test_Ownership.cpp +100 -57
- data/test/test_Proc.cpp +0 -1
- data/test/test_Self.cpp +4 -4
- data/test/test_Stl_Map.cpp +37 -39
- data/test/test_Stl_Multimap.cpp +693 -0
- data/test/test_Stl_Pair.cpp +8 -8
- data/test/test_Stl_Reference_Wrapper.cpp +4 -2
- data/test/test_Stl_Set.cpp +790 -0
- data/test/{test_Stl_SmartPointer.cpp → test_Stl_SharedPtr.cpp} +97 -127
- data/test/test_Stl_Tuple.cpp +116 -0
- data/test/test_Stl_Type.cpp +1 -1
- data/test/test_Stl_UniquePtr.cpp +202 -0
- data/test/test_Stl_Unordered_Map.cpp +28 -34
- data/test/test_Stl_Variant.cpp +217 -89
- data/test/test_Stl_Vector.cpp +209 -83
- data/test/test_To_Ruby.cpp +373 -1
- data/test/test_Type.cpp +85 -14
- data/test/test_global_functions.cpp +17 -4
- metadata +94 -10
- data/rice/detail/TupleIterator.hpp +0 -14
@@ -0,0 +1,113 @@
|
|
1
|
+
#ifndef Rice__ruby_struct__hpp_
|
2
|
+
#define Rice__ruby_struct__hpp_
|
3
|
+
|
4
|
+
namespace Rice
|
5
|
+
{
|
6
|
+
//! A wrapper for creating Struct classes.
|
7
|
+
/*! The Struct class is used for creating new Classes. Note that the
|
8
|
+
* notation used here differs slightly from the notation inside the
|
9
|
+
* interpreter.
|
10
|
+
*
|
11
|
+
* Inside the interpreter, calling Struct.new creates a new Class:
|
12
|
+
* \code
|
13
|
+
* irb(main):001:0> MyStruct = Struct.new(:a, :b, :c)
|
14
|
+
* => S
|
15
|
+
* irb(main):002:0> MyStruct.class
|
16
|
+
* => Class
|
17
|
+
* \endcode
|
18
|
+
*
|
19
|
+
* Instantiating that Class creates an instance of that Class:
|
20
|
+
* \code
|
21
|
+
* irb(main):003:0> mystruct_instance = MyStruct.new
|
22
|
+
* => #<struct MyStruct a=nil, b=nil, c=nil>
|
23
|
+
* irb(main):004:0> mystruct_instance.class
|
24
|
+
* => MyStruct
|
25
|
+
* irb(main):005:0> mystruct_instance.class.ancestors
|
26
|
+
* => [MyStruct, Struct, Enumerable, Object, Kernel]
|
27
|
+
* \endcode
|
28
|
+
*
|
29
|
+
* Thus, inside the interpreter, MyStruct is a Class which inherits
|
30
|
+
* from Struct, and mystruct_instance is an instance of MyStruct.
|
31
|
+
*
|
32
|
+
* At the C++ level, we might do this instead:
|
33
|
+
* \code
|
34
|
+
* Struct rb_cMyStruct = define_struct()
|
35
|
+
* .define_member("a")
|
36
|
+
* .define_member("b")
|
37
|
+
* .define_member("c")
|
38
|
+
* .initialize("MyStruct");
|
39
|
+
* Struct::Instance mystruct_instance(rb_cMyStruct.new_instance());
|
40
|
+
* \endcode
|
41
|
+
*
|
42
|
+
* Here rb_cMyStruct is an instance of Struct and that mystruct_instance
|
43
|
+
* is an instance of Struct::Instance.
|
44
|
+
*/
|
45
|
+
class Struct : public Class
|
46
|
+
{
|
47
|
+
public:
|
48
|
+
//! Define a new Struct member.
|
49
|
+
/*! Defines a new member of the Struct. Must be called before the
|
50
|
+
* Struct is initialized.
|
51
|
+
* \return *this
|
52
|
+
*/
|
53
|
+
Struct& define_member(Identifier name);
|
54
|
+
|
55
|
+
//! Initialize the Struct class.
|
56
|
+
/*! Must be called after all Struct members have been defined.
|
57
|
+
* \param module the module under which to define the Struct.
|
58
|
+
* \param name the name of the Class at the ruby level.
|
59
|
+
*/
|
60
|
+
Struct& initialize(Module module, Identifier name);
|
61
|
+
|
62
|
+
//! Get the members in Struct.
|
63
|
+
Array members() const;
|
64
|
+
|
65
|
+
class Instance;
|
66
|
+
friend class Instance;
|
67
|
+
//friend Struct Rice::define_struct();
|
68
|
+
|
69
|
+
//! Create a new instance of the Struct
|
70
|
+
/*! \param args the arguments to the constructor.
|
71
|
+
* \return a new Struct::Instance
|
72
|
+
*/
|
73
|
+
Instance new_instance(Array args = Array()) const;
|
74
|
+
|
75
|
+
private:
|
76
|
+
std::vector<Symbol> members_;
|
77
|
+
};
|
78
|
+
|
79
|
+
//! An instance of a Struct
|
80
|
+
//! \sa Struct
|
81
|
+
class Struct::Instance : public Builtin_Object<T_STRUCT>
|
82
|
+
{
|
83
|
+
public:
|
84
|
+
//! Create a new Instance of a Struct.
|
85
|
+
/*! \param type the Struct type to create.
|
86
|
+
* \param args the initial values for the objects of the instance.
|
87
|
+
*/
|
88
|
+
Instance(Struct const& type,Array args = Array());
|
89
|
+
|
90
|
+
//! Encapsulate an existing Struct instance.
|
91
|
+
/*! \param type the Struct type to encapsulate.
|
92
|
+
* \param s the instance to encapsulate.
|
93
|
+
*/
|
94
|
+
Instance(Struct const& type, Object s);
|
95
|
+
|
96
|
+
//! Get a member, given its offset.
|
97
|
+
/*! \param index the (integral) index into the Struct's internal
|
98
|
+
* array or its name (an Identifier or char const *)
|
99
|
+
* \return the member.
|
100
|
+
*/
|
101
|
+
template<typename T>
|
102
|
+
Object operator[](T index);
|
103
|
+
|
104
|
+
private:
|
105
|
+
Struct type_;
|
106
|
+
};
|
107
|
+
|
108
|
+
//! Define a new Struct
|
109
|
+
Struct define_struct();
|
110
|
+
|
111
|
+
} // namespace Rice
|
112
|
+
|
113
|
+
#endif // Rice__ruby_struct__hpp_
|
@@ -0,0 +1,92 @@
|
|
1
|
+
|
2
|
+
namespace Rice
|
3
|
+
{
|
4
|
+
inline Struct& Struct::initialize(Module module, Identifier name)
|
5
|
+
{
|
6
|
+
Class struct_class(rb_cStruct);
|
7
|
+
|
8
|
+
Object type = struct_class.vcall("new", this->members());
|
9
|
+
|
10
|
+
set_value(type);
|
11
|
+
module.const_set(name, type);
|
12
|
+
|
13
|
+
return *this;
|
14
|
+
}
|
15
|
+
|
16
|
+
inline Struct& Struct::define_member(Identifier name)
|
17
|
+
{
|
18
|
+
if (value() != rb_cObject)
|
19
|
+
{
|
20
|
+
throw std::runtime_error("struct is already initialized");
|
21
|
+
}
|
22
|
+
|
23
|
+
members_.push_back(name.to_sym());
|
24
|
+
|
25
|
+
return *this;
|
26
|
+
}
|
27
|
+
|
28
|
+
inline Array Struct::members() const
|
29
|
+
{
|
30
|
+
if (value() == rb_cObject)
|
31
|
+
{
|
32
|
+
// Struct is not yet defined
|
33
|
+
return Array(members_.begin(), members_.end());
|
34
|
+
}
|
35
|
+
else
|
36
|
+
{
|
37
|
+
// Struct is defined, call Ruby API
|
38
|
+
return rb_struct_s_members(this->value());
|
39
|
+
}
|
40
|
+
}
|
41
|
+
|
42
|
+
inline Struct::Instance Struct::new_instance(Array args) const
|
43
|
+
{
|
44
|
+
Object instance = const_cast<Struct*>(this)->vcall("new", args);
|
45
|
+
return Instance(*this, instance);
|
46
|
+
}
|
47
|
+
|
48
|
+
inline Struct::Instance::Instance(Struct const& type, Array args) :
|
49
|
+
Builtin_Object<T_STRUCT>(type.new_instance(args)), type_(type)
|
50
|
+
{
|
51
|
+
}
|
52
|
+
|
53
|
+
inline Struct::Instance::Instance(Struct const& type, Object s) :
|
54
|
+
Builtin_Object<T_STRUCT>(s), type_(type)
|
55
|
+
{
|
56
|
+
}
|
57
|
+
|
58
|
+
inline Struct define_struct()
|
59
|
+
{
|
60
|
+
return Struct();
|
61
|
+
}
|
62
|
+
|
63
|
+
template<typename T>
|
64
|
+
inline Object Struct::Instance::operator[](T index)
|
65
|
+
{
|
66
|
+
return rb_struct_aref(value(), ULONG2NUM(index));
|
67
|
+
}
|
68
|
+
|
69
|
+
template<>
|
70
|
+
inline Object Struct::Instance::operator[]<Identifier>(Identifier member)
|
71
|
+
{
|
72
|
+
return rb_struct_aref(value(), Symbol(member));
|
73
|
+
}
|
74
|
+
|
75
|
+
template<>
|
76
|
+
inline Object Struct::Instance::operator[]<char const*>(char const* name)
|
77
|
+
{
|
78
|
+
return (*this)[Identifier(name)];
|
79
|
+
}
|
80
|
+
}
|
81
|
+
|
82
|
+
namespace Rice::detail
|
83
|
+
{
|
84
|
+
template<>
|
85
|
+
struct Type<Struct>
|
86
|
+
{
|
87
|
+
static bool verify()
|
88
|
+
{
|
89
|
+
return true;
|
90
|
+
}
|
91
|
+
};
|
92
|
+
}
|
@@ -0,0 +1,46 @@
|
|
1
|
+
#ifndef Rice__Symbol__hpp_
|
2
|
+
#define Rice__Symbol__hpp_
|
3
|
+
|
4
|
+
namespace Rice
|
5
|
+
{
|
6
|
+
//! A wrapper for ruby's Symbol class.
|
7
|
+
/*! Symbols are internal identifiers in ruby. They are singletons and
|
8
|
+
* can be thought of as frozen strings. They differ from an Identifier
|
9
|
+
* in that they are in fact real Objects, but they can be converted
|
10
|
+
* back and forth between Identifier and Symbol.
|
11
|
+
*/
|
12
|
+
class Symbol
|
13
|
+
: public Object
|
14
|
+
{
|
15
|
+
public:
|
16
|
+
//! Wrap an existing symbol.
|
17
|
+
Symbol(VALUE v);
|
18
|
+
|
19
|
+
//! Wrap an existing symbol.
|
20
|
+
Symbol(Object v);
|
21
|
+
|
22
|
+
//! Construct a Symbol from an Identifier.
|
23
|
+
Symbol(Identifier id);
|
24
|
+
|
25
|
+
//! Construct a Symbol from a null-terminated C string.
|
26
|
+
Symbol(char const* s = "");
|
27
|
+
|
28
|
+
//! Construct a Symbol from an std::string.
|
29
|
+
Symbol(std::string const& s);
|
30
|
+
|
31
|
+
//! Construct a Symbol from an std::string_view.
|
32
|
+
Symbol(std::string_view const& s);
|
33
|
+
|
34
|
+
//! Return a string representation of the Symbol.
|
35
|
+
char const* c_str() const;
|
36
|
+
|
37
|
+
//! Return a string representation of the Symbol.
|
38
|
+
std::string str() const;
|
39
|
+
|
40
|
+
//! Return the Symbol as an Identifier.
|
41
|
+
Identifier to_id() const;
|
42
|
+
};
|
43
|
+
} // namespace Rice
|
44
|
+
|
45
|
+
#endif // Rice__Symbol__hpp_
|
46
|
+
|
@@ -0,0 +1,93 @@
|
|
1
|
+
namespace Rice
|
2
|
+
{
|
3
|
+
inline Symbol::Symbol(VALUE value) : Object(value)
|
4
|
+
{
|
5
|
+
detail::protect(rb_check_type, value, (int)T_SYMBOL);
|
6
|
+
}
|
7
|
+
|
8
|
+
inline Symbol::Symbol(Object value) : Object(value)
|
9
|
+
{
|
10
|
+
detail::protect(rb_check_type, value.value(), (int)T_SYMBOL);
|
11
|
+
}
|
12
|
+
|
13
|
+
inline Symbol::Symbol(char const* s)
|
14
|
+
: Object(detail::protect(rb_id2sym, detail::protect(rb_intern, s)))
|
15
|
+
{
|
16
|
+
}
|
17
|
+
|
18
|
+
inline Symbol::Symbol(std::string const& s)
|
19
|
+
: Object(detail::protect(rb_id2sym, detail::protect(rb_intern2, s.c_str(), (long)s.length())))
|
20
|
+
{
|
21
|
+
}
|
22
|
+
|
23
|
+
inline Symbol::Symbol(std::string_view const& view)
|
24
|
+
: Object(detail::protect(rb_id2sym, detail::protect(rb_intern2, view.data(), (long)view.length())))
|
25
|
+
{
|
26
|
+
}
|
27
|
+
|
28
|
+
inline Symbol::Symbol(Identifier id) : Object(detail::protect(rb_id2sym, id))
|
29
|
+
{
|
30
|
+
}
|
31
|
+
|
32
|
+
inline char const* Symbol::c_str() const
|
33
|
+
{
|
34
|
+
return to_id().c_str();
|
35
|
+
}
|
36
|
+
|
37
|
+
inline std::string Symbol::str() const
|
38
|
+
{
|
39
|
+
return to_id().str();
|
40
|
+
}
|
41
|
+
|
42
|
+
inline Identifier Symbol::to_id() const
|
43
|
+
{
|
44
|
+
return rb_to_id(value());
|
45
|
+
}
|
46
|
+
}
|
47
|
+
|
48
|
+
namespace Rice::detail
|
49
|
+
{
|
50
|
+
template<>
|
51
|
+
struct Type<Symbol>
|
52
|
+
{
|
53
|
+
static bool verify()
|
54
|
+
{
|
55
|
+
return true;
|
56
|
+
}
|
57
|
+
};
|
58
|
+
|
59
|
+
template<>
|
60
|
+
class To_Ruby<Symbol>
|
61
|
+
{
|
62
|
+
public:
|
63
|
+
VALUE convert(Symbol const& x)
|
64
|
+
{
|
65
|
+
return x.value();
|
66
|
+
}
|
67
|
+
};
|
68
|
+
|
69
|
+
template<>
|
70
|
+
class From_Ruby<Symbol>
|
71
|
+
{
|
72
|
+
public:
|
73
|
+
Convertible is_convertible(VALUE value)
|
74
|
+
{
|
75
|
+
switch (rb_type(value))
|
76
|
+
{
|
77
|
+
case RUBY_T_SYMBOL:
|
78
|
+
return Convertible::Exact;
|
79
|
+
break;
|
80
|
+
case RUBY_T_STRING:
|
81
|
+
return Convertible::Cast;
|
82
|
+
break;
|
83
|
+
default:
|
84
|
+
return Convertible::None;
|
85
|
+
}
|
86
|
+
}
|
87
|
+
|
88
|
+
Symbol convert(VALUE value)
|
89
|
+
{
|
90
|
+
return Symbol(value);
|
91
|
+
}
|
92
|
+
};
|
93
|
+
}
|
@@ -0,0 +1,134 @@
|
|
1
|
+
// Include these methods to call methods from Module but return
|
2
|
+
// an instance of the current classes. This is an alternative to
|
3
|
+
// using CRTP.
|
4
|
+
|
5
|
+
|
6
|
+
//! Include a module.
|
7
|
+
/*! \param inc the module to be included.
|
8
|
+
* \return *this
|
9
|
+
*/
|
10
|
+
inline auto& include_module(Module const& inc)
|
11
|
+
{
|
12
|
+
detail::protect(rb_include_module, this->value(), inc.value());
|
13
|
+
return *this;
|
14
|
+
}
|
15
|
+
|
16
|
+
//! Define an instance method.
|
17
|
+
/*! The method's implementation can be a member function, plain function
|
18
|
+
* or lambda. The easiest case is a member function where the Ruby
|
19
|
+
* method maps one-to-one to the C++ method. In the case of a
|
20
|
+
* plain function or lambda, the first argument must be SELF - ie,
|
21
|
+
* the current object. If the type of the first argument is VALUE, then
|
22
|
+
* the current Ruby object is passed. If the type is a C++ class,
|
23
|
+
* then the C++ object is passed. If you don't want to include the
|
24
|
+
* SELF argument see define_function.
|
25
|
+
* Rice will automatically convert method parameters from Ruby to C++ and
|
26
|
+
* convert the return value from C++ to Ruby.
|
27
|
+
* \param name the name of the method
|
28
|
+
* \param func the implementation of the function, either a function
|
29
|
+
* pointer or a member function pointer.
|
30
|
+
* \param args a list of Arg instance used to define default parameters.
|
31
|
+
* \return *this
|
32
|
+
*/
|
33
|
+
template<typename Function_T, typename...Arg_Ts>
|
34
|
+
inline auto& define_method(std::string name, Function_T&& func, const Arg_Ts&...args)
|
35
|
+
{
|
36
|
+
MethodInfo* methodInfo = new MethodInfo(detail::method_traits<Function_T, true>::arity, args...);
|
37
|
+
this->wrap_native_call<true>(this->value(), name, std::forward<Function_T>(func), methodInfo);
|
38
|
+
return *this;
|
39
|
+
}
|
40
|
+
|
41
|
+
//! Define a function.
|
42
|
+
/*! The function implementation is a plain function or a static
|
43
|
+
* member function.
|
44
|
+
* Rice will automatically convert method method from Ruby to C++ and
|
45
|
+
* then convert the return value from C++ to Ruby.
|
46
|
+
* \param name the name of the method
|
47
|
+
* \param func the implementation of the function, either a function
|
48
|
+
* pointer or a member function pointer.
|
49
|
+
* \param args a list of Arg instance used to define default parameters (optional)
|
50
|
+
* \return *this
|
51
|
+
*/
|
52
|
+
template<typename Function_T, typename...Arg_Ts>
|
53
|
+
inline auto& define_function(std::string name, Function_T&& func, const Arg_Ts&...args)
|
54
|
+
{
|
55
|
+
MethodInfo* methodInfo = new MethodInfo(detail::method_traits<Function_T, false>::arity, args...);
|
56
|
+
this->wrap_native_call<false>(this->value(), name, std::forward<Function_T>(func), methodInfo);
|
57
|
+
return *this;
|
58
|
+
}
|
59
|
+
|
60
|
+
//! Define a singleton method.
|
61
|
+
/*! The method's implementation can be a static member function,
|
62
|
+
* plain function or lambda. In all cases the first argument
|
63
|
+
* must be SELF - ie, the current object. If it is specified as a VALUE, then
|
64
|
+
* the current Ruby object is passed. If it is specified as a C++ class,
|
65
|
+
* then the C++ object is passed. If you don't want to include the
|
66
|
+
* SELF argument see define_singleton_function.
|
67
|
+
* Rice will automatically convert method method from Ruby to C++ and
|
68
|
+
* then convert the return value from C++ to Ruby.
|
69
|
+
* \param name the name of the method
|
70
|
+
* \param func the implementation of the function, either a function
|
71
|
+
* pointer or a member function pointer.
|
72
|
+
* \param args a list of Arg instance used to define default parameters (optional)
|
73
|
+
* \return *this
|
74
|
+
*/
|
75
|
+
template<typename Function_T, typename...Arg_Ts>
|
76
|
+
inline auto& define_singleton_method(std::string name, Function_T&& func, const Arg_Ts&...args)
|
77
|
+
{
|
78
|
+
MethodInfo* methodInfo = new MethodInfo(detail::method_traits<Function_T, true>::arity, args...);
|
79
|
+
this->wrap_native_call<true>(rb_singleton_class(*this), name, std::forward<Function_T>(func), methodInfo);
|
80
|
+
return *this;
|
81
|
+
}
|
82
|
+
|
83
|
+
//! Define a singleton method.
|
84
|
+
/*! The method's implementation can be a static member function, plain
|
85
|
+
* function or lambda. A wrapper will be generated which will convert the method
|
86
|
+
* from ruby types to C++ types before calling the function. The return
|
87
|
+
* value will be converted back to ruby.
|
88
|
+
* \param name the name of the method
|
89
|
+
* \param func the implementation of the function, either a function
|
90
|
+
* pointer or a member function pointer.
|
91
|
+
* \param args a list of Arg instance used to define default parameters (optional)
|
92
|
+
* \return *this
|
93
|
+
*/
|
94
|
+
template<typename Function_T, typename...Arg_Ts>
|
95
|
+
inline auto& define_singleton_function(std::string name, Function_T&& func, const Arg_Ts& ...args)
|
96
|
+
{
|
97
|
+
MethodInfo* methodInfo = new MethodInfo(detail::method_traits<Function_T, false>::arity, args...);
|
98
|
+
this->wrap_native_call<false>(rb_singleton_class(*this), name, std::forward<Function_T>(func), methodInfo);
|
99
|
+
return *this;
|
100
|
+
}
|
101
|
+
|
102
|
+
//! Define a module function.
|
103
|
+
/*! A module function is a function that can be accessed either as a
|
104
|
+
* singleton method or as an instance method. It wrap a plain
|
105
|
+
* function, static member function or lambda.
|
106
|
+
* Rice will automatically convert method method from Ruby to C++ and
|
107
|
+
* then convert the return value from C++ to Ruby.
|
108
|
+
* \param name the name of the method
|
109
|
+
* \param func the implementation of the function, either a function
|
110
|
+
* pointer or a member function pointer.
|
111
|
+
* \param args a list of Arg instance used to define default parameters (optional)
|
112
|
+
* \return *this
|
113
|
+
*/
|
114
|
+
template<typename Function_T, typename...Arg_Ts>
|
115
|
+
inline auto& define_module_function(std::string name, Function_T&& func, const Arg_Ts& ...args)
|
116
|
+
{
|
117
|
+
if (this->rb_type() != T_MODULE)
|
118
|
+
{
|
119
|
+
throw std::runtime_error("can only define module functions for modules");
|
120
|
+
}
|
121
|
+
|
122
|
+
define_function(name, std::forward<Function_T>(func), args...);
|
123
|
+
define_singleton_function(name, std::forward<Function_T>(func), args...);
|
124
|
+
return *this;
|
125
|
+
}
|
126
|
+
|
127
|
+
//! Define a constant
|
128
|
+
template<typename Constant_T>
|
129
|
+
inline auto& define_constant(std::string name, Constant_T value)
|
130
|
+
{
|
131
|
+
using Base_T = detail::remove_cv_recursive_t<Constant_T>;
|
132
|
+
detail::protect(rb_define_const, this->value(), name.c_str(), detail::To_Ruby<Base_T>().convert(value));
|
133
|
+
return *this;
|
134
|
+
}
|
data/rice/detail/MethodInfo.hpp
CHANGED
@@ -13,12 +13,6 @@ namespace Rice
|
|
13
13
|
template <typename...Arg_Ts>
|
14
14
|
MethodInfo(size_t argCount, const Arg_Ts&...args);
|
15
15
|
|
16
|
-
/**
|
17
|
-
* Get the rb_scan_args format string for this
|
18
|
-
* list of arguments.
|
19
|
-
*/
|
20
|
-
std::string formatString();
|
21
|
-
|
22
16
|
/**
|
23
17
|
* Add a defined Arg to this list of Arguments
|
24
18
|
*/
|
@@ -34,9 +28,7 @@ namespace Rice
|
|
34
28
|
*/
|
35
29
|
Arg* arg(std::string name);
|
36
30
|
|
37
|
-
int
|
38
|
-
int optionalArgCount();
|
39
|
-
void verifyArgCount(int argc);
|
31
|
+
int argCount();
|
40
32
|
|
41
33
|
// Iterator support
|
42
34
|
std::vector<Arg>::iterator begin();
|
data/rice/detail/MethodInfo.ipp
CHANGED
@@ -25,11 +25,13 @@ namespace Rice
|
|
25
25
|
template <typename Arg_T>
|
26
26
|
inline void MethodInfo::processArg(const Arg_T& arg)
|
27
27
|
{
|
28
|
+
static_assert(std::is_same_v<Arg_T, Return> || std::is_same_v<Arg_T, Arg>, "Unknown argument type");
|
29
|
+
|
28
30
|
if constexpr (std::is_same_v<Arg_T, Return>)
|
29
31
|
{
|
30
32
|
this->returnInfo = arg;
|
31
33
|
}
|
32
|
-
else
|
34
|
+
else if constexpr (std::is_same_v<Arg_T, Arg>)
|
33
35
|
{
|
34
36
|
this->addArg(arg);
|
35
37
|
}
|
@@ -40,78 +42,9 @@ namespace Rice
|
|
40
42
|
this->args_.push_back(arg);
|
41
43
|
}
|
42
44
|
|
43
|
-
inline int MethodInfo::
|
44
|
-
{
|
45
|
-
int result = 0;
|
46
|
-
|
47
|
-
for (const Arg& arg : this->args_)
|
48
|
-
{
|
49
|
-
if (!arg.hasDefaultValue())
|
50
|
-
{
|
51
|
-
result++;
|
52
|
-
}
|
53
|
-
}
|
54
|
-
|
55
|
-
return result;
|
56
|
-
}
|
57
|
-
|
58
|
-
inline int MethodInfo::optionalArgCount()
|
59
|
-
{
|
60
|
-
int result = 0;
|
61
|
-
|
62
|
-
for (const Arg& arg : this->args_)
|
63
|
-
{
|
64
|
-
if (arg.hasDefaultValue())
|
65
|
-
{
|
66
|
-
result++;
|
67
|
-
}
|
68
|
-
}
|
69
|
-
|
70
|
-
return result;
|
71
|
-
}
|
72
|
-
|
73
|
-
inline void MethodInfo::verifyArgCount(int argc)
|
45
|
+
inline int MethodInfo::argCount()
|
74
46
|
{
|
75
|
-
|
76
|
-
int optionalArgCount = this->optionalArgCount();
|
77
|
-
|
78
|
-
if (argc < requiredArgCount || argc > requiredArgCount + optionalArgCount)
|
79
|
-
{
|
80
|
-
std::string message;
|
81
|
-
|
82
|
-
if (optionalArgCount > 0)
|
83
|
-
{
|
84
|
-
message = "wrong number of arguments (given " +
|
85
|
-
std::to_string(argc) + ", expected " +
|
86
|
-
std::to_string(requiredArgCount) + ".." + std::to_string(requiredArgCount + optionalArgCount) + ")";
|
87
|
-
}
|
88
|
-
else
|
89
|
-
{
|
90
|
-
message = "wrong number of arguments (given " +
|
91
|
-
std::to_string(argc) + ", expected " + std::to_string(requiredArgCount) + ")";
|
92
|
-
}
|
93
|
-
throw std::invalid_argument(message);
|
94
|
-
}
|
95
|
-
}
|
96
|
-
|
97
|
-
inline std::string MethodInfo::formatString()
|
98
|
-
{
|
99
|
-
size_t required = 0;
|
100
|
-
size_t optional = 0;
|
101
|
-
|
102
|
-
for (const Arg& arg : this->args_)
|
103
|
-
{
|
104
|
-
if (arg.hasDefaultValue())
|
105
|
-
{
|
106
|
-
optional++;
|
107
|
-
}
|
108
|
-
else
|
109
|
-
{
|
110
|
-
required++;
|
111
|
-
}
|
112
|
-
}
|
113
|
-
|
114
|
-
return std::to_string(required) + std::to_string(optional);
|
47
|
+
return this->args_.size();
|
115
48
|
}
|
116
49
|
|
117
50
|
inline Arg* MethodInfo::arg(size_t pos)
|
data/rice/detail/Native.hpp
CHANGED
@@ -24,8 +24,9 @@ namespace Rice::detail
|
|
24
24
|
virtual ~Native() = default;
|
25
25
|
VALUE call(int argc, VALUE* argv, VALUE self);
|
26
26
|
|
27
|
-
virtual Resolved matches(
|
28
|
-
virtual VALUE operator()(
|
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;
|
29
30
|
};
|
30
31
|
}
|
31
32
|
|
data/rice/detail/Native.ipp
CHANGED
@@ -83,6 +83,8 @@ namespace Rice::detail
|
|
83
83
|
}
|
84
84
|
else
|
85
85
|
{
|
86
|
+
Identifier identifier(methodId);
|
87
|
+
|
86
88
|
// Loop over every native to see how well they match the Ruby parameters
|
87
89
|
std::vector<Resolved> resolves;
|
88
90
|
std::transform(natives.begin(), natives.end(),
|
@@ -95,9 +97,30 @@ namespace Rice::detail
|
|
95
97
|
// Now sort from best to worst
|
96
98
|
std::sort(resolves.begin(), resolves.end(), std::greater{});
|
97
99
|
|
98
|
-
// Get the
|
100
|
+
// Get the first one
|
99
101
|
Resolved resolved = resolves.front();
|
100
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
|
+
|
101
124
|
// Did it match?
|
102
125
|
if (resolved.convertible != Convertible::None)
|
103
126
|
{
|
@@ -107,7 +130,6 @@ namespace Rice::detail
|
|
107
130
|
{
|
108
131
|
// Special case == to make the RubyMine debugger work. It calls == with a Module as
|
109
132
|
// the other argument, thus breaking if C++ operator== is implemented.
|
110
|
-
Identifier identifier(methodId);
|
111
133
|
if (identifier.str() == "==")
|
112
134
|
{
|
113
135
|
return detail::protect(rb_call_super, argc, argv);
|
@@ -116,8 +138,14 @@ namespace Rice::detail
|
|
116
138
|
{
|
117
139
|
std::ostringstream message;
|
118
140
|
message << "Could not resolve method call for %s#%s" << "\n"
|
119
|
-
<< " %d overload(s) were evaluated based on the types of Ruby parameters provided
|
120
|
-
|
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());
|
121
149
|
}
|
122
150
|
}
|
123
151
|
}
|
@@ -34,8 +34,9 @@ namespace Rice
|
|
34
34
|
void operator=(const NativeAttribute_T&) = delete;
|
35
35
|
void operator=(NativeAttribute_T&&) = delete;
|
36
36
|
|
37
|
-
Resolved matches(
|
38
|
-
VALUE operator()(
|
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;
|
39
40
|
|
40
41
|
protected:
|
41
42
|
NativeAttributeGet(VALUE klass, std::string name, Attribute_T attr);
|