gir_ffi 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. data/DESIGN.rdoc +54 -0
  2. data/History.txt +3 -0
  3. data/README.rdoc +59 -0
  4. data/Rakefile +21 -0
  5. data/TODO.rdoc +40 -0
  6. data/examples/01_empty_window.rb +15 -0
  7. data/examples/02_hello_world.rb +30 -0
  8. data/examples/03_upgraded_hello_world.rb +45 -0
  9. data/examples/demo_ffi_inherited_layout.rb +21 -0
  10. data/examples/demo_ffi_nested_struct.rb +17 -0
  11. data/examples/demo_ffi_safe_inherited_layout.rb +43 -0
  12. data/examples/hard_coded.rb +144 -0
  13. data/lib/gir_ffi.rb +47 -0
  14. data/lib/gir_ffi/allocation_helper.rb +12 -0
  15. data/lib/gir_ffi/arg_helper.rb +77 -0
  16. data/lib/gir_ffi/base.rb +23 -0
  17. data/lib/gir_ffi/builder.rb +159 -0
  18. data/lib/gir_ffi/builder_helper.rb +32 -0
  19. data/lib/gir_ffi/class_base.rb +11 -0
  20. data/lib/gir_ffi/class_builder.rb +116 -0
  21. data/lib/gir_ffi/constructor_definition_builder.rb +20 -0
  22. data/lib/gir_ffi/function_definition_builder.rb +148 -0
  23. data/lib/gir_ffi/g_error.rb +8 -0
  24. data/lib/gir_ffi/g_type.rb +14 -0
  25. data/lib/gir_ffi/i_arg_info.rb +16 -0
  26. data/lib/gir_ffi/i_base_info.rb +45 -0
  27. data/lib/gir_ffi/i_callable_info.rb +18 -0
  28. data/lib/gir_ffi/i_callback_info.rb +7 -0
  29. data/lib/gir_ffi/i_constant_info.rb +6 -0
  30. data/lib/gir_ffi/i_enum_info.rb +13 -0
  31. data/lib/gir_ffi/i_field_info.rb +10 -0
  32. data/lib/gir_ffi/i_flags_info.rb +5 -0
  33. data/lib/gir_ffi/i_function_info.rb +16 -0
  34. data/lib/gir_ffi/i_interface_info.rb +7 -0
  35. data/lib/gir_ffi/i_object_info.rb +50 -0
  36. data/lib/gir_ffi/i_property_info.rb +7 -0
  37. data/lib/gir_ffi/i_registered_type_info.rb +8 -0
  38. data/lib/gir_ffi/i_repository.rb +108 -0
  39. data/lib/gir_ffi/i_signal_info.rb +7 -0
  40. data/lib/gir_ffi/i_struct_info.rb +22 -0
  41. data/lib/gir_ffi/i_type_info.rb +25 -0
  42. data/lib/gir_ffi/i_union_info.rb +7 -0
  43. data/lib/gir_ffi/i_value_info.rb +8 -0
  44. data/lib/gir_ffi/i_vfunc_info.rb +7 -0
  45. data/lib/gir_ffi/lib.rb +174 -0
  46. data/lib/gir_ffi/lib_c.rb +11 -0
  47. data/lib/gir_ffi/method_missing_definition_builder.rb +62 -0
  48. data/lib/gir_ffi/module_builder.rb +66 -0
  49. data/lib/gir_ffi/overrides/gtk.rb +12 -0
  50. data/lib/gir_ffi/version.rb +4 -0
  51. data/tasks/bones.rake +87 -0
  52. data/tasks/notes.rake +134 -0
  53. data/tasks/post_load.rake +25 -0
  54. data/tasks/setup.rb +138 -0
  55. data/tasks/test.rake +22 -0
  56. data/test/arg_helper_test.rb +112 -0
  57. data/test/builder_test.rb +328 -0
  58. data/test/constructor_definition_builder_test.rb +19 -0
  59. data/test/function_definition_builder_test.rb +60 -0
  60. data/test/g_type_test.rb +22 -0
  61. data/test/girffi_test.rb +11 -0
  62. data/test/gtk_overrides_test.rb +22 -0
  63. data/test/i_repository_test.rb +54 -0
  64. data/test/test_helper.rb +39 -0
  65. metadata +174 -0
