rice2 2.2.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 +7 -0
- data/COPYING +23 -0
- data/Doxyfile +2268 -0
- data/Makefile.am +26 -0
- data/Makefile.in +929 -0
- data/README.md +1054 -0
- data/README.mingw +8 -0
- data/Rakefile +24 -0
- data/aclocal.m4 +1090 -0
- data/bootstrap +8 -0
- data/config.guess +1667 -0
- data/config.sub +1793 -0
- data/configure +8209 -0
- data/configure.ac +55 -0
- data/depcomp +791 -0
- data/doxygen.ac +314 -0
- data/doxygen.am +186 -0
- data/extconf.rb +66 -0
- data/install-sh +529 -0
- data/missing +215 -0
- data/post-autoconf.rb +22 -0
- data/post-automake.rb +28 -0
- data/rice/Address_Registration_Guard.cpp +22 -0
- data/rice/Address_Registration_Guard.hpp +7 -0
- data/rice/Address_Registration_Guard.ipp +37 -0
- data/rice/Address_Registration_Guard_defn.hpp +75 -0
- data/rice/Arg.hpp +8 -0
- data/rice/Arg_impl.hpp +129 -0
- data/rice/Arg_operators.cpp +21 -0
- data/rice/Arg_operators.hpp +19 -0
- data/rice/Array.hpp +214 -0
- data/rice/Array.ipp +256 -0
- data/rice/Builtin_Object.hpp +8 -0
- data/rice/Builtin_Object.ipp +50 -0
- data/rice/Builtin_Object_defn.hpp +50 -0
- data/rice/Class.cpp +57 -0
- data/rice/Class.hpp +8 -0
- data/rice/Class.ipp +6 -0
- data/rice/Class_defn.hpp +83 -0
- data/rice/Constructor.hpp +47 -0
- data/rice/Data_Object.hpp +8 -0
- data/rice/Data_Object.ipp +133 -0
- data/rice/Data_Object_defn.hpp +138 -0
- data/rice/Data_Type.cpp +54 -0
- data/rice/Data_Type.hpp +8 -0
- data/rice/Data_Type.ipp +365 -0
- data/rice/Data_Type_defn.hpp +261 -0
- data/rice/Data_Type_fwd.hpp +12 -0
- data/rice/Director.cpp +13 -0
- data/rice/Director.hpp +39 -0
- data/rice/Enum.hpp +117 -0
- data/rice/Enum.ipp +246 -0
- data/rice/Exception.cpp +59 -0
- data/rice/Exception.hpp +13 -0
- data/rice/Exception_Base.hpp +8 -0
- data/rice/Exception_Base.ipp +13 -0
- data/rice/Exception_Base_defn.hpp +27 -0
- data/rice/Exception_defn.hpp +69 -0
- data/rice/Hash.hpp +227 -0
- data/rice/Hash.ipp +329 -0
- data/rice/Identifier.cpp +8 -0
- data/rice/Identifier.hpp +50 -0
- data/rice/Identifier.ipp +33 -0
- data/rice/Jump_Tag.hpp +24 -0
- data/rice/Makefile.am +122 -0
- data/rice/Makefile.in +885 -0
- data/rice/Module.cpp +84 -0
- data/rice/Module.hpp +8 -0
- data/rice/Module.ipp +6 -0
- data/rice/Module_defn.hpp +88 -0
- data/rice/Module_impl.hpp +281 -0
- data/rice/Module_impl.ipp +345 -0
- data/rice/Object.cpp +169 -0
- data/rice/Object.hpp +8 -0
- data/rice/Object.ipp +33 -0
- data/rice/Object_defn.hpp +214 -0
- data/rice/Require_Guard.hpp +21 -0
- data/rice/String.cpp +94 -0
- data/rice/String.hpp +91 -0
- data/rice/Struct.cpp +117 -0
- data/rice/Struct.hpp +162 -0
- data/rice/Struct.ipp +26 -0
- data/rice/Symbol.cpp +25 -0
- data/rice/Symbol.hpp +66 -0
- data/rice/Symbol.ipp +44 -0
- data/rice/config.hpp +47 -0
- data/rice/config.hpp.in +46 -0
- data/rice/detail/Arguments.hpp +118 -0
- data/rice/detail/Auto_Function_Wrapper.hpp +898 -0
- data/rice/detail/Auto_Function_Wrapper.ipp +3694 -0
- data/rice/detail/Auto_Member_Function_Wrapper.hpp +897 -0
- data/rice/detail/Auto_Member_Function_Wrapper.ipp +2774 -0
- data/rice/detail/Caster.hpp +103 -0
- data/rice/detail/Exception_Handler.hpp +8 -0
- data/rice/detail/Exception_Handler.ipp +68 -0
- data/rice/detail/Exception_Handler_defn.hpp +96 -0
- data/rice/detail/Iterator.hpp +93 -0
- data/rice/detail/Not_Copyable.hpp +25 -0
- data/rice/detail/Wrapped_Function.hpp +33 -0
- data/rice/detail/cfp.hpp +24 -0
- data/rice/detail/cfp.ipp +51 -0
- data/rice/detail/check_ruby_type.cpp +27 -0
- data/rice/detail/check_ruby_type.hpp +23 -0
- data/rice/detail/creation_funcs.hpp +37 -0
- data/rice/detail/creation_funcs.ipp +36 -0
- data/rice/detail/default_allocation_func.hpp +23 -0
- data/rice/detail/default_allocation_func.ipp +11 -0
- data/rice/detail/define_method_and_auto_wrap.hpp +31 -0
- data/rice/detail/define_method_and_auto_wrap.ipp +30 -0
- data/rice/detail/demangle.cpp +56 -0
- data/rice/detail/demangle.hpp +19 -0
- data/rice/detail/env.hpp +11 -0
- data/rice/detail/from_ruby.hpp +43 -0
- data/rice/detail/from_ruby.ipp +60 -0
- data/rice/detail/method_data.cpp +92 -0
- data/rice/detail/method_data.hpp +21 -0
- data/rice/detail/node.hpp +13 -0
- data/rice/detail/protect.cpp +29 -0
- data/rice/detail/protect.hpp +34 -0
- data/rice/detail/ruby.hpp +74 -0
- data/rice/detail/ruby_version_code.hpp +6 -0
- data/rice/detail/ruby_version_code.hpp.in +6 -0
- data/rice/detail/st.hpp +22 -0
- data/rice/detail/to_ruby.hpp +22 -0
- data/rice/detail/to_ruby.ipp +36 -0
- data/rice/detail/traits.hpp +43 -0
- data/rice/detail/win32.hpp +16 -0
- data/rice/detail/wrap_function.hpp +66 -0
- data/rice/global_function.hpp +33 -0
- data/rice/global_function.ipp +22 -0
- data/rice/protect.hpp +38 -0
- data/rice/protect.ipp +1134 -0
- data/rice/ruby_mark.hpp +13 -0
- data/rice/ruby_try_catch.hpp +86 -0
- data/rice/rubypp.rb +97 -0
- data/rice/to_from_ruby.hpp +8 -0
- data/rice/to_from_ruby.ipp +418 -0
- data/rice/to_from_ruby_defn.hpp +70 -0
- data/ruby.ac +135 -0
- data/ruby/Makefile.am +1 -0
- data/ruby/Makefile.in +628 -0
- data/ruby/lib/Makefile.am +3 -0
- data/ruby/lib/Makefile.in +506 -0
- data/ruby/lib/mkmf-rice.rb.in +217 -0
- data/ruby/lib/version.rb +3 -0
- data/sample/Makefile.am +47 -0
- data/sample/Makefile.in +489 -0
- data/sample/enum/extconf.rb +3 -0
- data/sample/enum/sample_enum.cpp +54 -0
- data/sample/enum/test.rb +8 -0
- data/sample/inheritance/animals.cpp +98 -0
- data/sample/inheritance/extconf.rb +3 -0
- data/sample/inheritance/test.rb +7 -0
- data/sample/map/extconf.rb +3 -0
- data/sample/map/map.cpp +81 -0
- data/sample/map/test.rb +7 -0
- data/test/Makefile.am +72 -0
- data/test/Makefile.in +1213 -0
- data/test/ext/Makefile.am +41 -0
- data/test/ext/Makefile.in +483 -0
- data/test/ext/t1/Foo.hpp +10 -0
- data/test/ext/t1/extconf.rb +2 -0
- data/test/ext/t1/t1.cpp +15 -0
- data/test/ext/t2/extconf.rb +2 -0
- data/test/ext/t2/t2.cpp +11 -0
- data/test/test_Address_Registration_Guard.cpp +43 -0
- data/test/test_Array.cpp +248 -0
- data/test/test_Builtin_Object.cpp +71 -0
- data/test/test_Class.cpp +496 -0
- data/test/test_Constructor.cpp +128 -0
- data/test/test_Data_Object.cpp +275 -0
- data/test/test_Data_Type.cpp +348 -0
- data/test/test_Director.cpp +308 -0
- data/test/test_Enum.cpp +215 -0
- data/test/test_Exception.cpp +47 -0
- data/test/test_Hash.cpp +212 -0
- data/test/test_Identifier.cpp +70 -0
- data/test/test_Jump_Tag.cpp +17 -0
- data/test/test_Memory_Management.cpp +50 -0
- data/test/test_Module.cpp +497 -0
- data/test/test_Object.cpp +159 -0
- data/test/test_String.cpp +107 -0
- data/test/test_Struct.cpp +205 -0
- data/test/test_Symbol.cpp +63 -0
- data/test/test_To_From_Ruby.cpp +428 -0
- data/test/test_global_functions.cpp +114 -0
- data/test/test_rice.rb +41 -0
- data/test/unittest.cpp +136 -0
- data/test/unittest.hpp +294 -0
- metadata +297 -0
@@ -0,0 +1,138 @@
|
|
1
|
+
#ifndef Rice__Data_Object_defn__hpp_
|
2
|
+
#define Rice__Data_Object_defn__hpp_
|
3
|
+
|
4
|
+
#include "Object_defn.hpp"
|
5
|
+
#include "Data_Type_fwd.hpp"
|
6
|
+
#include "ruby_mark.hpp"
|
7
|
+
#include "detail/to_ruby.hpp"
|
8
|
+
#include "detail/ruby.hpp"
|
9
|
+
|
10
|
+
/*! \file
|
11
|
+
* \brief Provides a helper class for wrapping and unwrapping C++
|
12
|
+
* objects as Ruby objects.
|
13
|
+
*/
|
14
|
+
|
15
|
+
namespace Rice
|
16
|
+
{
|
17
|
+
|
18
|
+
template<typename T>
|
19
|
+
struct Default_Mark_Function
|
20
|
+
{
|
21
|
+
typedef void (*Ruby_Data_Func)(T * obj);
|
22
|
+
static const Ruby_Data_Func mark;
|
23
|
+
};
|
24
|
+
|
25
|
+
template<typename T>
|
26
|
+
struct Default_Free_Function
|
27
|
+
{
|
28
|
+
static void free(T * obj) { delete obj; }
|
29
|
+
};
|
30
|
+
|
31
|
+
|
32
|
+
//! A smartpointer-like wrapper for Ruby data objects.
|
33
|
+
/*! A data object is a ruby object of type T_DATA, which is usually
|
34
|
+
* created by using the Data_Wrap_Struct or Data_Make_Struct macro.
|
35
|
+
* This class wraps creation of the data structure, providing a
|
36
|
+
* type-safe object-oriented interface to the underlying C interface.
|
37
|
+
* This class works in conjunction with the Data_Type class to ensure
|
38
|
+
* type safety.
|
39
|
+
*
|
40
|
+
* Example:
|
41
|
+
* \code
|
42
|
+
* class Foo { };
|
43
|
+
* ...
|
44
|
+
* Data_Type<Foo> rb_cFoo = define_class("Foo");
|
45
|
+
* ...
|
46
|
+
* // Wrap:
|
47
|
+
* Data_Object<Foo> foo1(new Foo);
|
48
|
+
*
|
49
|
+
* // Get value to return:
|
50
|
+
* VALUE v = foo1.value()
|
51
|
+
*
|
52
|
+
* // Unwrap:
|
53
|
+
* Data_Object<Foo> foo2(v, rb_cFoo);
|
54
|
+
* \endcode
|
55
|
+
*/
|
56
|
+
template<typename T>
|
57
|
+
class Data_Object
|
58
|
+
: public Object
|
59
|
+
{
|
60
|
+
public:
|
61
|
+
//! A function that takes a T* and returns void.
|
62
|
+
typedef void (*Ruby_Data_Func)(T * obj);
|
63
|
+
|
64
|
+
//! Wrap a C++ object.
|
65
|
+
/*! This constructor is analogous to calling Data_Wrap_Struct. Be
|
66
|
+
* careful not to call this function more than once for the same
|
67
|
+
* pointer (in general, it should only be called for newly
|
68
|
+
* constructed objects that need to be managed by Ruby's garbage
|
69
|
+
* collector).
|
70
|
+
* \param obj the object to wrap.
|
71
|
+
* \param klass the Ruby class to use for the newly created Ruby
|
72
|
+
* object.
|
73
|
+
* \param mark_func a function that gets called by the garbage
|
74
|
+
* collector to mark the object's children.
|
75
|
+
* \param free_func a function that gets called by the garbage
|
76
|
+
* collector to free the object.
|
77
|
+
*/
|
78
|
+
Data_Object(
|
79
|
+
T * obj,
|
80
|
+
VALUE klass = Data_Type<T>::klass(),
|
81
|
+
Ruby_Data_Func mark_func = Default_Mark_Function<T>::mark,
|
82
|
+
Ruby_Data_Func free_func = Default_Free_Function<T>::free);
|
83
|
+
|
84
|
+
//! Unwrap a Ruby object.
|
85
|
+
/*! This constructor is analogous to calling Data_Get_Struct. Uses
|
86
|
+
* Data_Type<T>::klass as the class of the object.
|
87
|
+
* \param value the Ruby object to unwrap.
|
88
|
+
*/
|
89
|
+
Data_Object(
|
90
|
+
Object value);
|
91
|
+
|
92
|
+
//! Unwrap a Ruby object.
|
93
|
+
/*! This constructor is analogous to calling Data_Get_Struct. Will
|
94
|
+
* throw an exception if the class of the object differs from the
|
95
|
+
* specified class.
|
96
|
+
* \param value the Ruby object to unwrap.
|
97
|
+
* \param klass the expected class of the object.
|
98
|
+
*/
|
99
|
+
template<typename U>
|
100
|
+
Data_Object(
|
101
|
+
Object value,
|
102
|
+
Data_Type<U> const & klass = Data_Type<T>::klass());
|
103
|
+
|
104
|
+
//! Make a copy of a Data_Object
|
105
|
+
/*! \param other the Data_Object to copy.
|
106
|
+
*/
|
107
|
+
Data_Object(Data_Object const & other);
|
108
|
+
|
109
|
+
T & operator*() const { return *obj_; } //!< Return a reference to obj_
|
110
|
+
T * operator->() const { return obj_; } //!< Return a pointer to obj_
|
111
|
+
T * get() const { return obj_; } //!< Return a pointer to obj_
|
112
|
+
|
113
|
+
//! Swap with another data object of the same type
|
114
|
+
/*! \param ref the object with which to swap.
|
115
|
+
*/
|
116
|
+
template<typename U>
|
117
|
+
void swap(Data_Object<U> & ref);
|
118
|
+
|
119
|
+
private:
|
120
|
+
static void check_cpp_type(Data_Type<T> const & klass);
|
121
|
+
|
122
|
+
private:
|
123
|
+
T * obj_;
|
124
|
+
};
|
125
|
+
|
126
|
+
namespace detail
|
127
|
+
{
|
128
|
+
template<typename T>
|
129
|
+
struct to_ruby_<Data_Object<T> >
|
130
|
+
{
|
131
|
+
static Rice::Object convert(Data_Object<T> const & x);
|
132
|
+
};
|
133
|
+
}
|
134
|
+
|
135
|
+
} // namespace Rice
|
136
|
+
|
137
|
+
#endif // Rice__Data_Object_defn__hpp_
|
138
|
+
|
data/rice/Data_Type.cpp
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
#include "Data_Type.hpp"
|
2
|
+
|
3
|
+
Rice::Data_Type_Base::Casters * Rice::Data_Type_Base::casters_ = 0;
|
4
|
+
|
5
|
+
Rice::Data_Type_Base::
|
6
|
+
Data_Type_Base()
|
7
|
+
: Module_impl<Class, Data_Type_Base>()
|
8
|
+
{
|
9
|
+
}
|
10
|
+
|
11
|
+
Rice::Data_Type_Base::
|
12
|
+
Data_Type_Base(VALUE v)
|
13
|
+
: Module_impl<Class, Data_Type_Base>(v)
|
14
|
+
{
|
15
|
+
}
|
16
|
+
|
17
|
+
Rice::Data_Type_Base::
|
18
|
+
~Data_Type_Base()
|
19
|
+
{
|
20
|
+
}
|
21
|
+
|
22
|
+
Rice::Data_Type_Base::Casters &
|
23
|
+
Rice::Data_Type_Base::
|
24
|
+
casters()
|
25
|
+
{
|
26
|
+
// Initialize the casters_ if it is null
|
27
|
+
if (!casters_)
|
28
|
+
{
|
29
|
+
// First, see if it has been previously registered with the
|
30
|
+
// interpreter (possibly by another extension)
|
31
|
+
Class object(rb_cObject);
|
32
|
+
Object casters_object(object.attr_get("__rice_casters__"));
|
33
|
+
|
34
|
+
if (casters_object.is_nil())
|
35
|
+
{
|
36
|
+
// If it is unset, then set it for the first time
|
37
|
+
Data_Object<Casters> casters(
|
38
|
+
new Casters,
|
39
|
+
rb_cObject);
|
40
|
+
object.iv_set("__rice_casters__", casters);
|
41
|
+
casters_ = casters.get();
|
42
|
+
}
|
43
|
+
else
|
44
|
+
{
|
45
|
+
// If it is set, then use the existing value
|
46
|
+
Data_Object<Casters> casters(
|
47
|
+
casters_object);
|
48
|
+
casters_ = casters.get();
|
49
|
+
}
|
50
|
+
}
|
51
|
+
|
52
|
+
return *casters_;
|
53
|
+
}
|
54
|
+
|
data/rice/Data_Type.hpp
ADDED
data/rice/Data_Type.ipp
ADDED
@@ -0,0 +1,365 @@
|
|
1
|
+
#ifndef Rice__Data_Type__ipp_
|
2
|
+
#define Rice__Data_Type__ipp_
|
3
|
+
|
4
|
+
#include "Class.hpp"
|
5
|
+
#include "String.hpp"
|
6
|
+
#include "Data_Object.hpp"
|
7
|
+
#include "detail/default_allocation_func.hpp"
|
8
|
+
#include "detail/creation_funcs.hpp"
|
9
|
+
#include "detail/method_data.hpp"
|
10
|
+
#include "detail/Caster.hpp"
|
11
|
+
#include "detail/demangle.hpp"
|
12
|
+
|
13
|
+
#include <stdexcept>
|
14
|
+
#include <typeinfo>
|
15
|
+
|
16
|
+
template<typename T>
|
17
|
+
VALUE Rice::Data_Type<T>::klass_ = Qnil;
|
18
|
+
|
19
|
+
template<typename T>
|
20
|
+
std_unique_ptr<Rice::detail::Abstract_Caster> Rice::Data_Type<T>::caster_;
|
21
|
+
|
22
|
+
template<typename T>
|
23
|
+
template<typename Base_T>
|
24
|
+
inline Rice::Data_Type<T> Rice::Data_Type<T>::
|
25
|
+
bind(Module const & klass)
|
26
|
+
{
|
27
|
+
if(klass.value() == klass_)
|
28
|
+
{
|
29
|
+
return Data_Type<T>();
|
30
|
+
}
|
31
|
+
|
32
|
+
if(is_bound())
|
33
|
+
{
|
34
|
+
std::string s;
|
35
|
+
s = "Data type ";
|
36
|
+
s += detail::demangle(typeid(T).name());
|
37
|
+
s += " is already bound to a different type";
|
38
|
+
throw std::runtime_error(s.c_str());
|
39
|
+
}
|
40
|
+
|
41
|
+
// TODO: Make sure base type is bound; throw an exception otherwise.
|
42
|
+
// We can't do this just yet, because we don't have a specialization
|
43
|
+
// for binding to void.
|
44
|
+
klass_ = klass;
|
45
|
+
|
46
|
+
// TODO: do we need to unregister when the program exits? we have to
|
47
|
+
// be careful if we do, because the ruby interpreter might have
|
48
|
+
// already shut down. The correct behavior is probably to register an
|
49
|
+
// exit proc with the interpreter, so the proc gets called before the
|
50
|
+
// GC shuts down.
|
51
|
+
rb_gc_register_address(&klass_);
|
52
|
+
|
53
|
+
for(typename Instances::iterator it = unbound_instances().begin(),
|
54
|
+
end = unbound_instances().end();
|
55
|
+
it != end;
|
56
|
+
unbound_instances().erase(it++))
|
57
|
+
{
|
58
|
+
(*it)->set_value(klass);
|
59
|
+
}
|
60
|
+
|
61
|
+
detail::Abstract_Caster * base_caster = Data_Type<Base_T>().caster();
|
62
|
+
caster_.reset(new detail::Caster<T, Base_T>(base_caster, klass));
|
63
|
+
Data_Type_Base::casters().insert(std::make_pair(klass, caster_.get()));
|
64
|
+
return Data_Type<T>();
|
65
|
+
}
|
66
|
+
|
67
|
+
template<typename T>
|
68
|
+
inline Rice::Data_Type<T>::
|
69
|
+
Data_Type()
|
70
|
+
: Module_impl<Data_Type_Base, Data_Type<T> >(
|
71
|
+
klass_ == Qnil ? rb_cObject : klass_)
|
72
|
+
{
|
73
|
+
if(!is_bound())
|
74
|
+
{
|
75
|
+
unbound_instances().insert(this);
|
76
|
+
}
|
77
|
+
}
|
78
|
+
|
79
|
+
template<typename T>
|
80
|
+
inline Rice::Data_Type<T>::
|
81
|
+
Data_Type(Module const & klass)
|
82
|
+
: Module_impl<Data_Type_Base, Data_Type<T> >(
|
83
|
+
klass)
|
84
|
+
{
|
85
|
+
this->bind<void>(klass);
|
86
|
+
}
|
87
|
+
|
88
|
+
template<typename T>
|
89
|
+
inline Rice::Data_Type<T>::
|
90
|
+
~Data_Type()
|
91
|
+
{
|
92
|
+
unbound_instances().erase(this);
|
93
|
+
}
|
94
|
+
|
95
|
+
template<typename T>
|
96
|
+
Rice::Module
|
97
|
+
Rice::Data_Type<T>::
|
98
|
+
klass() {
|
99
|
+
if(is_bound())
|
100
|
+
{
|
101
|
+
return klass_;
|
102
|
+
}
|
103
|
+
else
|
104
|
+
{
|
105
|
+
std::string s;
|
106
|
+
s += detail::demangle(typeid(T *).name());
|
107
|
+
s += " is unbound";
|
108
|
+
throw std::runtime_error(s.c_str());
|
109
|
+
}
|
110
|
+
}
|
111
|
+
|
112
|
+
template<typename T>
|
113
|
+
Rice::Data_Type<T> & Rice::Data_Type<T>::
|
114
|
+
operator=(Module const & klass)
|
115
|
+
{
|
116
|
+
this->bind<void>(klass);
|
117
|
+
return *this;
|
118
|
+
}
|
119
|
+
|
120
|
+
template<typename T>
|
121
|
+
template<typename Constructor_T>
|
122
|
+
inline Rice::Data_Type<T> & Rice::Data_Type<T>::
|
123
|
+
define_constructor(
|
124
|
+
Constructor_T /* constructor */,
|
125
|
+
Arguments* arguments)
|
126
|
+
{
|
127
|
+
check_is_bound();
|
128
|
+
|
129
|
+
// Normal constructor pattern with new/initialize
|
130
|
+
rb_define_alloc_func(
|
131
|
+
static_cast<VALUE>(*this),
|
132
|
+
detail::default_allocation_func<T>);
|
133
|
+
this->define_method(
|
134
|
+
"initialize",
|
135
|
+
&Constructor_T::construct,
|
136
|
+
arguments
|
137
|
+
);
|
138
|
+
|
139
|
+
return *this;
|
140
|
+
}
|
141
|
+
|
142
|
+
template<typename T>
|
143
|
+
template<typename Constructor_T>
|
144
|
+
inline Rice::Data_Type<T> & Rice::Data_Type<T>::
|
145
|
+
define_constructor(
|
146
|
+
Constructor_T constructor,
|
147
|
+
Arg const& arg)
|
148
|
+
{
|
149
|
+
Arguments* args = new Arguments();
|
150
|
+
args->add(arg);
|
151
|
+
return define_constructor(constructor, args);
|
152
|
+
}
|
153
|
+
|
154
|
+
|
155
|
+
template<typename T>
|
156
|
+
template<typename Director_T>
|
157
|
+
inline Rice::Data_Type<T>& Rice::Data_Type<T>::
|
158
|
+
define_director()
|
159
|
+
{
|
160
|
+
Rice::Data_Type<Director_T>::template bind<T>(*this);
|
161
|
+
return *this;
|
162
|
+
}
|
163
|
+
|
164
|
+
template<typename T>
|
165
|
+
inline T * Rice::Data_Type<T>::
|
166
|
+
from_ruby(Object x)
|
167
|
+
{
|
168
|
+
check_is_bound();
|
169
|
+
|
170
|
+
void * v = DATA_PTR(x.value());
|
171
|
+
Class klass = x.class_of();
|
172
|
+
|
173
|
+
if(klass.value() == klass_)
|
174
|
+
{
|
175
|
+
// Great, not converting to a base/derived type
|
176
|
+
Data_Type<T> data_klass;
|
177
|
+
Data_Object<T> obj(x, data_klass);
|
178
|
+
return obj.get();
|
179
|
+
}
|
180
|
+
|
181
|
+
Data_Type_Base::Casters::const_iterator it = Data_Type_Base::casters().begin();
|
182
|
+
Data_Type_Base::Casters::const_iterator end = Data_Type_Base::casters().end();
|
183
|
+
|
184
|
+
// Finding the bound type that relates to the given klass is
|
185
|
+
// a two step process. We iterate over the list of known type casters,
|
186
|
+
// looking for:
|
187
|
+
//
|
188
|
+
// 1) casters that handle this direct type
|
189
|
+
// 2) casters that handle types that are ancestors of klass
|
190
|
+
//
|
191
|
+
// Step 2 allows us to handle the case where a Rice-wrapped class
|
192
|
+
// is subclassed in Ruby but then an instance of that class is passed
|
193
|
+
// back into C++ (say, in a Listener / callback construction)
|
194
|
+
//
|
195
|
+
|
196
|
+
VALUE ancestors = rb_mod_ancestors(klass.value());
|
197
|
+
|
198
|
+
long earliest = RARRAY_LEN(ancestors) + 1;
|
199
|
+
|
200
|
+
int index;
|
201
|
+
VALUE indexFound;
|
202
|
+
Data_Type_Base::Casters::const_iterator toUse = end;
|
203
|
+
|
204
|
+
for(; it != end; it++) {
|
205
|
+
// Do we match directly?
|
206
|
+
if(klass.value() == it->first) {
|
207
|
+
toUse = it;
|
208
|
+
break;
|
209
|
+
}
|
210
|
+
|
211
|
+
// Check for ancestors. Trick is, we need to find the lowest
|
212
|
+
// ancestor that does have a Caster to make sure that we're casting
|
213
|
+
// to the closest C++ type that the Ruby class is subclassing.
|
214
|
+
// There might be multiple ancestors that are also wrapped in
|
215
|
+
// the extension, so find the earliest in the list and use that one.
|
216
|
+
indexFound = rb_funcall(ancestors, rb_intern("index"), 1, it->first);
|
217
|
+
|
218
|
+
if(indexFound != Qnil) {
|
219
|
+
index = NUM2INT(indexFound);
|
220
|
+
|
221
|
+
if(index < earliest) {
|
222
|
+
earliest = index;
|
223
|
+
toUse = it;
|
224
|
+
}
|
225
|
+
}
|
226
|
+
}
|
227
|
+
|
228
|
+
if(toUse == end)
|
229
|
+
{
|
230
|
+
std::string s = "Class ";
|
231
|
+
s += klass.name().str();
|
232
|
+
s += " is not registered/bound in Rice";
|
233
|
+
throw std::runtime_error(s);
|
234
|
+
}
|
235
|
+
|
236
|
+
detail::Abstract_Caster * caster = toUse->second;
|
237
|
+
if(caster)
|
238
|
+
{
|
239
|
+
T * result = static_cast<T *>(caster->cast_to_base(v, klass_));
|
240
|
+
return result;
|
241
|
+
}
|
242
|
+
else
|
243
|
+
{
|
244
|
+
return static_cast<T *>(v);
|
245
|
+
}
|
246
|
+
}
|
247
|
+
|
248
|
+
template<typename T>
|
249
|
+
inline bool Rice::Data_Type<T>::
|
250
|
+
is_bound()
|
251
|
+
{
|
252
|
+
return klass_ != Qnil;
|
253
|
+
}
|
254
|
+
|
255
|
+
template<typename T>
|
256
|
+
inline Rice::detail::Abstract_Caster * Rice::Data_Type<T>::
|
257
|
+
caster() const
|
258
|
+
{
|
259
|
+
check_is_bound();
|
260
|
+
return caster_.get();
|
261
|
+
}
|
262
|
+
|
263
|
+
namespace Rice
|
264
|
+
{
|
265
|
+
|
266
|
+
template<>
|
267
|
+
inline detail::Abstract_Caster * Data_Type<void>::
|
268
|
+
caster() const
|
269
|
+
{
|
270
|
+
return 0;
|
271
|
+
}
|
272
|
+
|
273
|
+
template<typename T>
|
274
|
+
void Data_Type<T>::
|
275
|
+
check_is_bound()
|
276
|
+
{
|
277
|
+
if(!is_bound())
|
278
|
+
{
|
279
|
+
std::string s;
|
280
|
+
s = "Data type ";
|
281
|
+
s += detail::demangle(typeid(T).name());
|
282
|
+
s += " is not bound";
|
283
|
+
throw std::runtime_error(s.c_str());
|
284
|
+
}
|
285
|
+
}
|
286
|
+
|
287
|
+
} // Rice
|
288
|
+
|
289
|
+
template<typename T>
|
290
|
+
inline Rice::Data_Type<T> Rice::
|
291
|
+
define_class_under(
|
292
|
+
Object module,
|
293
|
+
char const * name)
|
294
|
+
{
|
295
|
+
Class c(define_class_under(module, name, rb_cObject));
|
296
|
+
c.undef_creation_funcs();
|
297
|
+
return Data_Type<T>::template bind<void>(c);
|
298
|
+
}
|
299
|
+
|
300
|
+
template<typename T, typename Base_T>
|
301
|
+
inline Rice::Data_Type<T> Rice::
|
302
|
+
define_class_under(
|
303
|
+
Object module,
|
304
|
+
char const * name)
|
305
|
+
{
|
306
|
+
Data_Type<Base_T> base_dt;
|
307
|
+
Class c(define_class_under(module, name, base_dt));
|
308
|
+
c.undef_creation_funcs();
|
309
|
+
return Data_Type<T>::template bind<Base_T>(c);
|
310
|
+
}
|
311
|
+
|
312
|
+
template<typename T>
|
313
|
+
inline Rice::Data_Type<T> Rice::
|
314
|
+
define_class(
|
315
|
+
char const * name)
|
316
|
+
{
|
317
|
+
Class c(define_class(name, rb_cObject));
|
318
|
+
c.undef_creation_funcs();
|
319
|
+
return Data_Type<T>::template bind<void>(c);
|
320
|
+
}
|
321
|
+
|
322
|
+
template<typename T, typename Base_T>
|
323
|
+
inline Rice::Data_Type<T> Rice::
|
324
|
+
define_class(
|
325
|
+
char const * name)
|
326
|
+
{
|
327
|
+
Data_Type<Base_T> base_dt;
|
328
|
+
Class c(define_class(name, base_dt));
|
329
|
+
c.undef_creation_funcs();
|
330
|
+
return Data_Type<T>::template bind<Base_T>(c);
|
331
|
+
}
|
332
|
+
|
333
|
+
template<typename From_T, typename To_T>
|
334
|
+
inline void
|
335
|
+
Rice::define_implicit_cast()
|
336
|
+
{
|
337
|
+
// As Rice currently expects only one entry into
|
338
|
+
// this list for a given klass VALUE, we need to get
|
339
|
+
// the current caster for From_T and insert in our
|
340
|
+
// new caster as the head of the caster list
|
341
|
+
|
342
|
+
Class from_class = Data_Type<From_T>::klass().value();
|
343
|
+
Class to_class = Data_Type<To_T>::klass().value();
|
344
|
+
|
345
|
+
detail::Abstract_Caster* from_caster =
|
346
|
+
Data_Type<From_T>::caster_.release();
|
347
|
+
|
348
|
+
detail::Abstract_Caster* new_caster =
|
349
|
+
new detail::Implicit_Caster<To_T, From_T>(from_caster, to_class);
|
350
|
+
|
351
|
+
// Insert our new caster into the list for the from class
|
352
|
+
Data_Type_Base::casters().erase(from_class);
|
353
|
+
Data_Type_Base::casters().insert(
|
354
|
+
std::make_pair(
|
355
|
+
from_class,
|
356
|
+
new_caster
|
357
|
+
)
|
358
|
+
);
|
359
|
+
|
360
|
+
// And make sure the from_class has direct access to the
|
361
|
+
// updated caster list
|
362
|
+
Data_Type<From_T>::caster_.reset(new_caster);
|
363
|
+
}
|
364
|
+
|
365
|
+
#endif // Rice__Data_Type__ipp_
|