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,7 @@
1
+ module GirFFI
2
+ # Wraps a GISignalInfo struct.
3
+ # Represents a signal.
4
+ # Not implemented yet.
5
+ class ISignalInfo < IBaseInfo
6
+ end
7
+ end
@@ -0,0 +1,22 @@
1
+ module GirFFI
2
+ # Wraps a GIStructInfo struct.
3
+ # Represents a struct.
4
+ class IStructInfo < IRegisteredTypeInfo
5
+ def n_fields; Lib.g_struct_info_get_n_fields @gobj; end
6
+ def field(index); IFieldInfo.wrap(Lib.g_struct_info_get_field @gobj, index); end
7
+
8
+ ##
9
+ build_array_method :fields
10
+
11
+ def n_methods; Lib.g_struct_info_get_n_methods @gobj; end
12
+ def method(index); IFunctionInfo.wrap(Lib.g_struct_info_get_method @gobj, index); end
13
+
14
+ ##
15
+ build_array_method :methods
16
+
17
+ def find_method(name); IFunctionInfo.wrap(Lib.g_struct_info_find_method @gobj, name); end
18
+ def size; Lib.g_struct_info_get_size @gobj; end
19
+ def alignment; Lib.g_struct_info_get_alignment @gobj; end
20
+ def gtype_struct?; Lib.g_struct_info_is_gtype_struct @gobj; end
21
+ end
22
+ end
@@ -0,0 +1,25 @@
1
+ module GirFFI
2
+ # Wraps a GITypeInfo struct.
3
+ # Represents type information, direction, transfer etc.
4
+ class ITypeInfo < IBaseInfo
5
+ def pointer?; Lib.g_type_info_is_pointer @gobj; end
6
+ def tag; Lib.g_type_info_get_tag @gobj; end
7
+ def param_type(index); ITypeInfo.wrap(Lib.g_type_info_get_param_type @gobj, index); end
8
+ def interface
9
+ ptr = Lib.g_type_info_get_interface @gobj
10
+ IRepository.wrap_ibaseinfo_pointer ptr
11
+ end
12
+ def array_length; Lib.g_type_info_get_array_length @gobj; end
13
+ def array_fixed_size; Lib.g_type_info_get_array_fixed_size @gobj; end
14
+ def zero_terminated?; Lib.g_type_info_is_zero_terminated @gobj; end
15
+ def n_error_domains; Lib.g_type_info_get_n_error_domains @gobj; end
16
+ def error_domain(index); IErrorDomainInfo.wrap(Lib.g_type_info_get_error_domain @gobj, index); end
17
+ ##
18
+ build_array_method :error_domains
19
+
20
+ def name
21
+ raise "Should not call this for gir 0.6.5 ..."
22
+ end
23
+ end
24
+ end
25
+
@@ -0,0 +1,7 @@
1
+ module GirFFI
2
+ # Wraps a GIUnionInfo struct.
3
+ # Represents a union.
4
+ # Not implemented yet.
5
+ class IUnionInfo < IRegisteredTypeInfo
6
+ end
7
+ end
@@ -0,0 +1,8 @@
1
+ module GirFFI
2
+ # Wraps a GIValueInfo struct.
3
+ # Represents one of the enum values of an IEnumInfo.
4
+ class IValueInfo < IBaseInfo
5
+ def value; Lib.g_value_info_get_value @gobj; end
6
+ end
7
+ end
8
+
@@ -0,0 +1,7 @@
1
+ module GirFFI
2
+ # Wraps a GIVFuncInfo struct.
3
+ # Represents a virtual function.
4
+ # Not implemented yet.
5
+ class IVFuncInfo < IBaseInfo
6
+ end
7
+ end
@@ -0,0 +1,174 @@
1
+ require 'ffi'
2
+
3
+ module GirFFI
4
+ module Lib
5
+ extend FFI::Library
6
+ ffi_lib "girepository-1.0"
7
+
8
+ # IRepository
9
+ enum :IRepositoryLoadFlags, [:LAZY, (1<<0)]
10
+
11
+ attach_function :g_irepository_get_default, [], :pointer
12
+ attach_function :g_irepository_require,
13
+ [:pointer, :string, :string, :IRepositoryLoadFlags, :pointer],
14
+ :pointer
15
+ attach_function :g_irepository_get_n_infos, [:pointer, :string], :int
16
+ attach_function :g_irepository_get_info,
17
+ [:pointer, :string, :int], :pointer
18
+ attach_function :g_irepository_find_by_name,
19
+ [:pointer, :string, :string], :pointer
20
+ attach_function :g_irepository_get_shared_library,
21
+ [:pointer, :string], :string
22
+
23
+ # IBaseInfo
24
+ enum :IInfoType, [
25
+ :invalid,
26
+ :function,
27
+ :callback,
28
+ :struct,
29
+ :boxed,
30
+ :enum,
31
+ :flags,
32
+ :object,
33
+ :interface,
34
+ :constant,
35
+ :error_domain,
36
+ :union,
37
+ :value,
38
+ :signal,
39
+ :vfunc,
40
+ :property,
41
+ :field,
42
+ :arg,
43
+ :type,
44
+ :unresolved
45
+ ]
46
+
47
+ attach_function :g_base_info_get_type, [:pointer], :IInfoType
48
+ attach_function :g_base_info_get_name, [:pointer], :string
49
+ attach_function :g_base_info_get_namespace, [:pointer], :string
50
+ attach_function :g_base_info_is_deprecated, [:pointer], :bool
51
+ attach_function :g_base_info_equal, [:pointer, :pointer], :bool
52
+
53
+ # IFunctionInfo
54
+ attach_function :g_function_info_get_symbol, [:pointer], :string
55
+ # TODO: return type is bitfield
56
+ attach_function :g_function_info_get_flags, [:pointer], :int
57
+
58
+ # ICallableInfo
59
+ enum :ITransfer, [
60
+ :nothing,
61
+ :container,
62
+ :everything
63
+ ]
64
+
65
+ attach_function :g_callable_info_get_return_type, [:pointer], :pointer
66
+ attach_function :g_callable_info_get_caller_owns, [:pointer], :ITransfer
67
+ attach_function :g_callable_info_may_return_null, [:pointer], :bool
68
+ attach_function :g_callable_info_get_n_args, [:pointer], :int
69
+ attach_function :g_callable_info_get_arg, [:pointer, :int], :pointer
70
+
71
+ # IArgInfo
72
+ enum :IDirection, [
73
+ :in,
74
+ :out,
75
+ :inout
76
+ ]
77
+
78
+ enum :IScopeType, [
79
+ :invalid,
80
+ :call,
81
+ :async,
82
+ :notified
83
+ ]
84
+
85
+ attach_function :g_arg_info_get_direction, [:pointer], :IDirection
86
+ attach_function :g_arg_info_is_return_value, [:pointer], :bool
87
+ attach_function :g_arg_info_is_optional, [:pointer], :bool
88
+ attach_function :g_arg_info_may_be_null, [:pointer], :bool
89
+ attach_function :g_arg_info_get_ownership_transfer, [:pointer], :ITransfer
90
+ attach_function :g_arg_info_get_scope, [:pointer], :IScopeType
91
+ attach_function :g_arg_info_get_closure, [:pointer], :int
92
+ attach_function :g_arg_info_get_destroy, [:pointer], :int
93
+ attach_function :g_arg_info_get_type, [:pointer], :pointer
94
+
95
+ # The values of ITypeTag were changed in an incompatible way between
96
+ # gobject-introspection version 0.9.0 and 0.9.1. Therefore, we need to
97
+ # retrieve the correct values before declaring the ITypeTag enum.
98
+ attach_function :tmp_type_tag_to_string, :g_type_tag_to_string, [:int], :string
99
+ arr = (0..31).map { |i| [tmp_type_tag_to_string(i).to_sym, i] }.flatten
100
+ enum :ITypeTag, arr
101
+
102
+ # Now, attach g_type_tag_to_string again under its own name with an
103
+ # improved signature.
104
+ attach_function :g_type_tag_to_string, [:ITypeTag], :string
105
+
106
+ #define G_TYPE_TAG_IS_BASIC(tag) (tag < GI_TYPE_TAG_ARRAY)
107
+
108
+ attach_function :g_type_info_is_pointer, [:pointer], :bool
109
+ attach_function :g_type_info_get_tag, [:pointer], :ITypeTag
110
+ attach_function :g_type_info_get_param_type, [:pointer, :int], :pointer
111
+ attach_function :g_type_info_get_interface, [:pointer], :pointer
112
+ attach_function :g_type_info_get_array_length, [:pointer], :int
113
+ attach_function :g_type_info_get_array_fixed_size, [:pointer], :int
114
+ attach_function :g_type_info_is_zero_terminated, [:pointer], :bool
115
+ attach_function :g_type_info_get_n_error_domains, [:pointer], :int
116
+ attach_function :g_type_info_get_error_domain, [:pointer, :int], :pointer
117
+
118
+ # IStructInfo
119
+ attach_function :g_struct_info_get_n_fields, [:pointer], :int
120
+ attach_function :g_struct_info_get_field, [:pointer, :int], :pointer
121
+ attach_function :g_struct_info_get_n_methods, [:pointer], :int
122
+ attach_function :g_struct_info_get_method, [:pointer, :int], :pointer
123
+ attach_function :g_struct_info_find_method, [:pointer, :string], :pointer
124
+ attach_function :g_struct_info_get_size, [:pointer], :int
125
+ attach_function :g_struct_info_get_alignment, [:pointer], :int
126
+ attach_function :g_struct_info_is_gtype_struct, [:pointer], :bool
127
+
128
+ # IValueInfo
129
+ attach_function :g_value_info_get_value, [:pointer], :long
130
+
131
+ # IFieldInfo
132
+ enum :IFieldInfoFlags, [
133
+ :readable, (1 << 0),
134
+ :writable, (1 << 1)
135
+ ]
136
+ attach_function :g_field_info_get_flags, [:pointer], :IFieldInfoFlags
137
+ attach_function :g_field_info_get_size, [:pointer], :int
138
+ attach_function :g_field_info_get_offset, [:pointer], :int
139
+ attach_function :g_field_info_get_type, [:pointer], :pointer
140
+
141
+ # IUnionInfo
142
+ # IStructInfo
143
+ # IRegisteredTypeInfo
144
+
145
+ # IEnumInfo
146
+ attach_function :g_enum_info_get_storage_type, [:pointer], :ITypeTag
147
+ attach_function :g_enum_info_get_n_values, [:pointer], :int
148
+ attach_function :g_enum_info_get_value, [:pointer, :int], :pointer
149
+
150
+ # IObjectInfo
151
+ attach_function :g_object_info_get_type_name, [:pointer], :string
152
+ attach_function :g_object_info_get_type_init, [:pointer], :string
153
+ attach_function :g_object_info_get_abstract, [:pointer], :bool
154
+ attach_function :g_object_info_get_parent, [:pointer], :pointer
155
+ attach_function :g_object_info_get_n_interfaces, [:pointer], :int
156
+ attach_function :g_object_info_get_interface, [:pointer, :int], :pointer
157
+ attach_function :g_object_info_get_n_fields, [:pointer], :int
158
+ attach_function :g_object_info_get_field, [:pointer, :int], :pointer
159
+ attach_function :g_object_info_get_n_properties, [:pointer], :int
160
+ attach_function :g_object_info_get_property, [:pointer, :int], :pointer
161
+ attach_function :g_object_info_get_n_methods, [:pointer], :int
162
+ attach_function :g_object_info_get_method, [:pointer, :int], :pointer
163
+ attach_function :g_object_info_find_method, [:pointer, :string], :pointer
164
+ attach_function :g_object_info_get_n_signals, [:pointer], :int
165
+ attach_function :g_object_info_get_signal, [:pointer, :int], :pointer
166
+ attach_function :g_object_info_get_n_vfuncs, [:pointer], :int
167
+ attach_function :g_object_info_get_vfunc, [:pointer, :int], :pointer
168
+ attach_function :g_object_info_find_vfunc, [:pointer, :string], :pointer
169
+ attach_function :g_object_info_get_n_constants, [:pointer], :int
170
+ attach_function :g_object_info_get_constant, [:pointer, :int], :pointer
171
+ attach_function :g_object_info_get_class_struct, [:pointer], :pointer
172
+
173
+ end
174
+ end
@@ -0,0 +1,11 @@
1
+ require 'ffi'
2
+
3
+ module GirFFI
4
+ module LibC
5
+ extend FFI::Library
6
+ ffi_lib FFI::Library::LIBC
7
+
8
+ attach_function :malloc, [:size_t], :pointer
9
+ attach_function :free, [:pointer], :void
10
+ end
11
+ end
@@ -0,0 +1,62 @@
1
+ module GirFFI
2
+ # Base class for builders of #method_missing definitions.
3
+ class MethodMissingDefinitionBuilder
4
+ def initialize lib, namespace
5
+ @lib = lib
6
+ @namespace = namespace
7
+ end
8
+
9
+ def generate
10
+ args = arguments.map {|arg| "\"#{arg}\""}
11
+
12
+ return <<-CODE
13
+ def #{slf}method_missing method, *arguments, &block
14
+ result = GirFFI::Builder.#{fn} #{args.join ', '}, #{libs.join ', '}, self, method.to_s
15
+ return super unless result
16
+ if block.nil?
17
+ self.send method, *arguments
18
+ else
19
+ self.send method, *arguments, &block
20
+ end
21
+ end
22
+ CODE
23
+ end
24
+ end
25
+
26
+ # Builds a #method_missing for a module. This method_missing will be
27
+ # called for missing module methods; these modules are not meant for
28
+ # #include'ing.
29
+ class ModuleMethodMissingDefinitionBuilder < MethodMissingDefinitionBuilder
30
+ private
31
+
32
+ def slf; "self."; end
33
+ def fn; "setup_function"; end
34
+ def arguments; [@namespace]; end
35
+ def libs; [@lib]; end
36
+ end
37
+
38
+ # Builds a #method_missing for missing instance methods.
39
+ class InstanceMethodMissingDefinitionBuilder < MethodMissingDefinitionBuilder
40
+ def initialize lib, modul, namespace, classname
41
+ super lib, namespace
42
+ @classname = classname
43
+ @module = modul
44
+ end
45
+
46
+ private
47
+
48
+ def slf; ""; end
49
+ def fn; "setup_method"; end
50
+ def arguments; [@namespace, @classname]; end
51
+ def libs; [@lib, @module]; end
52
+ end
53
+
54
+ # Builds a #method_missing for missing class methods.
55
+ class ClassMethodMissingDefinitionBuilder < InstanceMethodMissingDefinitionBuilder
56
+ private
57
+
58
+ def slf; "self."; end
59
+ end
60
+
61
+ end
62
+
@@ -0,0 +1,66 @@
1
+ require 'gir_ffi/builder_helper'
2
+
3
+ module GirFFI
4
+ # Builds a module based on information found in the introspection
5
+ # repository.
6
+ class ModuleBuilder
7
+
8
+ def initialize namespace, box
9
+ @namespace = namespace
10
+ @box = box
11
+ end
12
+
13
+ def generate
14
+ build_module
15
+ end
16
+
17
+ private
18
+
19
+ def build_module
20
+ IRepository.default.require @namespace, nil
21
+ setup_module
22
+ setup_lib_for_ffi
23
+ unless @module.respond_to? :method_missing
24
+ @module.class_eval module_method_missing_definition
25
+ @module.class_eval const_missing_definition
26
+ end
27
+ @module
28
+ end
29
+
30
+ def setup_module
31
+ if @box.nil?
32
+ boxm = ::Object
33
+ else
34
+ boxm = BuilderHelper.get_or_define_module ::Object, @box.to_s
35
+ end
36
+ @module = BuilderHelper.get_or_define_module boxm, @namespace.to_s
37
+ end
38
+
39
+ def setup_lib_for_ffi
40
+ @lib = BuilderHelper.get_or_define_module @module, :Lib
41
+
42
+ unless (class << @lib; self.include? FFI::Library; end)
43
+ @lib.extend FFI::Library
44
+ libs = IRepository.default.shared_library(@namespace).split(/,/)
45
+ @lib.ffi_lib(*libs)
46
+ end
47
+
48
+ BuilderHelper.optionally_define_constant(@lib, :CALLBACKS) { [] }
49
+ end
50
+
51
+ def module_method_missing_definition
52
+ ModuleMethodMissingDefinitionBuilder.new(@lib, @namespace).generate
53
+ end
54
+
55
+ def const_missing_definition
56
+ box = @box.nil? ? "nil" : "\"#{@box}\""
57
+ return <<-CODE
58
+ def self.const_missing classname
59
+ info = IRepository.default.find_by_name "#{@namespace}", classname.to_s
60
+ return super if info.nil?
61
+ return GirFFI::Builder.build_class "#{@namespace}", classname.to_s, #{box}
62
+ end
63
+ CODE
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,12 @@
1
+ GirFFI::Builder.setup_function "Gtk", Gtk::Lib, Gtk, "init"
2
+ module Gtk
3
+ class << self
4
+ alias _base_init init
5
+ def init
6
+ (my_len, my_args) = _base_init ARGV.length + 1, [$0, *ARGV]
7
+ my_args.shift
8
+ ARGV.replace my_args
9
+ end
10
+ private :_base_init
11
+ end
12
+ end
@@ -0,0 +1,4 @@
1
+ module GirFFI
2
+ VERSION = "0.0.1"
3
+ end
4
+
@@ -0,0 +1,87 @@
1
+ # The following code is copied straight from Bones 2.5.1
2
+ #
3
+ require 'pp'
4
+ require 'stringio'
5
+
6
+ module Bones
7
+
8
+ # Helper module that will pretty print OpenStruct objects. It is used mainly
9
+ # for debugging the Mr Bones project open struct.
10
+ #
11
+ module Debug
12
+
13
+ # :stopdoc:
14
+ KEY_LENGTH = 20
15
+ VAR_LENGTH = 78 - 6 - KEY_LENGTH
16
+ SEP = "\n" + ' '*(KEY_LENGTH+6)
17
+ FMT = " %-#{KEY_LENGTH}s => %s"
18
+ # :startdoc:
19
+
20
+ # Print all the keys for the given _ostruct_ to stdout. If a _prefix_ is
21
+ # given, then the open struct keys will be prefixed with this string.
22
+ #
23
+ def self.show( ostruct, prefix = '' )
24
+ sio = StringIO.new
25
+
26
+ h = ostruct.instance_variable_get(:@table)
27
+ h.keys.map {|k| k.to_s}.sort.each do |k|
28
+ sio.seek 0
29
+ sio.truncate 0
30
+ next if k =~ %r/^_/o
31
+
32
+ val = h[k.to_sym]
33
+ if val.instance_of?(OpenStruct)
34
+ self.show(val, prefix + k + '.')
35
+ else
36
+ PP.pp(val, sio, VAR_LENGTH)
37
+ sio.seek 0
38
+ val = sio.read
39
+ val = val.split("\n").join(SEP)
40
+
41
+ key = prefix + k
42
+ key[(KEY_LENGTH-3)..-1] = '...' if key.length > KEY_LENGTH
43
+ puts(FMT % [key, val])
44
+ end
45
+ end
46
+ end
47
+
48
+ # Print a single attribute from the given _ostruct_ to stdout. The
49
+ # attributed is identified by the given _key_.
50
+ #
51
+ def self.show_attr( ostruct, key )
52
+ sio = StringIO.new
53
+
54
+ key = key.dup if key.frozen?
55
+ val = key.split('.').inject(ostruct) {|os,k| os.send(k)}
56
+
57
+ if val.instance_of?(OpenStruct)
58
+ self.show(val, key + '.')
59
+ else
60
+ PP.pp(val, sio, VAR_LENGTH)
61
+ sio.seek 0
62
+ val = sio.read
63
+ val = val.split("\n").join(SEP)
64
+
65
+ key[(KEY_LENGTH-3)..-1] = '...' if key.length > KEY_LENGTH
66
+ puts(FMT % [key, val])
67
+ end
68
+ end
69
+
70
+ end # module Debug
71
+ end # module Bones
72
+
73
+ namespace :bones do
74
+
75
+ desc 'Show the PROJ open struct'
76
+ task :debug do |t|
77
+ atr = if t.application.top_level_tasks.length == 2
78
+ t.application.top_level_tasks.pop
79
+ end
80
+
81
+ if atr then Bones::Debug.show_attr(PROJ, atr)
82
+ else Bones::Debug.show PROJ end
83
+ end
84
+
85
+ end # namespace :bones
86
+
87
+ # EOF