Commit 627221a6519eacbdb368990ece9f9d7c80b3368c

Moved rust.rb and rust/ to lib/

Commit diff

lib/rust.rb

 
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
23require '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.
44module 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 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
65end
66
67require 'rust/bindings'
toggle raw diff

lib/rust/bindings.rb

 
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
23require 'rust/namespace'
24
25module 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 @cxx_includes = ""
52 @c_includes = ""
53 end
54
55 # This function is called when creating Ruby bindings for a
56 # library.
57 #
58 # The first parameter has to be one between Rust::Bindings::LangC
59 # or Rust::Bindings::LangCxx, and tells Rust which programming
60 # language the library to bind is written into.
61 #
62 # Please note that Rust always generates C++ code even when
63 # binding a library written in C, as STL templates are used all
64 # over the generics code.
65 def Bindings.create_bindings(lang, name)
66 bindings =
67 case lang
68 when Bindings::LangCxx, Bindings::LangC
69 bindings = Bindings.new(name, lang)
70 else
71 raise ArgumentError, "#{lang} is not a valid value for type parameter"
72 end
73
74 yield bindings
75
76 header = File.new("#{name}.hh", File::CREAT|File::TRUNC|File::RDWR)
77 unit = File.new("#{name}.cc", File::CREAT|File::TRUNC|File::RDWR)
78
79 header.puts bindings.header
80 unit.puts bindings.unit
81
82 header.close
83 unit.close
84 end
85
86 # Adds an include header with the specified name.
87 # This function adds to the list of header files to include the
88 # one with the specified name.
89 #
90 # If the scope paramether is set to Bindings.HeaderLocal, the name of
91 # the header file will be enclosed in double quotes ("") while
92 # including it, while it will be included it in angle quotes if
93 # the parameter is set to Bindings.HeaderGlobal (the default).
94 def include_header(name, scope = Bindings::HeaderGlobal, lang = @lang)
95 name =
96 case scope
97 when HeaderLocal then "\"#{name}\""
98 when HeaderGlobal then "<#{name}>"
99 else
100 raise ArgumentError, "#{scope} not a valid value for scope parameter."
101 end
102
103 case lang
104 when Bindings::LangCxx
105 @cxx_includes << "\n#include #{name}"
106 when Bindings::LangC
107 @c_includes << "\n#include #{name}"
108 end
109 end
110
111 # Binds a new Namespace to a Ruby module; the name parameter is
112 # used as the name of the module, while the cxxname one (if not
113 # null) is used to indicate the actual C++ namespace to use; when
114 # binding a C library, you should rather use the add_module
115 # function, although that's just a partial wrapper around this one.
116 def add_namespace(name, cxxname = nil)
117 cxxname = name if cxxname == nil
118
119 ns = Namespace.new(name, cxxname)
120
121 yield ns
122
123 @modules << ns
124 end
125
126 # Create a new Ruby module with the given name; this is used when
127 # binding C libraries, as they don't use namespace, so you have to
128 # create the modules from scratch.
129 def add_module(name)
130 add_namespace(name, "")
131 end
132
133 # Returns the content of the header for the bindings, recursively
134 # calling the proper functions to get the declarations for the
135 # modules bound and so on.
136 #
137 # This should *never* be used directly
138 def header
139 Templates["BindingsHeader"].
140 gsub("!bindings_name!", @name).
141 gsub("!modules_declaration!", @modules.collect { |ns| ns.declaration }.join("\n")).
142 gsub("!cxx_includes!", @cxx_includes).
143 gsub("!c_includes!", @c_includes)
144 end
145
146 # Returns the content of the unit for the bindings, recursively
147 # calling the proper functions to get the definitions and the
148 # initialisation function for the modules bound and so on.
149 #
150 # This should *never* be used directly
151 def unit
152 Templates["BindingsUnit"].
153 gsub("!bindings_name!", @name).
154 gsub("!modules_initialization!", @modules.collect { |ns| ns.initialization }.join("\n")).
155 gsub("!modules_definition!", @modules.collect { |ns| ns.definition }.join("\n"))
156 end
157 end
158
159end
toggle raw diff