@@ -0,0 +1,20 @@
1
+ module GirFFI
2
+ # Implements the creation of a Ruby constructor definition out of a GIR
3
+ # IFunctionInfo, if it represents a constructor.
4
+ class ConstructorDefinitionBuilder < FunctionDefinitionBuilder
5
+ private
6
+
7
+ def process_return_value
8
+ end
9
+
10
+ def filled_out_template
11
+ return <<-CODE
12
+ def #{@info.name} #{@inargs.join(', ')}
13
+ #{@pre.join("\n")}
14
+ _real_new #{@libmodule}.#{@info.symbol}(#{@callargs.join(', ')})
15
+ end
16
+ CODE
17
+ end
18
+ end
19
+ end
20
+
@@ -0,0 +1,148 @@
1
+ module GirFFI
2
+ # Implements the creation of a Ruby function definition out of a GIR
3
+ # IFunctionInfo.
4
+ class FunctionDefinitionBuilder
5
+ KEYWORDS = [
6
+ "alias", "and", "begin", "break", "case", "class", "def", "do",
7
+ "else", "elsif", "end", "ensure", "false", "for", "if", "in",
8
+ "module", "next", "nil", "not", "or", "redo", "rescue", "retry",
9
+ "return", "self", "super", "then", "true", "undef", "unless",
10
+ "until", "when", "while", "yield"
11
+ ]
12
+
13
+ def initialize info, libmodule
14
+ @info = info
15
+ @libmodule = libmodule
16
+ end
17
+
18
+ def generate
19
+ setup_accumulators
20
+ process_return_value
21
+ @info.args.each {|a| process_arg a}
22
+ adjust_accumulators
23
+ return filled_out_template
24
+ end
25
+
26
+ private
27
+
28
+ def setup_accumulators
29
+ @inargs = []
30
+ @callargs = []
31
+ @retvals = []
32
+
33
+ @pre = []
34
+ @post = []
35
+
36
+ @capture = ""
37
+
38
+ @varno = 0
39
+ end
40
+
41
+ def process_arg arg
42
+ case arg.direction
43
+ when :inout
44
+ process_inout_arg arg
45
+ when :in
46
+ process_in_arg arg
47
+ else
48
+ raise NotImplementedError
49
+ end
50
+ end
51
+
52
+ def process_inout_arg arg
53
+ raise NotImplementedError unless arg.ownership_transfer == :everything
54
+
55
+ name = safe arg.name
56
+ prevar = new_var
57
+ postvar = new_var
58
+
59
+ @inargs << name
60
+ case arg.type.tag
61
+ when :int, :int32
62
+ @pre << "#{prevar} = GirFFI::ArgHelper.int_to_inoutptr #{name}"
63
+ @post << "#{postvar} = GirFFI::ArgHelper.outptr_to_int #{prevar}"
64
+ when :array
65
+ case arg.type.param_type(0).tag
66
+ when :utf8
67
+ @pre << "#{prevar} = GirFFI::ArgHelper.string_array_to_inoutptr #{name}"
68
+ @post << "#{postvar} = GirFFI::ArgHelper.outptr_to_string_array #{prevar}, #{name}.nil? ? 0 : #{name}.size"
69
+ else
70
+ raise NotImplementedError
71
+ end
72
+ else
73
+ raise NotImplementedError
74
+ end
75
+ @callargs << prevar
76
+ @retvals << postvar
77
+ end
78
+
79
+ def process_in_arg arg
80
+ name = safe arg.name
81
+ type = arg.type
82
+ tag = type.tag
83
+
84
+ @inargs << name
85
+
86
+ if tag == :interface and type.interface.type == :callback
87
+ # TODO: Use arg.scope to decide if this is needed.
88
+ procvar = new_var
89
+ @pre << "#{procvar} = GirFFI::ArgHelper.mapped_callback_args #{name}"
90
+ @pre << "#{@libmodule}::CALLBACKS << #{procvar}"
91
+ @callargs << procvar
92
+ elsif tag == :void
93
+ raise NotImplementedError unless arg.type.pointer?
94
+ prevar = new_var
95
+ @pre << "#{prevar} = GirFFI::ArgHelper.object_to_inptr #{name}"
96
+ @callargs << prevar
97
+ else
98
+ @callargs << name
99
+ end
100
+ end
101
+
102
+ def process_return_value
103
+ type = @info.return_type
104
+ tag = type.tag
105
+ return if tag == :void
106
+ retval = new_var
107
+ @capture = "#{retval} = "
108
+
109
+ if tag == :interface
110
+ interface = type.interface
111
+ @retvals << "#{interface.namespace}::#{interface.name}._real_new(#{retval})"
112
+ else
113
+ @retvals << retval
114
+ end
115
+ end
116
+
117
+ def adjust_accumulators
118
+ @post << "return #{@retvals.join(', ')}" unless @retvals.empty?
119
+
120
+ if @info.method?
121
+ @callargs.unshift "self"
122
+ end
123
+ end
124
+
125
+ def filled_out_template
126
+ return <<-CODE
127
+ def #{@info.name} #{@inargs.join(', ')}
128
+ #{@pre.join("\n")}
129
+ #{@capture}#{@libmodule}.#{@info.symbol} #{@callargs.join(', ')}
130
+ #{@post.join("\n")}
131
+ end
132
+ CODE
133
+ end
134
+
135
+ def new_var
136
+ @varno += 1
137
+ "_v#{@varno}"
138
+ end
139
+
140
+ def safe name
141
+ if KEYWORDS.include? name
142
+ "#{name}_"
143
+ else
144
+ name
145
+ end
146
+ end
147
+ end
148
+ end
@@ -0,0 +1,8 @@
1
+ module GirFFI
2
+ # Wraps GObject's GError struct.
3
+ class GError < FFI::Struct
4
+ layout :domain, :uint32,
5
+ :code, :int,
6
+ :message, :string
7
+ end
8
+ end
@@ -0,0 +1,14 @@
1
+ require 'ffi'
2
+
3
+ module GirFFI
4
+ module GType
5
+ def self.init; Lib::g_type_init; end
6
+ module Lib
7
+ extend FFI::Library
8
+ ffi_lib "gobject-2.0"
9
+ attach_function :g_type_init, [], :void
10
+ end
11
+ end
12
+ end
13
+
14
+
@@ -0,0 +1,16 @@
1
+ require 'gir_ffi/i_base_info'
2
+ module GirFFI
3
+ # Wraps a GIArgInfo struct.
4
+ # Represents an argument.
5
+ class IArgInfo < IBaseInfo
6
+ def direction; Lib.g_arg_info_get_direction @gobj; end
7
+ def return_value?; Lib.g_arg_info_is_return_value @gobj; end
8
+ def optional?; Lib.g_arg_info_is_optional @gobj; end
9
+ def may_be_null?; Lib.g_arg_info_may_be_null @gobj; end
10
+ def ownership_transfer; Lib.g_arg_info_get_ownership_transfer @gobj; end
11
+ def scope; Lib.g_arg_info_get_scope @gobj; end
12
+ def closure; Lib.g_arg_info_get_closure @gobj; end
13
+ def destroy; Lib.g_arg_info_get_destroy @gobj; end
14
+ def type; ITypeInfo.wrap(Lib.g_arg_info_get_type @gobj); end
15
+ end
16
+ end
@@ -0,0 +1,45 @@
1
+ require 'gir_ffi/class_base'
2
+
3
+ module GirFFI
4
+ # Wraps GIBaseInfo struct, the base \type for all info types.
5
+ # Decendant types will be implemented as needed.
6
+ class IBaseInfo
7
+ include ClassBase
8
+
9
+ # This is a helper method to construct a method returning an array, out
10
+ # of the methods returning their number and the individual elements.
11
+ #
12
+ # For example, given the methods +n_foos+ and +foo+(+i+), this method
13
+ # will create an additional method +foos+ returning all args.
14
+ #
15
+ # Provide the second parameter if the plural is not trivially
16
+ # constructed by adding +s+ to the singular.
17
+ def self.build_array_method method, single = nil
18
+ single ||= method.to_s[0..-2]
19
+ count = "n_#{method}"
20
+ self.class_eval <<-CODE
21
+ def #{method}
22
+ (0..(#{count} - 1)).map do |i|
23
+ #{single} i
24
+ end
25
+ end
26
+ CODE
27
+ end
28
+
29
+ private_class_method :new
30
+
31
+ def name; Lib.g_base_info_get_name @gobj; end
32
+ def type; Lib.g_base_info_get_type @gobj; end
33
+ def namespace; Lib.g_base_info_get_namespace @gobj; end
34
+ def deprecated?; Lib.g_base_info_is_deprecated @gobj; end
35
+
36
+ def self.wrap ptr
37
+ return nil if ptr.null?
38
+ return new ptr
39
+ end
40
+
41
+ def == other
42
+ Lib.g_base_info_equal @gobj, other.to_ptr
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,18 @@
1
+ require 'gir_ffi/i_base_info'
2
+ require 'gir_ffi/i_type_info'
3
+ require 'gir_ffi/i_arg_info'
4
+
5
+ module GirFFI
6
+ # Wraps a GICallableInfo struct; represents a callable, either
7
+ # IFunctionInfo, ICallbackInfo or IVFuncInfo.
8
+ class ICallableInfo < IBaseInfo
9
+ def return_type; ITypeInfo.wrap(Lib.g_callable_info_get_return_type @gobj); end
10
+ def caller_owns; Lib.g_callable_info_get_caller_owns @gobj; end
11
+ def may_return_null?; Lib.g_callable_info_may_return_null @gobj; end
12
+ def n_args; Lib.g_callable_info_get_n_args @gobj; end
13
+ def arg(index); IArgInfo.wrap(Lib.g_callable_info_get_arg @gobj, index); end
14
+ ##
15
+ build_array_method :args
16
+ end
17
+ end
18
+
@@ -0,0 +1,7 @@
1
+ module GirFFI
2
+ # Wraps a GICallbackInfo struct. Has no methods in addition to the onese
3
+ # inherited from ICallableInfo.
4
+ class ICallbackInfo < ICallableInfo
5
+ end
6
+ end
7
+
@@ -0,0 +1,6 @@
1
+ module GirFFI
2
+ # Wraps a GIConstantInfo struct; represents an constant.
3
+ # Not implemented yet.
4
+ class IConstantInfo < IBaseInfo
5
+ end
6
+ end
@@ -0,0 +1,13 @@
1
+ module GirFFI
2
+ # Wraps a GIEnumInfo struct if it represents an enum.
3
+ # If it represents a flag, an IFlagsInfo object is used instead.
4
+ class IEnumInfo < IRegisteredTypeInfo
5
+ def n_values; Lib.g_enum_info_get_n_values @gobj; end
6
+ def value(index); IValueInfo.wrap(Lib.g_enum_info_get_value @gobj, index); end
7
+ ##
8
+ build_array_method :values
9
+
10
+ def storage_type; Lib.g_enum_info_get_storage_type @gobj; end
11
+ end
12
+ end
13
+
@@ -0,0 +1,10 @@
1
+ module GirFFI
2
+ # Wraps a GIFieldInfo struct.
3
+ # Represents a field of an IStructInfo or an IUnionInfo.
4
+ class IFieldInfo < IBaseInfo
5
+ def flags; Lib.g_field_info_get_flags @gobj; end
6
+ def size; Lib.g_field_info_get_size @gobj; end
7
+ def offset; Lib.g_field_info_get_offset @gobj; end
8
+ def type; ITypeInfo.wrap(Lib.g_field_info_get_type @gobj); end
9
+ end
10
+ end
@@ -0,0 +1,5 @@
1
+ module GirFFI
2
+ # Wraps a GIEnumInfo struct, if it represents a flag type.
3
+ class IFlagsInfo < IEnumInfo
4
+ end
5
+ end
@@ -0,0 +1,16 @@
1
+ module GirFFI
2
+ # Wraps a GIFunctioInfo struct.
3
+ # Represents a function.
4
+ class IFunctionInfo < ICallableInfo
5
+ def symbol; Lib.g_function_info_get_symbol @gobj; end
6
+ def flags; Lib.g_function_info_get_flags @gobj; end
7
+
8
+ #TODO: Use some sort of bitfield
9
+ def method?; flags & 1 != 0 end
10
+ def constructor?; flags & 2 != 0 end
11
+ def getter?; flags & 4 != 0 end
12
+ def setter?; flags & 8 != 0 end
13
+ def wraps_vfunc?; flags & 16 != 0 end
14
+ def throws?; flags & 32 != 0 end
15
+ end
16
+ end
@@ -0,0 +1,7 @@
1
+ module GirFFI
2
+ # Wraps a GIInterfaceInfo struct.
3
+ # Represents an interface.
4
+ # Not implemented yet.
5
+ class IInterfaceInfo < IRegisteredTypeInfo
6
+ end
7
+ end
@@ -0,0 +1,50 @@
1
+ module GirFFI
2
+ # Wraps a GIObjectInfo struct.
3
+ # Represents an object.
4
+ class IObjectInfo < IRegisteredTypeInfo
5
+ def type_name; Lib.g_object_info_get_type_name @gobj; end
6
+ def type_init; Lib.g_object_info_get_type_init @gobj; end
7
+ def abstract?; Lib.g_object_info_get_abstract @gobj; end
8
+ def parent; IObjectInfo.wrap(Lib.g_object_info_get_parent @gobj); end
9
+
10
+ def n_interfaces; Lib.g_object_info_get_n_interfaces @gobj; end
11
+ def interface(index); IInterfaceInfo.wrap(Lib.g_object_info_get_interface @gobj, index); end
12
+ ##
13
+ build_array_method :interfaces
14
+
15
+ def n_fields; Lib.g_object_info_get_n_fields @gobj; end
16
+ def field(index); IFieldInfo.wrap(Lib.g_object_info_get_field @gobj, index); end
17
+ ##
18
+ build_array_method :fields
19
+
20
+ def n_properties; Lib.g_object_info_get_n_properties @gobj; end
21
+ def property(index); IPropertyInfo.wrap(Lib.g_object_info_get_property @gobj, index); end
22
+ ##
23
+ build_array_method :properties, :property
24
+
25
+ def n_methods; Lib.g_object_info_get_n_methods @gobj; end
26
+ def method(index); IFunctionInfo.wrap(Lib.g_object_info_get_method @gobj, index); end
27
+ ##
28
+ build_array_method :methods
29
+
30
+ def find_method(name); IFunctionInfo.wrap(Lib.g_object_info_find_method @gobj, name); end
31
+
32
+ def n_signals; Lib.g_object_info_get_n_signals @gobj; end
33
+ def signal(index); ISignalInfo.wrap(Lib.g_object_info_get_signal @gobj, index); end
34
+ ##
35
+ build_array_method :signals
36
+
37
+ def n_vfuncs; Lib.g_object_info_get_n_vfuncs @gobj; end
38
+ def vfunc(index); IVFuncInfo.wrap(Lib.g_object_info_get_vfunc @gobj, index); end
39
+ def find_vfunc; IVFuncInfo.wrap(Lib.g_object_info_find_vfunc @gobj); end
40
+ ##
41
+ build_array_method :vfuncs
42
+
43
+ def n_constants; Lib.g_object_info_get_n_constants @gobj; end
44
+ def constant(index); IConstantInfo.wrap(Lib.g_object_info_get_constant @gobj, index); end
45
+ ##
46
+ build_array_method :constants
47
+
48
+ def class_struct; IStructInfo.wrap(Lib.g_object_info_get_class_struct @gobj); end
49
+ end
50
+ end
@@ -0,0 +1,7 @@
1
+ module GirFFI
2
+ # Wraps a GIPropertyInfo struct.
3
+ # Represents a property of an IObjectInfo or an IInterfaceInfo.
4
+ # Not implemented yet.
5
+ class IPropertyInfo < IBaseInfo
6
+ end
7
+ end
@@ -0,0 +1,8 @@
1
+ module GirFFI
2
+ # Wraps a GIRegisteredTypeInfo struct.
3
+ # Represents a registered type.
4
+ # Not implemented yet.
5
+ class IRegisteredTypeInfo < IBaseInfo
6
+ end
7
+ end
8
+
@@ -0,0 +1,108 @@
1
+ require 'singleton'
2
+ require 'gir_ffi/lib'
3
+ require 'gir_ffi/g_type'
4
+ require 'gir_ffi/g_error'
5
+ require 'gir_ffi/i_base_info'
6
+ require 'gir_ffi/i_callable_info'
7
+ require 'gir_ffi/i_callback_info'
8
+ require 'gir_ffi/i_function_info'
9
+ require 'gir_ffi/i_constant_info'
10
+ require 'gir_ffi/i_field_info'
11
+ require 'gir_ffi/i_registered_type_info'
12
+ require 'gir_ffi/i_interface_info'
13
+ require 'gir_ffi/i_property_info'
14
+ require 'gir_ffi/i_vfunc_info'
15
+ require 'gir_ffi/i_signal_info'
16
+ require 'gir_ffi/i_object_info'
17
+ require 'gir_ffi/i_struct_info'
18
+ require 'gir_ffi/i_value_info'
19
+ require 'gir_ffi/i_union_info'
20
+ require 'gir_ffi/i_enum_info'
21
+ require 'gir_ffi/i_flags_info'
22
+
23
+ module GirFFI
24
+ # The Gobject Introspection Repository. This class is the point of
25
+ # access to the introspection typelibs.
26
+ # This class wraps the GIRepository struct.
27
+ class IRepository
28
+ TYPEMAP = {
29
+ #:invalid,
30
+ :function => IFunctionInfo,
31
+ :callback => ICallbackInfo,
32
+ :struct => IStructInfo,
33
+ #:boxed => ,
34
+ :enum => IEnumInfo,
35
+ :flags => IFlagsInfo,
36
+ :object => IObjectInfo,
37
+ :interface => IInterfaceInfo,
38
+ :constant => IConstantInfo,
39
+ # :error_domain,
40
+ :union => IUnionInfo,
41
+ :value => IValueInfo,
42
+ :signal => ISignalInfo,
43
+ :vfunc => IVFuncInfo,
44
+ :property => IPropertyInfo,
45
+ :field => IFieldInfo,
46
+ :arg => IArgInfo,
47
+ :type => ITypeInfo,
48
+ #:unresolved
49
+ }
50
+
51
+ def initialize
52
+ GType.init
53
+ @gobj = Lib::g_irepository_get_default
54
+ end
55
+
56
+ include Singleton
57
+
58
+ def self.default
59
+ self.instance
60
+ end
61
+
62
+ def self.type_tag_to_string type
63
+ Lib.g_type_tag_to_string type
64
+ end
65
+
66
+ def n_infos namespace
67
+ Lib.g_irepository_get_n_infos @gobj, namespace
68
+ end
69
+
70
+ def require namespace, version
71
+ errpp = FFI::MemoryPointer.new(:pointer).write_pointer nil
72
+
73
+ Lib.g_irepository_require @gobj, namespace, version, 0, errpp
74
+
75
+ errp = errpp.read_pointer
76
+ raise GError.new(errp)[:message] unless errp.null?
77
+ end
78
+
79
+ def info namespace, index
80
+ ptr = Lib.g_irepository_get_info @gobj, namespace, index
81
+ return wrap ptr
82
+ end
83
+
84
+ def find_by_name namespace, name
85
+ ptr = Lib.g_irepository_find_by_name @gobj, namespace, name
86
+ return wrap ptr
87
+ end
88
+
89
+ def shared_library namespace
90
+ Lib.g_irepository_get_shared_library @gobj, namespace
91
+ end
92
+
93
+ def self.wrap_ibaseinfo_pointer ptr
94
+ return nil if ptr.null?
95
+
96
+ type = Lib.g_base_info_get_type ptr
97
+ klass = TYPEMAP[type]
98
+
99
+ return klass.wrap(ptr)
100
+ end
101
+
102
+ private
103
+
104
+ def wrap ptr
105
+ IRepository.wrap_ibaseinfo_pointer ptr
106
+ end
107
+ end
108
+ end