gir_ffi 0.0.1

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 (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