lib/rust/class.rb

 
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
23require 'rust/container'
24require 'rust/function'
25
26module Rust
27 class Class < Container
28 attr_reader :name, :cname
29 attr_reader :varname, :varcname, :ptrmap, :function_free, :parent_varname
30
31 # Rust::Namespace object for the class, used to get the proper C++
32 # name.
33 attr_reader :namespace
34
35 # This function initializes the Class instance by setting the
36 # values to the attributes defining its namespace, name
37 # and a few other needed information.
38 #
39 # Don't call this function directly, use Namespace.add_cxx_class
40 def initialize(name, namespace) # :notnew:
41 super()
42
43 @name = name
44 @namespace = namespace
45
46 @varname = "#{@namespace.name.gsub("::", "_")}_#{@name}"
47 @parent_varname = "rb_cObject"
48
49 @ptrmap = "#{@namespace.name.gsub("::", "_")}_#{@name}_ptrMap"
50 @function_free = "#{varname}_free"
51
52 @cname = @namespace.cname ? "#{@namespace.cname}::#{@name}" : @name
53 @varcname = @cname.sub("*", "Ptr").gsub("::", "_").gsub(' ', '')
54
55 @declaration_template = Templates["ClassDeclarations"]
56 @initialization_template = Templates["ClassInitialize"]
57
58 add_expansion 'class_varname', 'varname'
59 add_expansion 'class_varcname', 'varcname'
60 add_expansion 'c_class_name', 'cname'
61 add_expansion 'c_class_basename', '@name.split("::").last'
62 add_expansion 'class_ptrmap', 'ptrmap'
63 add_expansion 'class_free_function', '@function_free'
64 add_expansion 'parent_varname', '@parent_varname'
65 end
66
67 # Adds a new constructor for the class.
68 # This function creates a new constructor method for the C/C++
69 # class to bind, and yields it so that parameters can be added
70 # afterward.
71 def add_constructor
72 constructor = self.class::Constructor.new(self)
73
74 begin
75 yield constructor
76 rescue LocalJumpError
77 # Ignore this, we can easily have methods without parameters
78 # or other extra informations.
79 end
80
81 @children << constructor
82
83 return constructor
84 end
85
86 # Adds a new method for the class.
87 # This function adds a new generic method for the class. In the
88 # case of C++ classes, this is an actual method of the bound
89 # class, while in case of Class Wrappers, this is just a function
90 # that expects to find a static parameter that is the instance
91 # pointer itself.
92 def add_method(name, return_value = "void", bindname = name)
93 method = self.class::Method.new({ :name => name,
94 :bindname => bindname,
95 :return => return_value,
96 :klass => self
97 })
98
99 begin
100 yield method
101 rescue LocalJumpError
102 # Ignore this, we can easily have methods without parameters
103 # or other extra informations.
104 end
105
106 @children << method
107
108 return method
109 end
110
111 # Adds a new variable for the class. It's not an actual variable,
112 # as hopefully there aren't global or class public variables in
113 # any library.
114 # These virtual variables have setter and getter methods, usually
115 # called 'var' and 'setVar' in C++ (or 'getVar' and 'setVar'), and
116 # are mapped to 'var' and 'var=' in Ruby, so that setting the
117 # variable in Ruby will just call the setter method.
118 def add_variable(name, type, getter = nil, setter = nil)
119 getter = name unless getter
120 setter = "set" + name[0..0].capitalize + name[1..-1] unless
121 setter
122
123 method_get = add_method getter, type
124 method_get.add_alias name
125
126 method_set = add_method setter, "void"
127 method_set.add_alias "#{name}="
128
129 begin
130 yield method_get, method_set
131 rescue LocalJumpError
132 # Ignore this, we can easily have methods without parameters
133 # or other extra informations.
134 end
135
136 method_set.add_parameter type, "value"
137
138 return [method_get, method_set]
139 end
140
141 # This class is used to represent a method for a C/C++ class bound
142 # in a Ruby extension. Through an object of this class you can add
143 # parameters and more to the method.
144 class Method < Function
145
146 # Initialisation function, calls Function.initialize and sets
147 # the important parameters that differs from a generic function
148 def initialize(params) # :notnew:
149 params[:parent] = params[:klass]
150 super
151
152 @varname =
153 "f#{@parent.namespace.name.gsub("::","_")}_#{@parent.name}_#{@name}"
154
155 @definition_template = Templates["CxxMethodStub"]
156 @initialization_template = Templates["MethodInitBinding"]
157 end
158 end
159
160 # This class is used to represente the constructor of a C++ class
161 # bound in a Ruby extension.
162 class Constructor < Function
163
164 # Initialisation function, calls Function.initialise, but accepts
165 # only a single parameter, the class the constructor belong to.
166 def initialize(klass) # :notnew:
167 super({
168 :parent => klass,
169 :bindname => "initialize",
170 :name => klass.name
171 })
172
173 @definition_template = Templates["ConstructorStub"]
174 end
175
176 def bind_call(nparam = nil)
177 "#{raw_call(nparam)};\n"
178 end
179 end
180
181 end
182end
toggle raw diff

