rice 4.3.2 → 4.5.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 +66 -25
- data/README.md +7 -2
- data/Rakefile +7 -1
- data/include/rice/rice.hpp +7321 -4470
- data/include/rice/stl.hpp +769 -222
- data/lib/mkmf-rice.rb +37 -95
- data/rice/Address_Registration_Guard.hpp +72 -3
- data/rice/Arg.hpp +19 -5
- data/rice/Arg.ipp +24 -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 +74 -3
- data/rice/Data_Object.ipp +324 -32
- data/rice/Data_Type.hpp +215 -3
- data/rice/Data_Type.ipp +125 -64
- data/rice/Director.hpp +0 -2
- data/rice/Enum.hpp +4 -6
- data/rice/Enum.ipp +101 -57
- data/rice/Exception.hpp +62 -2
- data/rice/Exception.ipp +7 -12
- data/rice/JumpException.hpp +44 -0
- data/rice/JumpException.ipp +48 -0
- data/rice/MemoryView.hpp +11 -0
- data/rice/MemoryView.ipp +43 -0
- data/rice/Return.hpp +6 -26
- data/rice/Return.ipp +10 -16
- 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 +15 -5
- data/rice/detail/MethodInfo.ipp +78 -6
- data/rice/detail/Native.hpp +32 -0
- data/rice/detail/Native.ipp +129 -0
- data/rice/detail/NativeAttributeGet.hpp +51 -0
- data/rice/detail/NativeAttributeGet.ipp +51 -0
- data/rice/detail/NativeAttributeSet.hpp +43 -0
- data/rice/detail/NativeAttributeSet.ipp +82 -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 +20 -21
- data/rice/detail/NativeFunction.ipp +199 -64
- data/rice/detail/NativeIterator.hpp +8 -11
- data/rice/detail/NativeIterator.ipp +27 -31
- data/rice/detail/NativeRegistry.hpp +24 -17
- data/rice/detail/NativeRegistry.ipp +23 -56
- 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 +19 -0
- data/rice/detail/RubyType.ipp +187 -0
- data/rice/detail/TupleIterator.hpp +14 -0
- data/rice/detail/Type.hpp +5 -6
- data/rice/detail/Type.ipp +150 -33
- data/rice/detail/TypeRegistry.hpp +15 -7
- data/rice/detail/TypeRegistry.ipp +105 -12
- data/rice/detail/Wrapper.hpp +6 -5
- data/rice/detail/Wrapper.ipp +45 -23
- data/rice/detail/cpp_protect.hpp +5 -6
- data/rice/detail/default_allocation_func.ipp +0 -2
- data/rice/detail/from_ruby.hpp +37 -3
- data/rice/detail/from_ruby.ipp +911 -454
- data/rice/detail/ruby.hpp +18 -0
- data/rice/detail/to_ruby.hpp +41 -3
- data/rice/detail/to_ruby.ipp +437 -113
- data/rice/global_function.hpp +0 -4
- data/rice/global_function.ipp +1 -2
- data/rice/rice.hpp +105 -22
- data/rice/ruby_mark.hpp +4 -3
- data/rice/stl.hpp +4 -0
- data/test/embed_ruby.cpp +4 -1
- data/test/extconf.rb +2 -0
- data/test/ruby/test_multiple_extensions_same_class.rb +14 -14
- data/test/test_Address_Registration_Guard.cpp +5 -0
- data/test/test_Array.cpp +12 -1
- data/test/test_Attribute.cpp +103 -21
- data/test/test_Builtin_Object.cpp +5 -0
- data/test/test_Callback.cpp +231 -0
- data/test/test_Class.cpp +5 -31
- data/test/test_Constructor.cpp +69 -6
- data/test/test_Data_Object.cpp +9 -4
- data/test/test_Data_Type.cpp +428 -64
- data/test/test_Director.cpp +10 -5
- data/test/test_Enum.cpp +152 -40
- data/test/test_Exception.cpp +235 -0
- data/test/test_File.cpp +70 -0
- data/test/test_From_Ruby.cpp +542 -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 +5 -0
- data/test/test_JumpException.cpp +22 -0
- data/test/test_Keep_Alive.cpp +6 -1
- data/test/test_Keep_Alive_No_Wrapper.cpp +5 -0
- data/test/test_Memory_Management.cpp +5 -0
- data/test/test_Module.cpp +118 -64
- data/test/test_Native_Registry.cpp +2 -33
- data/test/test_Object.cpp +5 -0
- data/test/test_Overloads.cpp +631 -0
- data/test/test_Ownership.cpp +67 -4
- data/test/test_Proc.cpp +45 -0
- data/test/test_Self.cpp +5 -0
- data/test/test_Stl_Exception.cpp +109 -0
- data/test/test_Stl_Map.cpp +22 -8
- data/test/test_Stl_Optional.cpp +5 -0
- data/test/test_Stl_Pair.cpp +7 -2
- data/test/test_Stl_Reference_Wrapper.cpp +5 -0
- data/test/test_Stl_SmartPointer.cpp +210 -5
- data/test/test_Stl_String.cpp +5 -0
- data/test/test_Stl_String_View.cpp +5 -0
- data/test/test_Stl_Type.cpp +147 -0
- data/test/test_Stl_Unordered_Map.cpp +18 -7
- data/test/test_Stl_Variant.cpp +5 -0
- data/test/test_Stl_Vector.cpp +130 -8
- 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 +152 -0
- data/test/test_Tracking.cpp +1 -0
- data/test/test_Type.cpp +100 -0
- data/test/test_global_functions.cpp +53 -6
- data/test/unittest.cpp +8 -0
- metadata +37 -20
- 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/Identifier.hpp +0 -50
- data/rice/Identifier.ipp +0 -29
- 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_To_From_Ruby.cpp +0 -399
@@ -0,0 +1,51 @@
|
|
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(int argc, const VALUE* argv, VALUE self) override;
|
38
|
+
VALUE operator()(int argc, const VALUE* argv, VALUE self) override;
|
39
|
+
|
40
|
+
protected:
|
41
|
+
NativeAttributeGet(VALUE klass, std::string name, Attribute_T attr);
|
42
|
+
|
43
|
+
private:
|
44
|
+
VALUE klass_;
|
45
|
+
std::string name_;
|
46
|
+
Attribute_T attribute_;
|
47
|
+
};
|
48
|
+
} // detail
|
49
|
+
} // Rice
|
50
|
+
|
51
|
+
#endif // Rice__detail__Native_Attribute_Get__hpp_
|
@@ -0,0 +1,51 @@
|
|
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(int 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()(int 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
|
+
} // Rice
|
@@ -0,0 +1,43 @@
|
|
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(int argc, const VALUE* argv, VALUE self) override;
|
30
|
+
VALUE operator()(int argc, const VALUE* argv, VALUE self) override;
|
31
|
+
|
32
|
+
protected:
|
33
|
+
NativeAttributeSet(VALUE klass, std::string name, Attribute_T attr);
|
34
|
+
|
35
|
+
private:
|
36
|
+
VALUE klass_;
|
37
|
+
std::string name_;
|
38
|
+
Attribute_T attribute_;
|
39
|
+
};
|
40
|
+
} // detail
|
41
|
+
} // Rice
|
42
|
+
|
43
|
+
#endif // Rice__detail__Native_Attribute_Set__hpp_
|
@@ -0,0 +1,82 @@
|
|
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(int 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()(int 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
|
+
} // Rice
|
@@ -0,0 +1,55 @@
|
|
1
|
+
#ifndef Rice__detail__Native_Callback_Ffi_hpp_
|
2
|
+
#define Rice__detail__Native_Callback_Ffi_hpp_
|
3
|
+
|
4
|
+
#ifdef HAVE_LIBFFI
|
5
|
+
|
6
|
+
#include <ffi.h>
|
7
|
+
|
8
|
+
namespace Rice::detail
|
9
|
+
{
|
10
|
+
template<typename Callback_T>
|
11
|
+
class NativeCallbackFFI;
|
12
|
+
|
13
|
+
template<typename Return_T, typename ...Arg_Ts>
|
14
|
+
class NativeCallbackFFI<Return_T(*)(Arg_Ts...)>
|
15
|
+
{
|
16
|
+
public:
|
17
|
+
using Callback_T = Return_T(Arg_Ts...);
|
18
|
+
using Tuple_T = std::tuple<Arg_Ts...>;
|
19
|
+
static void ffiCallback(ffi_cif* cif, void* ret, void* args[], void* instance);
|
20
|
+
static VALUE finalizerCallback(VALUE yielded_arg, VALUE callback_arg, int argc, const VALUE* argv, VALUE blockarg);
|
21
|
+
static void setMethodInfo(MethodInfo* methodInfo);
|
22
|
+
|
23
|
+
public:
|
24
|
+
NativeCallbackFFI(VALUE proc);
|
25
|
+
~NativeCallbackFFI();
|
26
|
+
NativeCallbackFFI(const NativeCallbackFFI&) = delete;
|
27
|
+
NativeCallbackFFI(NativeCallbackFFI&&) = delete;
|
28
|
+
void operator=(const NativeCallbackFFI&) = delete;
|
29
|
+
void operator=(NativeCallbackFFI&&) = delete;
|
30
|
+
|
31
|
+
Return_T operator()(Arg_Ts...args);
|
32
|
+
Callback_T* callback();
|
33
|
+
|
34
|
+
private:
|
35
|
+
template <typename Arg_T>
|
36
|
+
static ffi_type* ffiType();
|
37
|
+
|
38
|
+
template<std::size_t... I>
|
39
|
+
static Tuple_T convertArgsToTuple(void* args[], std::index_sequence<I...>& indices);
|
40
|
+
|
41
|
+
static inline std::array<ffi_type*, sizeof...(Arg_Ts)> args_ = { ffiType<Arg_Ts>()... };
|
42
|
+
static inline ffi_cif cif_;
|
43
|
+
static inline ffi_closure* closure_ = nullptr;
|
44
|
+
static inline Callback_T* callback_ = nullptr;
|
45
|
+
static inline std::unique_ptr<MethodInfo> methodInfo_ = std::make_unique<MethodInfo>();
|
46
|
+
|
47
|
+
template<std::size_t... I>
|
48
|
+
Return_T callRuby(std::index_sequence<I...>& indices, Arg_Ts...args);
|
49
|
+
private:
|
50
|
+
VALUE proc_;
|
51
|
+
};
|
52
|
+
}
|
53
|
+
#endif // HAVE_LIBFFI
|
54
|
+
|
55
|
+
#endif // Rice__detail__Native_Callback_Ffi_hpp_
|
@@ -0,0 +1,151 @@
|
|
1
|
+
#ifdef HAVE_LIBFFI
|
2
|
+
#include <ffi.h>
|
3
|
+
|
4
|
+
namespace Rice::detail
|
5
|
+
{
|
6
|
+
template<typename Return_T, typename ...Arg_Ts>
|
7
|
+
template<typename Arg_T>
|
8
|
+
ffi_type* NativeCallbackFFI<Return_T(*)(Arg_Ts...)>::ffiType()
|
9
|
+
{
|
10
|
+
std::map<std::type_index, ffi_type*> nativeToFfiMapping = {
|
11
|
+
{std::type_index(typeid(bool)), &ffi_type_uint8},
|
12
|
+
{std::type_index(typeid(bool)), &ffi_type_uint8},
|
13
|
+
{std::type_index(typeid(char)), &ffi_type_schar},
|
14
|
+
{std::type_index(typeid(unsigned char)), &ffi_type_uchar},
|
15
|
+
{std::type_index(typeid(signed char)), &ffi_type_schar},
|
16
|
+
{std::type_index(typeid(uint8_t)), &ffi_type_uint8},
|
17
|
+
{std::type_index(typeid(unsigned short)), &ffi_type_uint8},
|
18
|
+
{std::type_index(typeid(int8_t)), &ffi_type_sint8},
|
19
|
+
{std::type_index(typeid(short)), &ffi_type_sint8},
|
20
|
+
{std::type_index(typeid(uint16_t)), &ffi_type_uint16},
|
21
|
+
{std::type_index(typeid(int16_t)), &ffi_type_sint16},
|
22
|
+
{std::type_index(typeid(uint32_t)), &ffi_type_uint32},
|
23
|
+
{std::type_index(typeid(unsigned int)), &ffi_type_uint32},
|
24
|
+
{std::type_index(typeid(signed int)), &ffi_type_uint32},
|
25
|
+
{std::type_index(typeid(int32_t)), &ffi_type_sint32},
|
26
|
+
{std::type_index(typeid(uint64_t)), &ffi_type_uint64},
|
27
|
+
{std::type_index(typeid(unsigned long long)), &ffi_type_uint64},
|
28
|
+
{std::type_index(typeid(int64_t)), &ffi_type_sint64},
|
29
|
+
{std::type_index(typeid(signed long long)), &ffi_type_sint64},
|
30
|
+
{std::type_index(typeid(float)), &ffi_type_float},
|
31
|
+
{std::type_index(typeid(double)), &ffi_type_double},
|
32
|
+
{std::type_index(typeid(void)), &ffi_type_pointer},
|
33
|
+
{std::type_index(typeid(long double)), &ffi_type_longdouble}
|
34
|
+
};
|
35
|
+
|
36
|
+
if (sizeof(long) == 32)
|
37
|
+
{
|
38
|
+
nativeToFfiMapping[std::type_index(typeid(unsigned long))] = &ffi_type_uint32;
|
39
|
+
nativeToFfiMapping[std::type_index(typeid(long))] = &ffi_type_sint32;
|
40
|
+
}
|
41
|
+
else if (sizeof(long) == 64)
|
42
|
+
{
|
43
|
+
nativeToFfiMapping[std::type_index(typeid(unsigned long))] = &ffi_type_uint64;
|
44
|
+
nativeToFfiMapping[std::type_index(typeid(long))] = &ffi_type_sint64;
|
45
|
+
}
|
46
|
+
|
47
|
+
if (std::is_pointer_v<Arg_T>)
|
48
|
+
{
|
49
|
+
return &ffi_type_pointer;
|
50
|
+
}
|
51
|
+
else
|
52
|
+
{
|
53
|
+
const std::type_index& key = std::type_index(typeid(Arg_T));
|
54
|
+
return nativeToFfiMapping[key];
|
55
|
+
}
|
56
|
+
}
|
57
|
+
|
58
|
+
template<typename Return_T, typename ...Arg_Ts>
|
59
|
+
template<std::size_t... I>
|
60
|
+
typename NativeCallbackFFI<Return_T(*)(Arg_Ts...)>::Tuple_T NativeCallbackFFI<Return_T(*)(Arg_Ts...)>::convertArgsToTuple(void* args[], std::index_sequence<I...>& indices)
|
61
|
+
{
|
62
|
+
/* Loop over each value returned from Ruby and convert it to the appropriate C++ type based
|
63
|
+
on the arguments (Arg_Ts) required by the C++ function. Arg_T may have const/volatile while
|
64
|
+
the associated From_Ruby<T> template parameter will not. Thus From_Ruby produces non-const values
|
65
|
+
which we let the compiler convert to const values as needed. This works except for
|
66
|
+
T** -> const T**, see comment in getNativeValue method. */
|
67
|
+
return std::forward_as_tuple(*(std::tuple_element_t<I, Tuple_T>*)(args[I])...);
|
68
|
+
}
|
69
|
+
|
70
|
+
template<typename Return_T, typename ...Arg_Ts>
|
71
|
+
void NativeCallbackFFI<Return_T(*)(Arg_Ts...)>::ffiCallback(ffi_cif* cif, void* ret, void* args[], void* instance)
|
72
|
+
{
|
73
|
+
using Self_T = NativeCallbackFFI<Return_T(*)(Arg_Ts...)>;
|
74
|
+
Self_T* self = (Self_T*)instance;
|
75
|
+
|
76
|
+
auto indices = std::make_index_sequence<sizeof...(Arg_Ts)>{};
|
77
|
+
|
78
|
+
if constexpr (sizeof...(Arg_Ts) == 0)
|
79
|
+
{
|
80
|
+
*(Return_T*)ret = self->operator()();
|
81
|
+
}
|
82
|
+
else
|
83
|
+
{
|
84
|
+
std::tuple<Arg_Ts...> tuple = convertArgsToTuple(args, indices);
|
85
|
+
*(Return_T*)ret = std::apply(*self, tuple);
|
86
|
+
}
|
87
|
+
}
|
88
|
+
|
89
|
+
template<typename Return_T, typename ...Arg_Ts>
|
90
|
+
void NativeCallbackFFI<Return_T(*)(Arg_Ts...)>::setMethodInfo(MethodInfo* methodInfo)
|
91
|
+
{
|
92
|
+
methodInfo_.reset(methodInfo);
|
93
|
+
}
|
94
|
+
|
95
|
+
template<typename Return_T, typename ...Arg_Ts>
|
96
|
+
NativeCallbackFFI<Return_T(*)(Arg_Ts...)>::~NativeCallbackFFI()
|
97
|
+
{
|
98
|
+
this->proc_ = Qnil;
|
99
|
+
}
|
100
|
+
|
101
|
+
template<typename Return_T, typename ...Arg_Ts>
|
102
|
+
VALUE NativeCallbackFFI<Return_T(*)(Arg_Ts...)>::finalizerCallback(VALUE yielded_arg, VALUE callback_arg, int argc, const VALUE* argv, VALUE blockarg)
|
103
|
+
{
|
104
|
+
using NativeCallback_T = NativeCallbackFFI<Return_T(*)(Arg_Ts...)>;
|
105
|
+
NativeCallback_T* nativeCallback = (NativeCallback_T*)callback_arg;
|
106
|
+
delete nativeCallback;
|
107
|
+
return Qnil;
|
108
|
+
}
|
109
|
+
|
110
|
+
template<typename Return_T, typename ...Arg_Ts>
|
111
|
+
NativeCallbackFFI<Return_T(*)(Arg_Ts...)>::NativeCallbackFFI(VALUE proc) : proc_(proc)
|
112
|
+
{
|
113
|
+
// First setup desccription of callback
|
114
|
+
if (cif_.bytes == 0)
|
115
|
+
{
|
116
|
+
ffi_prep_cif(&cif_, FFI_DEFAULT_ABI, sizeof...(Arg_Ts), &ffi_type_pointer, args_.data());
|
117
|
+
}
|
118
|
+
|
119
|
+
// Create FFI closure
|
120
|
+
this->closure_ = (ffi_closure *)ffi_closure_alloc(sizeof(ffi_closure) + sizeof(void*), (void**)(&this->callback_));
|
121
|
+
ffi_status status = ffi_prep_closure_loc(this->closure_, &cif_, ffiCallback, (void*)this, (void*)this->callback_);
|
122
|
+
}
|
123
|
+
|
124
|
+
template<typename Return_T, typename ...Arg_Ts>
|
125
|
+
typename NativeCallbackFFI<Return_T(*)(Arg_Ts...)>::Callback_T* NativeCallbackFFI<Return_T(*)(Arg_Ts...)>::callback()
|
126
|
+
{
|
127
|
+
return (Callback_T*)this->callback_;
|
128
|
+
}
|
129
|
+
|
130
|
+
template<typename Return_T, typename ...Arg_Ts>
|
131
|
+
template<std::size_t... I>
|
132
|
+
Return_T NativeCallbackFFI<Return_T(*)(Arg_Ts...)>::callRuby(std::index_sequence<I...>& indices, Arg_Ts...args)
|
133
|
+
{
|
134
|
+
static Identifier id("call");
|
135
|
+
std::array<VALUE, sizeof...(Arg_Ts)> values = { detail::To_Ruby<detail::remove_cv_recursive_t<Arg_Ts>>(methodInfo_->arg(I)).convert(args)... };
|
136
|
+
VALUE result = detail::protect(rb_funcallv, this->proc_, id.id(), (int)sizeof...(Arg_Ts), values.data());
|
137
|
+
if constexpr (!std::is_void_v<Return_T>)
|
138
|
+
{
|
139
|
+
static From_Ruby<Return_T> fromRuby(dynamic_cast<Arg*>(&methodInfo_->returnInfo));
|
140
|
+
return fromRuby.convert(result);
|
141
|
+
}
|
142
|
+
}
|
143
|
+
|
144
|
+
template<typename Return_T, typename ...Arg_Ts>
|
145
|
+
Return_T NativeCallbackFFI<Return_T(*)(Arg_Ts...)>::operator()(Arg_Ts...args)
|
146
|
+
{
|
147
|
+
auto indices = std::make_index_sequence<sizeof...(Arg_Ts)>{};
|
148
|
+
return NativeCallbackFFI<Return_T(*)(Arg_Ts...)>::callRuby(indices, args...);
|
149
|
+
}
|
150
|
+
}
|
151
|
+
#endif // HAVE_LIBFFI
|
@@ -0,0 +1,30 @@
|
|
1
|
+
#ifndef Rice__detail__Native_Callback_Simple_hpp_
|
2
|
+
#define Rice__detail__Native_Callback_Simple_hpp_
|
3
|
+
|
4
|
+
namespace Rice::detail
|
5
|
+
{
|
6
|
+
template<typename Callback_T>
|
7
|
+
class NativeCallbackSimple;
|
8
|
+
|
9
|
+
template<typename Return_T, typename ...Arg_Ts>
|
10
|
+
class NativeCallbackSimple<Return_T(*)(Arg_Ts...)>
|
11
|
+
{
|
12
|
+
public:
|
13
|
+
static Return_T callback(Arg_Ts...args);
|
14
|
+
static inline VALUE proc = Qnil;
|
15
|
+
static void setMethodInfo(MethodInfo* methodInfo);
|
16
|
+
|
17
|
+
public:
|
18
|
+
NativeCallbackSimple() = delete;
|
19
|
+
NativeCallbackSimple(const NativeCallbackSimple&) = delete;
|
20
|
+
NativeCallbackSimple(NativeCallbackSimple&&) = delete;
|
21
|
+
void operator=(const NativeCallbackSimple&) = delete;
|
22
|
+
void operator=(NativeCallbackSimple&&) = delete;
|
23
|
+
|
24
|
+
private:
|
25
|
+
template<std::size_t... I>
|
26
|
+
static Return_T callRuby(std::index_sequence<I...>& indices, Arg_Ts...args);
|
27
|
+
static inline std::unique_ptr<MethodInfo> methodInfo_ = std::make_unique<MethodInfo>();
|
28
|
+
};
|
29
|
+
}
|
30
|
+
#endif // Rice__detail__Native_Callback_Simple_hpp_
|
@@ -0,0 +1,29 @@
|
|
1
|
+
namespace Rice::detail
|
2
|
+
{
|
3
|
+
template<typename Return_T, typename ...Arg_Ts>
|
4
|
+
void NativeCallbackSimple<Return_T(*)(Arg_Ts...)>::setMethodInfo(MethodInfo* methodInfo)
|
5
|
+
{
|
6
|
+
methodInfo_.reset(methodInfo);
|
7
|
+
}
|
8
|
+
|
9
|
+
template<typename Return_T, typename ...Arg_Ts>
|
10
|
+
template<std::size_t... I>
|
11
|
+
Return_T NativeCallbackSimple<Return_T(*)(Arg_Ts...)>::callRuby(std::index_sequence<I...>& indices, Arg_Ts...args)
|
12
|
+
{
|
13
|
+
static Identifier id("call");
|
14
|
+
std::array<VALUE, sizeof...(Arg_Ts)> values = { detail::To_Ruby<detail::remove_cv_recursive_t<Arg_Ts>>(methodInfo_->arg(I)).convert(args)... };
|
15
|
+
VALUE result = detail::protect(rb_funcallv, proc, id.id(), (int)sizeof...(Arg_Ts), values.data());
|
16
|
+
if constexpr (!std::is_void_v<Return_T>)
|
17
|
+
{
|
18
|
+
static From_Ruby<Return_T> fromRuby(dynamic_cast<Arg*>(&methodInfo_->returnInfo));
|
19
|
+
return fromRuby.convert(result);
|
20
|
+
}
|
21
|
+
}
|
22
|
+
|
23
|
+
template<typename Return_T, typename ...Arg_Ts>
|
24
|
+
Return_T NativeCallbackSimple<Return_T(*)(Arg_Ts...)>::callback(Arg_Ts...args)
|
25
|
+
{
|
26
|
+
auto indices = std::make_index_sequence<sizeof...(Arg_Ts)>{};
|
27
|
+
return NativeCallbackSimple<Return_T(*)(Arg_Ts...)>::callRuby(indices, args...);
|
28
|
+
}
|
29
|
+
}
|
@@ -1,13 +1,6 @@
|
|
1
1
|
#ifndef Rice__detail__Native_Function__hpp_
|
2
2
|
#define Rice__detail__Native_Function__hpp_
|
3
3
|
|
4
|
-
#include "ruby.hpp"
|
5
|
-
#include "ExceptionHandler_defn.hpp"
|
6
|
-
#include "MethodInfo.hpp"
|
7
|
-
#include "../traits/function_traits.hpp"
|
8
|
-
#include "../traits/method_traits.hpp"
|
9
|
-
#include "from_ruby.hpp"
|
10
|
-
|
11
4
|
namespace Rice::detail
|
12
5
|
{
|
13
6
|
//! The NativeFunction class calls C++ functions/methods/lambdas on behalf of Ruby
|
@@ -43,24 +36,26 @@ namespace Rice::detail
|
|
43
36
|
*/
|
44
37
|
|
45
38
|
template<typename Class_T, typename Function_T, bool IsMethod>
|
46
|
-
class NativeFunction
|
39
|
+
class NativeFunction: Native
|
47
40
|
{
|
48
41
|
public:
|
49
42
|
using NativeFunction_T = NativeFunction<Class_T, Function_T, IsMethod>;
|
50
43
|
|
51
44
|
// We remove const to avoid an explosion of To_Ruby specializations and Ruby doesn't
|
52
45
|
// have the concept of constants anyways
|
53
|
-
using Return_T =
|
46
|
+
using Return_T = typename function_traits<Function_T>::return_type;
|
54
47
|
using Receiver_T = typename method_traits<Function_T, IsMethod>::Class_T;
|
55
48
|
using Arg_Ts = typename method_traits<Function_T, IsMethod>::Arg_Ts;
|
49
|
+
static constexpr std::size_t arity = method_traits<Function_T, IsMethod>::arity;
|
56
50
|
using From_Ruby_Args_Ts = typename tuple_map<From_Ruby, Arg_Ts>::type;
|
51
|
+
using To_Ruby_T = remove_cv_recursive_t<Return_T>;
|
57
52
|
|
58
53
|
// Register function with Ruby
|
59
54
|
static void define(VALUE klass, std::string method_name, Function_T function, MethodInfo* methodInfo);
|
60
55
|
|
61
|
-
//
|
62
|
-
static VALUE
|
63
|
-
|
56
|
+
// Proc entry
|
57
|
+
static VALUE procEntry(VALUE yielded_arg, VALUE callback_arg, int argc, const VALUE* argv, VALUE blockarg);
|
58
|
+
static VALUE finalizerCallback(VALUE yielded_arg, VALUE callback_arg, int argc, const VALUE* argv, VALUE blockarg);
|
64
59
|
public:
|
65
60
|
// Disallow creating/copying/moving
|
66
61
|
NativeFunction() = delete;
|
@@ -69,11 +64,12 @@ namespace Rice::detail
|
|
69
64
|
void operator=(const NativeFunction_T&) = delete;
|
70
65
|
void operator=(NativeFunction_T&&) = delete;
|
71
66
|
|
72
|
-
|
73
|
-
VALUE operator()(int argc, VALUE* argv, VALUE self);
|
67
|
+
Resolved matches(int argc, const VALUE* argv, VALUE self) override;
|
68
|
+
VALUE operator()(int argc, const VALUE* argv, VALUE self) override;
|
74
69
|
|
75
|
-
|
70
|
+
NativeFunction(Function_T function);
|
76
71
|
NativeFunction(VALUE klass, std::string method_name, Function_T function, MethodInfo* methodInfo);
|
72
|
+
protected:
|
77
73
|
|
78
74
|
private:
|
79
75
|
template<typename T, std::size_t I>
|
@@ -83,10 +79,14 @@ namespace Rice::detail
|
|
83
79
|
template<std::size_t...I>
|
84
80
|
From_Ruby_Args_Ts createFromRuby(std::index_sequence<I...>& indices);
|
85
81
|
|
86
|
-
|
82
|
+
// Convert C++ value to Ruby
|
83
|
+
To_Ruby<To_Ruby_T> createToRuby();
|
87
84
|
|
88
85
|
// Convert Ruby argv pointer to Ruby values
|
89
|
-
std::vector<VALUE> getRubyValues(int argc, VALUE* argv);
|
86
|
+
std::vector<VALUE> getRubyValues(int argc, const VALUE* argv, bool validate);
|
87
|
+
|
88
|
+
template<typename Arg_T, int I>
|
89
|
+
Arg_T getNativeValue(std::vector<VALUE>& values);
|
90
90
|
|
91
91
|
// Convert Ruby values to C++ values
|
92
92
|
template<typename std::size_t...I>
|
@@ -102,18 +102,17 @@ namespace Rice::detail
|
|
102
102
|
void checkKeepAlive(VALUE self, VALUE returnValue, std::vector<VALUE>& rubyValues);
|
103
103
|
|
104
104
|
// Call the underlying C++ function
|
105
|
-
VALUE invokeNativeFunction(
|
106
|
-
VALUE invokeNativeMethod(VALUE self,
|
105
|
+
VALUE invokeNativeFunction(Arg_Ts&& nativeArgs);
|
106
|
+
VALUE invokeNativeMethod(VALUE self, Arg_Ts&& nativeArgs);
|
107
107
|
|
108
108
|
private:
|
109
109
|
VALUE klass_;
|
110
110
|
std::string method_name_;
|
111
111
|
Function_T function_;
|
112
112
|
From_Ruby_Args_Ts fromRubys_;
|
113
|
-
To_Ruby<
|
113
|
+
To_Ruby<To_Ruby_T> toRuby_;
|
114
114
|
std::unique_ptr<MethodInfo> methodInfo_;
|
115
115
|
};
|
116
116
|
}
|
117
|
-
#include "NativeFunction.ipp"
|
118
117
|
|
119
118
|
#endif // Rice__detail__Native_Function__hpp_
|