gecoder 0.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.
Files changed (75) hide show
  1. data/COPYING +17 -0
  2. data/LGPL-LICENSE +458 -0
  3. data/README +20 -0
  4. data/Rakefile +6 -0
  5. data/ext/extconf.rb +29 -0
  6. data/ext/missing.cpp +295 -0
  7. data/ext/missing.h +116 -0
  8. data/ext/vararray.cpp +312 -0
  9. data/ext/vararray.h +146 -0
  10. data/lib/gecoder.rb +4 -0
  11. data/lib/gecoder/bindings.rb +7 -0
  12. data/lib/gecoder/bindings/bindings.rb +2055 -0
  13. data/lib/gecoder/interface.rb +6 -0
  14. data/lib/gecoder/interface/binding_changes.rb +111 -0
  15. data/lib/gecoder/interface/branch.rb +102 -0
  16. data/lib/gecoder/interface/constraints.rb +10 -0
  17. data/lib/gecoder/interface/constraints/distinct.rb +15 -0
  18. data/lib/gecoder/interface/constraints/linear.rb +158 -0
  19. data/lib/gecoder/interface/constraints/relation.rb +76 -0
  20. data/lib/gecoder/interface/enum_wrapper.rb +64 -0
  21. data/lib/gecoder/interface/model.rb +130 -0
  22. data/lib/gecoder/interface/search.rb +23 -0
  23. data/vendor/rust/README +28 -0
  24. data/vendor/rust/bin/cxxgenerator.rb +93 -0
  25. data/vendor/rust/include/rust_checks.hh +115 -0
  26. data/vendor/rust/include/rust_conversions.hh +103 -0
  27. data/vendor/rust/rust.rb +67 -0
  28. data/vendor/rust/rust/attribute.rb +51 -0
  29. data/vendor/rust/rust/bindings.rb +172 -0
  30. data/vendor/rust/rust/class.rb +334 -0
  31. data/vendor/rust/rust/constants.rb +48 -0
  32. data/vendor/rust/rust/container.rb +110 -0
  33. data/vendor/rust/rust/cppifaceparser.rb +129 -0
  34. data/vendor/rust/rust/cwrapper.rb +72 -0
  35. data/vendor/rust/rust/cxxclass.rb +98 -0
  36. data/vendor/rust/rust/element.rb +81 -0
  37. data/vendor/rust/rust/enum.rb +63 -0
  38. data/vendor/rust/rust/function.rb +407 -0
  39. data/vendor/rust/rust/namespace.rb +61 -0
  40. data/vendor/rust/rust/templates/AttributeDefinition.rusttpl +17 -0
  41. data/vendor/rust/rust/templates/AttributeInitBinding.rusttpl +9 -0
  42. data/vendor/rust/rust/templates/BindingsHeader.rusttpl +24 -0
  43. data/vendor/rust/rust/templates/BindingsUnit.rusttpl +46 -0
  44. data/vendor/rust/rust/templates/CWrapperClassDefinitions.rusttpl +64 -0
  45. data/vendor/rust/rust/templates/ClassDeclarations.rusttpl +7 -0
  46. data/vendor/rust/rust/templates/ClassInitialize.rusttpl +6 -0
  47. data/vendor/rust/rust/templates/ConstructorStub.rusttpl +21 -0
  48. data/vendor/rust/rust/templates/CxxClassDefinitions.rusttpl +91 -0
  49. data/vendor/rust/rust/templates/CxxMethodStub.rusttpl +12 -0
  50. data/vendor/rust/rust/templates/CxxStandaloneClassDefinitions.rusttpl +12 -0
  51. data/vendor/rust/rust/templates/EnumDeclarations.rusttpl +3 -0
  52. data/vendor/rust/rust/templates/EnumDefinitions.rusttpl +29 -0
  53. data/vendor/rust/rust/templates/FunctionDefinition.rusttpl +9 -0
  54. data/vendor/rust/rust/templates/FunctionInitAlias.rusttpl +5 -0
  55. data/vendor/rust/rust/templates/FunctionInitBinding.rusttpl +9 -0
  56. data/vendor/rust/rust/templates/MethodInitBinding.rusttpl +9 -0
  57. data/vendor/rust/rust/templates/ModuleDeclarations.rusttpl +3 -0
  58. data/vendor/rust/rust/templates/ModuleDefinitions.rusttpl +3 -0
  59. data/vendor/rust/rust/templates/StandaloneClassDeclarations.rusttpl +5 -0
  60. data/vendor/rust/rust/templates/VariableFunctionCall.rusttpl +14 -0
  61. data/vendor/rust/rust/type.rb +98 -0
  62. data/vendor/rust/test/Makefile +4 -0
  63. data/vendor/rust/test/constants.rb +35 -0
  64. data/vendor/rust/test/cppclass.cc +40 -0
  65. data/vendor/rust/test/cppclass.hh +63 -0
  66. data/vendor/rust/test/cppclass.rb +59 -0
  67. data/vendor/rust/test/cwrapper.c +74 -0
  68. data/vendor/rust/test/cwrapper.h +41 -0
  69. data/vendor/rust/test/cwrapper.rb +56 -0
  70. data/vendor/rust/test/dummyclass.hh +31 -0
  71. data/vendor/rust/test/lib/extension-test.rb +98 -0
  72. data/vendor/rust/test/test-constants.rb +43 -0
  73. data/vendor/rust/test/test-cppclass.rb +82 -0
  74. data/vendor/rust/test/test-cwrapper.rb +77 -0
  75. metadata +144 -0
