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