lib/rust/constants.rb

 
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
23require 'rust/element'
24
25module Rust
26 # This class represents a C/C++ constants or enumeration, it is
27 # simply going to map a Ruby constant with the given name under its
28 # parent with the given value
29 class Constant < Element
30 def initialize(name, value, parent)
31 super()
32
33 @name = name
34 @value = value
35 @parent = parent
36
37 @declaration_template = ""
38 @definition_template = ""
39 @initialization_template =
40 "rb_define_const(r!parent_varname!, \"!name!\", cxx2ruby(!value!));\n"
41
42 add_expansion 'parent_varname', '@parent.varname'
43 add_expansion 'name', '@name'
44 add_expansion 'value', '@value'
45 end
46 end
47
48end
toggle raw diff

lib/rust/container.rb

 
1# Copyright (c) 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
23require 'rust/element'
24require 'rust/enum'
25
26module Rust
27 # This class defines a 'container', an element that can contain
28 # functions, constants and classes. Both modules and classes are
29 # modules, as you can have singleton methods and constants in both
30 # of them
31 class Container < Element
32 def add_cxx_class(name, parent = nil)
33 klass = CxxClass.new(name, self, parent)
34
35 yield klass
36
37 @children << klass
38 return klass
39 end
40
41 def add_class_wrapper(name, type)
42 klass = ClassWrapper.new(name, type, self)
43
44 yield klass
45
46 @children << klass
47 return klass
48 end
49
50 def add_function(name, return_value = "void", bindname = name)
51 function = Function.new({ :name => name,
52 :bindname => bindname,
53 :return => return_value,
54 :parent => self
55 })
56
57 begin
58 yield function
59 rescue LocalJumpError
60 # Ignore this, we can easily have methods without parameters
61 # or other extra informations.
62 end
63
64 @children << function
65
66 return function
67 end
68
69 def add_constant(name, value = name)
70 @children << Constant.new(name, value, self)
71 end
72
73 def add_enum(name, ctype = nil)
74 enum = Enum.new(name, self, ctype)
75
76 yield enum
77
78 @children << enum
79
80 return enum
81 end
82
83 def add_namespace(name, cname = name)
84 ns = Namespace.new(name, cname, self)
85
86 yield ns
87
88 @children << ns
89 end
90
91 end
92end
toggle raw diff

lib/rust/cwrapper.rb

 
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 no