@@ -0,0 +1,103 @@
1
+ /* Copyright (c) 2005-2007 Diego Pettenò <flameeyes@gmail.com>
2
+ *
3
+ * Permission is hereby granted, free of charge, to any person obtaining
4
+ * a copy of this software and associated documentation files (the
5
+ * "Software"), to deal in the Software without restriction, including
6
+ * without limitation the rights to use, copy, modify, merge,
7
+ * publish, distribute, sublicense, and/or sell copies of the Software,
8
+ * and to permit persons to whom the Software is furnished to do so,
9
+ * subject to the following conditions:
10
+ *
11
+ * The above copyright notice and this permission notice shall be
12
+ * included in all copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
18
+ * BE LIABLE
19
+ * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
20
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ */
23
+
24
+ #ifndef __RUST_CONVERSIONS__
25
+ #define __RUST_CONVERSIONS__
26
+
27
+ #include <stdint.h>
28
+ #include <ruby.h>
29
+
30
+ /* Standard conversions for integer values */
31
+
32
+ static inline uint32_t ruby2uint(VALUE rval, int argn = -1) {
33
+ return NUM2UINT(rval);
34
+ }
35
+
36
+ static inline int32_t ruby2int(VALUE rval, int argn = -1) {
37
+ return NUM2INT(rval);
38
+ }
39
+
40
+ static inline VALUE cxx2ruby(int32_t val) {
41
+ return INT2FIX(val);
42
+ }
43
+
44
+ static inline VALUE cxx2ruby(uint32_t val) {
45
+ return INT2FIX(val);
46
+ }
47
+
48
+ static inline VALUE cxx2ruby(double val) {
49
+ return rb_float_new(val);
50
+ }
51
+
52
+ /* Standard conversions for stdint-provided types */
53
+ /* TODO: replace these with something more comples but that properly
54
+ handle a try to convert a number too big to stay into the size
55
+ requested.
56
+ */
57
+ #define ruby2uint32_t ruby2uint
58
+ #define ruby2uint16_t ruby2uint
59
+ #define ruby2uint8_t ruby2uint
60
+
61
+ #define ruby2int32_t ruby2int
62
+ #define ruby2int16_t ruby2int
63
+ #define ruby2int8_t ruby2int
64
+
65
+ /* Conversion for common types (like strings */
66
+
67
+ static inline int *ruby2intArray(VALUE rval, int argn = -1) {
68
+ int i;
69
+ RArray *array = RARRAY(rval);
70
+ // int *ret = new int(array->len);
71
+ int ret[array->len];
72
+ for(i = 0; i < array->len; i++)
73
+ {
74
+ ret[i] = NUM2INT(array->ptr[i]);
75
+ }
76
+ return ret;
77
+ }
78
+
79
+ static inline char *ruby2charPtr(VALUE rval, int argn = -1) {
80
+ Check_Type(rval, T_STRING);
81
+ return StringValuePtr(rval);
82
+ }
83
+
84
+ static inline VALUE cxx2ruby(const char *val) {
85
+ if ( ! val ) return Qnil;
86
+ return rb_str_new2(val);
87
+ }
88
+
89
+ static inline VALUE cxx2ruby(const std::string &str) {
90
+ return rb_str_new2(str.c_str());
91
+ }
92
+
93
+ /* Booleans conversion */
94
+
95
+ static inline VALUE cxx2ruby(bool val) {
96
+ return val ? Qtrue : Qfalse;
97
+ }
98
+
99
+ static inline bool ruby2bool(VALUE rval, int argn = -1) {
100
+ return !( rval == Qnil || rval == Qfalse );
101
+ }
102
+
103
+ #endif
@@ -0,0 +1,67 @@
1
+ # Copyright (c) 2005-2007 Diego Pettenò <flameeyes@gmail.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining
4
+ # a copy of this software and associated documentation files (the
5
+ # "Software"), to deal in the Software without restriction, including
6
+ # without limitation the rights to use, copy, modify, merge,
7
+ # publish, distribute, sublicense, and/or sell copies of the Software,
8
+ # and to permit persons to whom the Software is furnished to do so,
9
+ # subject to the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be
12
+ # included in all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
18
+ # BE LIABLE
19
+ # FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
20
+ # CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+
23
+ require 'pathname'
24
+
25
+ # Rust is a Ruby bindings generator, developed by Diego Pettenò
26
+ # <flameeyes@gmail.com>, based on a simpler Ruby bindings generator
27
+ # that was used for RubyTag++ and ruby-hunspell.
28
+ #
29
+ # The original bindings generator was designed to permit a 1:1 mapping
30
+ # between C++ classes and Ruby classes, as otherwise writing Ruby
31
+ # bindings for a C++-based library would have consisted of a long
32
+ # series of generic functions to convert the types from one language
33
+ # to the other and to call the methods.
34
+ #
35
+ # Most C bindings, instead, either writes a lot of C code to create
36
+ # "fake" Classes out of a vaguely object-oriented C API, or simply
37
+ # create a module where to put all the C functions to call.
38
+ #
39
+ # The objective of Rust is to allow the description of a C or C++
40
+ # interface, through the creation of 1:1 class mappings or the design
41
+ # of "fake" classes out of C functions, without the need to actually
42
+ # write all the generic code, as that does not really change beside
43
+ # names, types and parameters.
44
+ module Rust
45
+
46
+ # The Template singleton class is used to simulate a big hash of
47
+ # templates, loaded with the data from the templates/ subdirectory.
48
+ # In truth the templates are loaded only when requested, removing
49
+ # the one-line comments found inside the files (as they are usually
50
+ # just for documenting that particular template).
51
+ class Templates
52
+ @cache = { }
53
+ @tpls_dir = (Pathname.new File.dirname(__FILE__)) + "rust/templates"
54
+
55
+ def Templates.[](name)
56
+ return @cache[name].dup if @cache[name]
57
+
58
+ pn = @tpls_dir + "#{name}.rusttpl"
59
+ raise "Template #{name} not found." unless pn.exist?
60
+
61
+ @cache[name] = pn.read.gsub(/\/\/.*$\n?/, '')
62
+ return @cache[name].dup
63
+ end
64
+ end
65
+ end
66
+
67
+ require 'rust/bindings'
@@ -0,0 +1,51 @@
1
+ # Copyright (c) 2007 David Cuadrado <krawek@gmail.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining
4
+ # a copy of this software and associated documentation files (the
5
+ # "Software"), to deal in the Software without restriction, including
6
+ # without limitation the rights to use, copy, modify, merge,
7
+ # publish, distribute, sublicense, and/or sell copies of the Software,
8
+ # and to permit persons to whom the Software is furnished to do so,
9
+ # subject to the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be
12
+ # included in all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
18
+ # BE LIABLE
19
+ # FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
20
+ # CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+
23
+ require 'set'
24
+ require 'rust/element'
25
+ require 'rust/type'
26
+
27
+ module Rust
28
+ class Attribute < Element
29
+ def initialize(name, type, opts)
30
+ super()
31
+
32
+ @name = name
33
+ @type = Type.new(type)
34
+ @options = opts
35
+
36
+ @declaration_template = ""
37
+ @definition_template = Templates["AttributeDefinition"]
38
+ @prototype_template = "void set!attribute_bindname!(VALUE self, VALUE val);\nVALUE get!attribute_bindname!(VALUE self);\n"
39
+ @initialization_template = Templates["AttributeInitBinding"]
40
+
41
+
42
+ add_expansion 'parent_varname', "@options[:parent].varname"
43
+ add_expansion 'attribute_bindname', "@name"
44
+ add_expansion 'attribute_type', "@type"
45
+ add_expansion 'attribute_name', "@name"
46
+ end
47
+
48
+ end
49
+ end
50
+
51
+
@@ -0,0 +1,172 @@
1
+ # Copyright (c) 2005-2007 Diego Pettenò <flameeyes@gmail.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining
4
+ # a copy of this software and associated documentation files (the
5
+ # "Software"), to deal in the Software without restriction, including
6
+ # without limitation the rights to use, copy, modify, merge,
7
+ # publish, distribute, sublicense, and/or sell copies of the Software,
8
+ # and to permit persons to whom the Software is furnished to do so,
9
+ # subject to the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be
12
+ # included in all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
18
+ # BE LIABLE
19
+ # FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
20
+ # CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+
23
+ require 'rust/namespace'
24
+
25
+ module Rust
26
+ # Base class to use to create bindings for ruby.
27
+ # You shouldn't instantiate this manually, but rather use the
28
+ # create_bindings function.
29
+ class Bindings
30
+ # Constant to use with Bindings.create_bindings to state that the
31
+ # bindings that are to be created are for a C library.
32
+ LangC = "c"
33
+
34
+ # Constant to use with Bindings.create_bindings to state that the
35
+ # bindings that are to be created are for a C++ library.
36
+ LangCxx = "cxx"
37
+
38
+ # Constant to use with include_header method to state that the
39
+ # included header is a system library header.
40
+ HeaderGlobal = "global"
41
+
42
+ # Constant to use with include_header method to state that the
43
+ # included header is a local header.
44
+ HeaderLocal = "local"
45
+
46
+ def initialize(name, lang) # :notnew:
47
+ @name = name
48
+ @lang = lang
49
+
50
+ @modules = Array.new
51
+ @custom_definition = Array.new
52
+ @custom_initialization = Array.new
53
+
54
+ @cxx_includes = ""
55
+ @c_includes = ""
56
+ end
57
+
58
+ # This function is called when creating Ruby bindings for a
59
+ # library.
60
+ #
61
+ # The first parameter has to be one between Rust::Bindings::LangC
62
+ # or Rust::Bindings::LangCxx, and tells Rust which programming
63
+ # language the library to bind is written into.
64
+ #
65
+ # Please note that Rust always generates C++ code even when
66
+ # binding a library written in C, as STL templates are used all
67
+ # over the generics code.
68
+ def Bindings.create_bindings(lang, name)
69
+ bindings =
70
+ case lang
71
+ when Bindings::LangCxx, Bindings::LangC
72
+ bindings = Bindings.new(name, lang)
73
+ else
74
+ raise ArgumentError, "#{lang} is not a valid value for type parameter"
75
+ end
76
+
77
+ yield bindings
78
+
79
+ header = File.new("#{name}.hh", File::CREAT|File::TRUNC|File::RDWR)
80
+ unit = File.new("#{name}.cc", File::CREAT|File::TRUNC|File::RDWR)
81
+
82
+ header.puts bindings.header
83
+ unit.puts bindings.unit
84
+
85
+ header.close
86
+ unit.close
87
+ end
88
+
89
+ # Adds an include header with the specified name.
90
+ # This function adds to the list of header files to include the
91
+ # one with the specified name.
92
+ #
93
+ # If the scope paramether is set to Bindings.HeaderLocal, the name of
94
+ # the header file will be enclosed in double quotes ("") while
95
+ # including it, while it will be included it in angle quotes if
96
+ # the parameter is set to Bindings.HeaderGlobal (the default).
97
+ def include_header(name, scope = Bindings::HeaderGlobal, lang = @lang)
98
+ name =
99
+ case scope
100
+ when HeaderLocal then "\"#{name}\""
101
+ when HeaderGlobal then "<#{name}>"
102
+ else
103
+ raise ArgumentError, "#{scope} not a valid value for scope parameter."
104
+ end
105
+
106
+ case lang
107
+ when Bindings::LangCxx
108
+ @cxx_includes << "\n#include #{name}"
109
+ when Bindings::LangC
110
+ @c_includes << "\n#include #{name}"
111
+ end
112
+ end
113
+
114
+ # Binds a new Namespace to a Ruby module; the name parameter is
115
+ # used as the name of the module, while the cxxname one (if not
116
+ # null) is used to indicate the actual C++ namespace to use; when
117
+ # binding a C library, you should rather use the add_module
118
+ # function, although that's just a partial wrapper around this one.
119
+ def add_namespace(name, cxxname = nil)
120
+ cxxname = name if cxxname == nil
121
+
122
+ ns = Namespace.new(name, cxxname)
123
+
124
+ yield ns
125
+
126
+ @modules << ns
127
+ end
128
+
129
+ # Create a new Ruby module with the given name; this is used when
130
+ # binding C libraries, as they don't use namespace, so you have to
131
+ # create the modules from scratch.
132
+ def add_module(name)
133
+ add_namespace(name, "")
134
+ end
135
+
136
+ # Returns the content of the header for the bindings, recursively
137
+ # calling the proper functions to get the declarations for the
138
+ # modules bound and so on.
139
+ #
140
+ # This should *never* be used directly
141
+ def header
142
+ Templates["BindingsHeader"].
143
+ gsub("!bindings_name!", @name).
144
+ gsub("!modules_declaration!", @modules.collect { |ns| ns.declaration }.join("\n")).
145
+ gsub("!cxx_includes!", @cxx_includes).
146
+ gsub("!c_includes!", @c_includes)
147
+ end
148
+
149
+ # Returns the content of the unit for the bindings, recursively
150
+ # calling the proper functions to get the definitions and the
151
+ # initialisation function for the modules bound and so on.
152
+ #
153
+ # This should *never* be used directly
154
+ def unit
155
+ Templates["BindingsUnit"].
156
+ gsub("!bindings_name!", @name).
157
+ gsub("!modules_initialization!", @modules.collect { |ns| ns.initialization }.join("\n")).
158
+ gsub("!modules_definition!", @modules.collect { |ns| ns.definition }.join("\n")).
159
+ gsub("!custom_definition!", @custom_definition.join("\n")).
160
+ gsub("!custom_initialization!", @custom_initialization.join("\n"))
161
+ end
162
+
163
+ def add_custom_definition(element)
164
+ @custom_definition << element
165
+ end
166
+
167
+ def add_custom_initialization(initialization)
168
+ @custom_initialization << initialization
169
+ end
170
+ end
171
+
172
+ end
@@ -0,0 +1,334 @@
1
+ # Copyright (c) 2005-2007 Diego Pettenò <flameeyes@gmail.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining
4
+ # a copy of this software and associated documentation files (the
5
+ # "Software"), to deal in the Software without restriction, including
6
+ # without limitation the rights to use, copy, modify, merge,
7
+ # publish, distribute, sublicense, and/or sell copies of the Software,
8
+ # and to permit persons to whom the Software is furnished to do so,
9
+ # subject to the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be
12
+ # included in all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
18
+ # BE LIABLE
19
+ # FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
20
+ # CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+
23
+ require 'rust/container'
24
+ require 'rust/function'
25
+ require 'rust/attribute'
26
+ require 'rust/type'
27
+
28
+ module Rust
29
+ class Class < Container
30
+ attr_accessor :bindname
31
+ attr_reader :name, :cname
32
+ attr_reader :varname, :varcname, :ptrmap, :function_free, :parent_varname
33
+
34
+ # Rust::Namespace object for the class, used to get the proper C++
35
+ # name.
36
+ attr_reader :namespace
37
+
38
+ # This function initializes the Class instance by setting the
39
+ # values to the attributes defining its namespace, name
40
+ # and a few other needed information.
41
+ #
42
+ # Don't call this function directly, use Namespace.add_cxx_class
43
+ def initialize(name, namespace, bindname = name.split("::").last ) # :notnew:
44
+ super()
45
+
46
+ @name = name
47
+ @namespace = namespace
48
+
49
+ type = Type.new(complete_name)
50
+ @varname = type.valid_name
51
+ @parent_varname = "rb_cObject"
52
+
53
+ @ptrmap = "#{type.valid_name}Map"
54
+ @function_free = "#{varname}_free"
55
+
56
+ @cname = @namespace.cname ? "#{@namespace.cname}::#{@name}" : @name
57
+
58
+ type = Type.new(@cname)
59
+ @varcname = type.valid_name
60
+ @bindname = bindname
61
+
62
+ @declaration_template = Templates["ClassDeclarations"]
63
+ @initialization_template = Templates["ClassInitialize"]
64
+
65
+ add_expansion 'class_varname', 'varname'
66
+ add_expansion 'class_varcname', 'varcname'
67
+ add_expansion 'c_class_name', 'cname'
68
+ # add_expansion 'c_class_basename', '@name.split("::").last'
69
+ add_expansion 'bind_name', '@bindname'
70
+ add_expansion 'class_ptrmap', 'ptrmap'
71
+ add_expansion 'class_free_function', '@function_free'
72
+ add_expansion 'parent_varname', '@parent_varname'
73
+ end
74
+
75
+ # Adds a new constructor for the class.
76
+ # This function creates a new constructor method for the C/C++
77
+ # class to bind, and yields it so that parameters can be added
78
+ # afterward.
79
+ def add_constructor
80
+ constructor = self.class::Constructor.new(self)
81
+
82
+ begin
83
+ yield constructor
84
+ rescue LocalJumpError
85
+ # Ignore this, we can easily have methods without parameters
86
+ # or other extra informations.
87
+ end if block_given?
88
+
89
+ register_function(constructor)
90
+
91
+ return constructor
92
+ end
93
+
94
+ # Adds a new method for the class.
95
+ # This function adds a new generic method for the class. In the
96
+ # case of C++ classes, this is an actual method of the bound
97
+ # class, while in case of Class Wrappers, this is just a function
98
+ # that expects to find a static parameter that is the instance
99
+ # pointer itself.
100
+ def add_method(name, return_value = "void", bindname = name)
101
+ method = self.class::Method.new({ :name => name,
102
+ :bindname => bindname,
103
+ :return => return_value,
104
+ :klass => self
105
+ })
106
+
107
+ begin
108
+ yield method
109
+ rescue LocalJumpError
110
+ # Ignore this, we can easily have methods without parameters
111
+ # or other extra informations.
112
+ end if block_given?
113
+
114
+ register_function(method)
115
+
116
+ method
117
+ end
118
+
119
+ def add_attribute(name, type, bindname = name)
120
+ attribute = Attribute.new(name, type, { :parent => self })
121
+
122
+ yield attribute if block_given?
123
+
124
+ @children << attribute
125
+
126
+ attribute
127
+ end
128
+
129
+ def add_operator(name, return_value, bindname = name)
130
+ operator = Class::Operator.new({ :name => name,
131
+ :bindname => bindname,
132
+ :return => return_value,
133
+ :klass => self
134
+ })
135
+ begin
136
+ yield operator
137
+ rescue LocalJumpError
138
+ end if block_given?
139
+
140
+ register_function(operator)
141
+
142
+
143
+ return operator
144
+ end
145
+
146
+ def complete_name
147
+ name = @name
148
+ parent = @parent
149
+ namespace = @namespace
150
+
151
+ if not parent.nil?
152
+ name = "#{parent.cname}::#{name}"
153
+ end
154
+
155
+ if not namespace.nil?
156
+ name = "#{namespace.cname}::#{name}"
157
+ end
158
+
159
+ return name if parent.nil?
160
+
161
+ while not parent.parent.nil?
162
+ name = "#{parent.parent.cname}::#{name}"
163
+ parent = parent.parent
164
+ end
165
+
166
+ return name if namespace.nil?
167
+
168
+ while not namespace.parent.nil?
169
+ name = "#{namespace.parent.cname}::#{name}"
170
+ namespace = namespace.parent
171
+ end
172
+
173
+ name
174
+ end
175
+
176
+ # Adds a new variable for the class. It's not an actual variable,
177
+ # as hopefully there aren't global or class public variables in
178
+ # any library.
179
+ # These virtual variables have setter and getter methods, usually
180
+ # called 'var' and 'setVar' in C++ (or 'getVar' and 'setVar'), and
181
+ # are mapped to 'var' and 'var=' in Ruby, so that setting the
182
+ # variable in Ruby will just call the setter method.
183
+ def add_variable(name, type, getter = nil, setter = nil)
184
+ getter = name unless getter
185
+ setter = "set" + name[0..0].capitalize + name[1..-1] unless
186
+ setter
187
+
188
+ method_get = add_method getter, type
189
+ method_get.add_alias name
190
+
191
+ method_set = add_method setter, "void"
192
+ method_set.add_alias "#{name}="
193
+
194
+ begin
195
+ yield method_get, method_set
196
+ rescue LocalJumpError
197
+ # Ignore this, we can easily have methods without parameters
198
+ # or other extra informations.
199
+ end if block_given?
200
+
201
+ method_set.add_parameter type, "value"
202
+
203
+ return [method_get, method_set]
204
+ end
205
+
206
+ # This class is used to represent a method for a C/C++ class bound
207
+ # in a Ruby extension. Through an object of this class you can add
208
+ # parameters and more to the method.
209
+ class Method < Function
210
+
211
+ # Initialisation function, calls Function.initialize and sets
212
+ # the important parameters that differs from a generic function
213
+ def initialize(params) # :notnew:
214
+ params[:parent] = params[:klass]
215
+ super
216
+
217
+ @varname =
218
+ "f#{@parent.namespace.name.gsub("::","_")}_#{@parent.name}_#{@name}"
219
+
220
+ @definition_template = Templates["CxxMethodStub"]
221
+ @initialization_template = Templates["MethodInitBinding"]
222
+ end
223
+ end
224
+
225
+ class Operator < Function
226
+ attr_reader :position # 1: pre 2: mid 3: post 4: mixed
227
+
228
+ def initialize(params)
229
+ params[:parent] = params[:klass]
230
+ super
231
+
232
+ type = Type.new(@parent.namespace.cname+"::"+@parent.cname)
233
+
234
+ @varname = "f#{type.valid_name}_#{valid_name}"
235
+
236
+ @definition_template = Templates["CxxMethodStub"]
237
+ @initialization_template = Templates["MethodInitBinding"]
238
+ end
239
+
240
+ def bind_call(nparam = nil)
241
+ case @return
242
+ when nil
243
+ raise "nil return value is not supported for non-constructors."
244
+ when "void"
245
+ return "#{raw_call(nparam)}; return Qnil;\n"
246
+ else
247
+ type = Type.new(@return)
248
+ if not @return.include?("*") and not type.native?
249
+ "return cxx2ruby( new #{@return.gsub("&", "")}(#{raw_call(nparam)}), true );\n" # XXX: needs a copy constructor
250
+ else
251
+ "return cxx2ruby( static_cast<#{@return}>(#{raw_call(nparam)}) );\n"
252
+ end
253
+ end
254
+ end
255
+
256
+ private
257
+ def raw_call(nparam = nil)
258
+ case @position
259
+ when 1 # pre
260
+ "#{@name} (*tmp)"
261
+ when 2 # mid
262
+ "(*tmp) #{@name[0].chr} #{params_conversion(nparam)} #{@name[@name.length-1].chr} "
263
+ when 4
264
+ "(*tmp) #{@name[0].chr} #{self.parameters[0].conversion} #{@name[1].chr} #{@name[@name.length-1].chr} #{self.parameters[1].conversion}" if self.parameters.size == 2
265
+ else
266
+ "(*tmp) #{@name} #{params_conversion(nparam)} "
267
+ end
268
+ end
269
+
270
+ def valid_name
271
+ case @name
272
+ when "+"
273
+ @position = 3
274
+ "plusop"
275
+ when "-"
276
+ @position = 3
277
+ "minusop"
278
+ when "*"
279
+ @position = 3
280
+ "multop"
281
+ when "/"
282
+ @position = 3
283
+ "divop"
284
+ when /\[\s*\]=/
285
+ @position = 4
286
+ "ateqop"
287
+ when /\[\s*\]/
288
+ @position = 2
289
+ "atop"
290
+ when "=="
291
+ @position = 3
292
+ "equalop"
293
+ when "!="
294
+ @position = 3
295
+ "notequalop"
296
+ when "<<"
297
+ @position = 3
298
+ "outstream"
299
+ when ">>"
300
+ @position = 3
301
+ "intstream"
302
+ when "!"
303
+ @position = 1
304
+ "notop"
305
+ else
306
+ @position = 3
307
+ "undefop_#{@name[0].chr.to_i}#{rand(1024)}"
308
+ end
309
+ end
310
+ end
311
+
312
+ # This class is used to represente the constructor of a C++ class
313
+ # bound in a Ruby extension.
314
+ class Constructor < Function
315
+
316
+ # Initialisation function, calls Function.initialise, but accepts
317
+ # only a single parameter, the class the constructor belong to.
318
+ def initialize(klass) # :notnew:
319
+ super({
320
+ :parent => klass,
321
+ :bindname => "initialize",
322
+ :name => klass.name
323
+ })
324
+
325
+ @definition_template = Templates["ConstructorStub"]
326
+ end
327
+
328
+ def bind_call(nparam = nil)
329
+ "#{raw_call(nparam)};\n"
330
+ end
331
+ end
332
+
333
+ end
334
+ end