gir_ffi 0.0.1 → 0.0.2
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.
- data/History.txt +6 -2
- data/lib/gir_ffi/arg_helper.rb +8 -2
- data/lib/gir_ffi/base.rb +16 -4
- data/lib/gir_ffi/builder.rb +71 -56
- data/lib/gir_ffi/class_builder.rb +13 -21
- data/lib/gir_ffi/function_definition_builder.rb +1 -0
- data/lib/gir_ffi/i_base_info.rb +7 -3
- data/lib/gir_ffi/method_missing_definition_builder.rb +4 -7
- data/lib/gir_ffi/module_builder.rb +3 -10
- data/lib/gir_ffi/overrides/gtk.rb +1 -1
- data/test/base_test.rb +72 -0
- data/test/builder_test.rb +102 -108
- data/test/constructor_definition_builder_test.rb +1 -1
- data/test/everything_test.rb +78 -0
- data/test/function_definition_builder_test.rb +1 -2
- data/test/gtk_overrides_test.rb +6 -1
- data/test/test_helper.rb +6 -0
- metadata +8 -5
- data/lib/gir_ffi/class_base.rb +0 -11
data/History.txt
CHANGED
data/lib/gir_ffi/arg_helper.rb
CHANGED
@@ -37,7 +37,7 @@ module GirFFI
|
|
37
37
|
value
|
38
38
|
end
|
39
39
|
|
40
|
-
# Converts an outptr to a string array, then frees
|
40
|
+
# Converts an outptr to a string array, then frees pointers.
|
41
41
|
def self.outptr_to_string_array ptr, size
|
42
42
|
return nil if ptr.nil?
|
43
43
|
|
@@ -49,7 +49,13 @@ module GirFFI
|
|
49
49
|
ptrs = block.read_array_of_pointer(size)
|
50
50
|
LibC.free block
|
51
51
|
|
52
|
-
ptrs.map
|
52
|
+
ptrs.map do |p|
|
53
|
+
if p.null?
|
54
|
+
nil
|
55
|
+
else
|
56
|
+
p.read_string.tap { LibC.free p }
|
57
|
+
end
|
58
|
+
end
|
53
59
|
end
|
54
60
|
|
55
61
|
def self.mapped_callback_args prc=nil, &block
|
data/lib/gir_ffi/base.rb
CHANGED
@@ -1,23 +1,35 @@
|
|
1
1
|
require 'forwardable'
|
2
2
|
module GirFFI
|
3
|
+
# Base class for all generated classes. Contains code for dealing with
|
4
|
+
# the generated Struct classes.
|
3
5
|
class Base
|
4
6
|
extend Forwardable
|
5
7
|
def_delegators :@struct, :[], :[]=, :to_ptr
|
6
8
|
|
7
|
-
def initialize(
|
8
|
-
@struct =
|
9
|
-
self.ffi_structure.new :
|
10
|
-
self.ffi_structure.new(ptr)
|
9
|
+
def initialize(*args)
|
10
|
+
@struct = ffi_structure.new(*args)
|
11
11
|
end
|
12
12
|
|
13
13
|
def ffi_structure
|
14
14
|
self.class.ffi_structure
|
15
15
|
end
|
16
16
|
|
17
|
+
def _fake_missing *args, &block
|
18
|
+
method_missing method_name.to_sym, *args, &block
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def method_name
|
24
|
+
caller[0].gsub(/.*`(.*)'/, '\1')
|
25
|
+
end
|
26
|
+
|
17
27
|
class << self
|
18
28
|
def ffi_structure
|
19
29
|
self.const_get(:Struct)
|
20
30
|
end
|
31
|
+
alias_method :_real_new, :new
|
32
|
+
undef new
|
21
33
|
end
|
22
34
|
end
|
23
35
|
end
|
data/lib/gir_ffi/builder.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
require 'gir_ffi/class_base'
|
2
1
|
require 'gir_ffi/arg_helper'
|
3
2
|
require 'gir_ffi/function_definition_builder'
|
4
3
|
require 'gir_ffi/constructor_definition_builder'
|
@@ -13,26 +12,65 @@ module GirFFI
|
|
13
12
|
# introspection repository. Call its build_module and build_class methods
|
14
13
|
# to create the modules and classes used in your program.
|
15
14
|
module Builder
|
16
|
-
def self.build_class namespace, classname
|
17
|
-
ClassBuilder.new(namespace, classname
|
15
|
+
def self.build_class namespace, classname
|
16
|
+
ClassBuilder.new(namespace, classname).generate
|
18
17
|
end
|
19
18
|
|
20
|
-
def self.build_module namespace
|
21
|
-
ModuleBuilder.new(namespace
|
19
|
+
def self.build_module namespace
|
20
|
+
ModuleBuilder.new(namespace).generate
|
22
21
|
end
|
23
22
|
|
24
|
-
|
25
|
-
def self.setup_method namespace, classname, lib, modul, klass, method
|
23
|
+
def self.setup_method namespace, classname, method
|
26
24
|
go = method_introspection_data namespace, classname, method.to_s
|
27
25
|
|
28
|
-
|
26
|
+
return false if go.nil?
|
27
|
+
return false if go.type != :function
|
28
|
+
|
29
|
+
klass = build_class namespace, classname
|
30
|
+
modul = build_module namespace
|
31
|
+
lib = modul.const_get(:Lib)
|
32
|
+
|
33
|
+
attach_ffi_function lib, go
|
34
|
+
|
35
|
+
meta = (class << klass; self; end)
|
36
|
+
meta.class_eval function_definition(go, lib)
|
37
|
+
|
38
|
+
true
|
29
39
|
end
|
30
40
|
|
31
|
-
|
32
|
-
def self.setup_function namespace, lib, modul, method
|
41
|
+
def self.setup_function namespace, method
|
33
42
|
go = function_introspection_data namespace, method.to_s
|
34
43
|
|
35
|
-
|
44
|
+
return false if go.nil?
|
45
|
+
return false if go.type != :function
|
46
|
+
|
47
|
+
modul = build_module namespace
|
48
|
+
lib = modul.const_get(:Lib)
|
49
|
+
|
50
|
+
attach_ffi_function lib, go
|
51
|
+
|
52
|
+
meta = (class << modul; self; end)
|
53
|
+
meta.class_eval function_definition(go, lib)
|
54
|
+
|
55
|
+
true
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.setup_instance_method namespace, classname, method
|
59
|
+
go = method_introspection_data namespace, classname, method.to_s
|
60
|
+
|
61
|
+
return false if go.nil?
|
62
|
+
return false if go.type != :function
|
63
|
+
|
64
|
+
klass = build_class namespace, classname
|
65
|
+
modul = build_module namespace
|
66
|
+
lib = modul.const_get(:Lib)
|
67
|
+
|
68
|
+
attach_ffi_function lib, go
|
69
|
+
|
70
|
+
klass.class_eval "undef #{method}"
|
71
|
+
klass.class_eval function_definition(go, lib)
|
72
|
+
|
73
|
+
true
|
36
74
|
end
|
37
75
|
|
38
76
|
# All methods below will be made private at the end.
|
@@ -57,17 +95,17 @@ module GirFFI
|
|
57
95
|
return objectinfo.find_method method
|
58
96
|
end
|
59
97
|
|
60
|
-
def self.attach_ffi_function
|
98
|
+
def self.attach_ffi_function lib, info
|
61
99
|
sym = info.symbol
|
62
|
-
argtypes = ffi_function_argument_types
|
63
|
-
rt = ffi_function_return_type
|
100
|
+
argtypes = ffi_function_argument_types info
|
101
|
+
rt = ffi_function_return_type info
|
64
102
|
|
65
103
|
lib.attach_function sym, argtypes, rt
|
66
104
|
end
|
67
105
|
|
68
|
-
def self.ffi_function_argument_types
|
106
|
+
def self.ffi_function_argument_types info
|
69
107
|
types = info.args.map do |a|
|
70
|
-
iarginfo_to_ffitype
|
108
|
+
iarginfo_to_ffitype a
|
71
109
|
end
|
72
110
|
if info.type == :function
|
73
111
|
types.unshift :pointer if info.method?
|
@@ -75,17 +113,11 @@ module GirFFI
|
|
75
113
|
types
|
76
114
|
end
|
77
115
|
|
78
|
-
def self.ffi_function_return_type
|
79
|
-
itypeinfo_to_ffitype
|
80
|
-
end
|
81
|
-
|
82
|
-
def self.define_ffi_types modul, lib, info, box
|
83
|
-
info.args.each do |arg|
|
84
|
-
type = iarginfo_to_ffitype modul, lib, arg, box
|
85
|
-
end
|
116
|
+
def self.ffi_function_return_type info
|
117
|
+
itypeinfo_to_ffitype info.return_type
|
86
118
|
end
|
87
119
|
|
88
|
-
def self.itypeinfo_to_ffitype
|
120
|
+
def self.itypeinfo_to_ffitype info
|
89
121
|
if info.pointer?
|
90
122
|
return :string if info.tag == :utf8
|
91
123
|
return :pointer
|
@@ -95,65 +127,48 @@ module GirFFI
|
|
95
127
|
interface = info.interface
|
96
128
|
case interface.type
|
97
129
|
when :object, :struct, :flags, :enum
|
98
|
-
return build_class interface.namespace, interface.name
|
130
|
+
return build_class interface.namespace, interface.name
|
99
131
|
when :callback
|
100
|
-
return build_callback
|
132
|
+
return build_callback interface
|
101
133
|
else
|
102
134
|
raise NotImplementedError
|
103
135
|
end
|
104
136
|
when :boolean
|
105
137
|
return :bool
|
138
|
+
when :GType
|
139
|
+
return :int32
|
106
140
|
else
|
107
141
|
return info.tag
|
108
142
|
end
|
109
143
|
end
|
110
144
|
|
111
|
-
def self.iarginfo_to_ffitype
|
145
|
+
def self.iarginfo_to_ffitype info
|
112
146
|
return :pointer if info.direction == :inout
|
113
|
-
return itypeinfo_to_ffitype
|
147
|
+
return itypeinfo_to_ffitype info.type
|
114
148
|
end
|
115
149
|
|
116
|
-
def self.build_callback
|
150
|
+
def self.build_callback interface
|
151
|
+
modul = build_module interface.namespace
|
152
|
+
lib = modul.const_get(:Lib)
|
153
|
+
|
117
154
|
sym = interface.name.to_sym
|
118
155
|
|
119
156
|
# FIXME: Rescue is ugly here.
|
120
157
|
ft = lib.find_type sym rescue nil
|
121
158
|
if ft.nil?
|
122
|
-
args = ffi_function_argument_types
|
123
|
-
ret = ffi_function_return_type
|
159
|
+
args = ffi_function_argument_types interface
|
160
|
+
ret = ffi_function_return_type interface
|
124
161
|
lib.callback sym, args, ret
|
125
162
|
end
|
126
163
|
sym
|
127
164
|
end
|
128
165
|
|
129
|
-
def self.setup_function_or_method klass, modul, lib, go
|
130
|
-
return false if go.nil?
|
131
|
-
return false if go.type != :function
|
132
|
-
|
133
|
-
box = get_box modul
|
134
|
-
|
135
|
-
define_ffi_types modul, lib, go, box
|
136
|
-
attach_ffi_function modul, lib, go, box
|
137
|
-
|
138
|
-
(class << klass; self; end).class_eval function_definition(go, lib)
|
139
|
-
true
|
140
|
-
end
|
141
|
-
|
142
|
-
# TODO: This is a weird way to get back the box.
|
143
|
-
def self.get_box modul
|
144
|
-
name = modul.to_s
|
145
|
-
if name =~ /::/
|
146
|
-
return Kernel.const_get(name.split('::')[0])
|
147
|
-
else
|
148
|
-
return nil
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
166
|
# Set up method access.
|
153
167
|
(self.public_methods - Module.public_methods).each do |m|
|
154
168
|
private_class_method m.to_sym
|
155
169
|
end
|
156
|
-
public_class_method :build_module, :build_class
|
170
|
+
public_class_method :build_module, :build_class
|
171
|
+
public_class_method :setup_method, :setup_function, :setup_instance_method
|
157
172
|
public_class_method :itypeinfo_to_ffitype
|
158
173
|
end
|
159
174
|
end
|
@@ -2,10 +2,9 @@ module GirFFI
|
|
2
2
|
# Builds a class based on information found in the introspection
|
3
3
|
# repository.
|
4
4
|
class ClassBuilder
|
5
|
-
def initialize namespace, classname
|
5
|
+
def initialize namespace, classname
|
6
6
|
@namespace = namespace
|
7
7
|
@classname = classname
|
8
|
-
@box = box
|
9
8
|
end
|
10
9
|
|
11
10
|
def generate
|
@@ -41,14 +40,14 @@ module GirFFI
|
|
41
40
|
def get_superclass
|
42
41
|
@parent = @info.type == :object ? @info.parent : nil
|
43
42
|
if @parent
|
44
|
-
@superclass = Builder.build_class @parent.namespace, @parent.name
|
43
|
+
@superclass = Builder.build_class @parent.namespace, @parent.name
|
45
44
|
else
|
46
45
|
@superclass = GirFFI::Base
|
47
46
|
end
|
48
47
|
end
|
49
48
|
|
50
49
|
def instantiate_module
|
51
|
-
@module = Builder.build_module @namespace
|
50
|
+
@module = Builder.build_module @namespace
|
52
51
|
@lib = @module.const_get :Lib
|
53
52
|
end
|
54
53
|
|
@@ -60,23 +59,8 @@ module GirFFI
|
|
60
59
|
|
61
60
|
def setup_class
|
62
61
|
setup_method_missing
|
63
|
-
setup_base
|
64
62
|
setup_layout
|
65
|
-
|
66
|
-
end
|
67
|
-
|
68
|
-
def setup_base
|
69
|
-
return if @parent
|
70
|
-
class << @klass
|
71
|
-
self.class_eval { alias_method :_real_new, :new }
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
def setup_constructor
|
76
|
-
ctor = @info.find_method 'new'
|
77
|
-
if not ctor.nil? and ctor.constructor?
|
78
|
-
Builder.setup_function_or_method @klass, @module, @lib, ctor
|
79
|
-
end
|
63
|
+
alias_instance_methods
|
80
64
|
end
|
81
65
|
|
82
66
|
def setup_method_missing
|
@@ -89,7 +73,7 @@ module GirFFI
|
|
89
73
|
@info.fields.each do |f|
|
90
74
|
layoutspec << f.name.to_sym
|
91
75
|
|
92
|
-
ffitype = Builder.itypeinfo_to_ffitype
|
76
|
+
ffitype = Builder.itypeinfo_to_ffitype f.type
|
93
77
|
if ffitype.kind_of?(Class) and BuilderHelper.const_defined_for ffitype, :Struct
|
94
78
|
ffitype = ffitype.const_get :Struct
|
95
79
|
end
|
@@ -101,6 +85,14 @@ module GirFFI
|
|
101
85
|
@structklass.class_eval { layout(*layoutspec) }
|
102
86
|
end
|
103
87
|
|
88
|
+
def alias_instance_methods
|
89
|
+
@info.methods.each do |m|
|
90
|
+
@klass.class_eval do
|
91
|
+
alias_method m.name.to_sym, :_fake_missing
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
104
96
|
def instance_method_missing_definition
|
105
97
|
InstanceMethodMissingDefinitionBuilder.new(@lib, @module, @namespace, @classname).generate
|
106
98
|
end
|
@@ -108,6 +108,7 @@ module GirFFI
|
|
108
108
|
|
109
109
|
if tag == :interface
|
110
110
|
interface = type.interface
|
111
|
+
GirFFI::Builder.build_class interface.namespace, interface.name
|
111
112
|
@retvals << "#{interface.namespace}::#{interface.name}._real_new(#{retval})"
|
112
113
|
else
|
113
114
|
@retvals << retval
|
data/lib/gir_ffi/i_base_info.rb
CHANGED
@@ -1,10 +1,14 @@
|
|
1
|
-
require 'gir_ffi/class_base'
|
2
|
-
|
3
1
|
module GirFFI
|
4
2
|
# Wraps GIBaseInfo struct, the base \type for all info types.
|
5
3
|
# Decendant types will be implemented as needed.
|
6
4
|
class IBaseInfo
|
7
|
-
|
5
|
+
def initialize ptr
|
6
|
+
@gobj = ptr
|
7
|
+
end
|
8
|
+
|
9
|
+
def to_ptr
|
10
|
+
@gobj
|
11
|
+
end
|
8
12
|
|
9
13
|
# This is a helper method to construct a method returning an array, out
|
10
14
|
# of the methods returning their number and the individual elements.
|
@@ -11,13 +11,9 @@ module GirFFI
|
|
11
11
|
|
12
12
|
return <<-CODE
|
13
13
|
def #{slf}method_missing method, *arguments, &block
|
14
|
-
result = GirFFI::Builder.#{fn} #{args.join ', '},
|
14
|
+
result = GirFFI::Builder.#{fn} #{args.join ', '}, method.to_s
|
15
15
|
return super unless result
|
16
|
-
|
17
|
-
self.send method, *arguments
|
18
|
-
else
|
19
|
-
self.send method, *arguments, &block
|
20
|
-
end
|
16
|
+
self.send method, *arguments, &block
|
21
17
|
end
|
22
18
|
CODE
|
23
19
|
end
|
@@ -46,7 +42,7 @@ module GirFFI
|
|
46
42
|
private
|
47
43
|
|
48
44
|
def slf; ""; end
|
49
|
-
def fn; "
|
45
|
+
def fn; "setup_instance_method"; end
|
50
46
|
def arguments; [@namespace, @classname]; end
|
51
47
|
def libs; [@lib, @module]; end
|
52
48
|
end
|
@@ -56,6 +52,7 @@ module GirFFI
|
|
56
52
|
private
|
57
53
|
|
58
54
|
def slf; "self."; end
|
55
|
+
def fn; "setup_method"; end
|
59
56
|
end
|
60
57
|
|
61
58
|
end
|
@@ -5,9 +5,8 @@ module GirFFI
|
|
5
5
|
# repository.
|
6
6
|
class ModuleBuilder
|
7
7
|
|
8
|
-
def initialize namespace
|
8
|
+
def initialize namespace
|
9
9
|
@namespace = namespace
|
10
|
-
@box = box
|
11
10
|
end
|
12
11
|
|
13
12
|
def generate
|
@@ -28,12 +27,7 @@ module GirFFI
|
|
28
27
|
end
|
29
28
|
|
30
29
|
def setup_module
|
31
|
-
|
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
|
30
|
+
@module = BuilderHelper.get_or_define_module ::Object, @namespace.to_s
|
37
31
|
end
|
38
32
|
|
39
33
|
def setup_lib_for_ffi
|
@@ -53,12 +47,11 @@ module GirFFI
|
|
53
47
|
end
|
54
48
|
|
55
49
|
def const_missing_definition
|
56
|
-
box = @box.nil? ? "nil" : "\"#{@box}\""
|
57
50
|
return <<-CODE
|
58
51
|
def self.const_missing classname
|
59
52
|
info = IRepository.default.find_by_name "#{@namespace}", classname.to_s
|
60
53
|
return super if info.nil?
|
61
|
-
return GirFFI::Builder.build_class "#{@namespace}", classname.to_s
|
54
|
+
return GirFFI::Builder.build_class "#{@namespace}", classname.to_s
|
62
55
|
end
|
63
56
|
CODE
|
64
57
|
end
|
data/test/base_test.rb
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
require File.expand_path('test_helper.rb', File.dirname(__FILE__))
|
2
|
+
require 'gir_ffi/base'
|
3
|
+
|
4
|
+
class BaseTest < Test::Unit::TestCase
|
5
|
+
context "A class derived from GirFFI::Base" do
|
6
|
+
setup do
|
7
|
+
@klass = Class.new(GirFFI::Base) do
|
8
|
+
# Boilerplate to make regular #new work again.
|
9
|
+
def initialize; end
|
10
|
+
def self.new; self._real_new; end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
should "be able to use method_name to get the names of its methods" do
|
15
|
+
@klass.class_eval do
|
16
|
+
def this_is_my_name
|
17
|
+
method_name
|
18
|
+
end
|
19
|
+
end
|
20
|
+
assert_equal "this_is_my_name", @klass.new.this_is_my_name
|
21
|
+
end
|
22
|
+
|
23
|
+
context "its #_fake_missing method" do
|
24
|
+
should "not be missing" do
|
25
|
+
assert @klass.new.respond_to? :_fake_missing
|
26
|
+
end
|
27
|
+
|
28
|
+
should "call method_missing" do
|
29
|
+
@klass.class_eval do
|
30
|
+
def method_missing method, *args
|
31
|
+
method
|
32
|
+
end
|
33
|
+
end
|
34
|
+
assert_equal :_fake_missing, @klass.new._fake_missing
|
35
|
+
end
|
36
|
+
|
37
|
+
should "pass on its arguments" do
|
38
|
+
@klass.class_eval do
|
39
|
+
def method_missing method, *args
|
40
|
+
args.join(', ')
|
41
|
+
end
|
42
|
+
end
|
43
|
+
assert_equal "a, b", @klass.new._fake_missing("a", "b")
|
44
|
+
end
|
45
|
+
|
46
|
+
should "pass on a given block" do
|
47
|
+
@klass.class_eval do
|
48
|
+
def method_missing method, *args
|
49
|
+
yield if block_given?
|
50
|
+
end
|
51
|
+
end
|
52
|
+
assert_equal :called, @klass.new._fake_missing { :called }
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
should "be able to use alias_method to create a self-defining method" do
|
57
|
+
@klass.class_eval do
|
58
|
+
def method_missing method, *args
|
59
|
+
self.class.class_eval "
|
60
|
+
undef #{method}
|
61
|
+
def #{method}
|
62
|
+
:redefined
|
63
|
+
end
|
64
|
+
"
|
65
|
+
self.send method
|
66
|
+
end
|
67
|
+
alias_method :new_method, :_fake_missing
|
68
|
+
end
|
69
|
+
assert_equal :redefined, @klass.new.new_method
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
data/test/builder_test.rb
CHANGED
@@ -1,105 +1,105 @@
|
|
1
1
|
require File.expand_path('test_helper.rb', File.dirname(__FILE__))
|
2
|
-
require 'gir_ffi
|
2
|
+
require 'gir_ffi'
|
3
3
|
|
4
4
|
class BuilderTest < Test::Unit::TestCase
|
5
5
|
context "The GirFFI::Builder module" do
|
6
6
|
# TODO: Use gir's sample Everything library for testing instead.
|
7
7
|
context "building GObject::Object" do
|
8
8
|
setup do
|
9
|
-
|
9
|
+
cleanup_module :GObject
|
10
|
+
GirFFI::Builder.build_class 'GObject', 'Object'
|
10
11
|
end
|
11
12
|
|
12
13
|
should "create a method_missing method for the class" do
|
13
|
-
ms =
|
14
|
+
ms = GObject::Object.instance_methods(false).map(&:to_sym)
|
14
15
|
assert_contains ms, :method_missing
|
15
16
|
end
|
16
17
|
|
17
18
|
should "create a Lib module in the parent namespace ready to attach functions from gobject-2.0" do
|
18
19
|
gir = GirFFI::IRepository.default
|
19
20
|
expected = gir.shared_library 'GObject'
|
20
|
-
assert_same_elements [*expected],
|
21
|
+
assert_same_elements [*expected], GObject::Lib.ffi_libraries.map(&:name)
|
21
22
|
end
|
22
23
|
|
23
24
|
should "create an array CALLBACKS inside the GObject::Lib module" do
|
24
|
-
assert_equal [],
|
25
|
+
assert_equal [], GObject::Lib::CALLBACKS
|
25
26
|
end
|
26
27
|
|
27
28
|
should "not replace existing classes" do
|
28
|
-
oldclass =
|
29
|
-
GirFFI::Builder.build_class 'GObject', 'Object'
|
30
|
-
assert_equal oldclass,
|
29
|
+
oldclass = GObject::Object
|
30
|
+
GirFFI::Builder.build_class 'GObject', 'Object'
|
31
|
+
assert_equal oldclass, GObject::Object
|
31
32
|
end
|
32
33
|
end
|
33
34
|
|
34
35
|
context "building Gtk::Window" do
|
35
36
|
setup do
|
36
|
-
|
37
|
+
cleanup_module :Gtk
|
38
|
+
cleanup_module :GObject
|
39
|
+
GirFFI::Builder.build_class 'Gtk', 'Window'
|
37
40
|
end
|
38
41
|
|
39
42
|
should "build Gtk namespace" do
|
40
|
-
assert
|
41
|
-
assert
|
43
|
+
assert Gtk.const_defined? :Lib
|
44
|
+
assert Gtk.respond_to? :method_missing
|
42
45
|
end
|
43
46
|
|
44
47
|
should "build parent classes also" do
|
45
|
-
assert
|
46
|
-
assert
|
47
|
-
assert
|
48
|
-
assert
|
49
|
-
assert
|
48
|
+
assert Gtk.const_defined? :Widget
|
49
|
+
assert Gtk.const_defined? :Object
|
50
|
+
assert Object.const_defined? :GObject
|
51
|
+
assert GObject.const_defined? :InitiallyUnowned
|
52
|
+
assert GObject.const_defined? :Object
|
50
53
|
end
|
51
54
|
|
52
55
|
should "set up inheritence chain" do
|
53
56
|
assert_equal [
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
],
|
57
|
+
Gtk::Window,
|
58
|
+
Gtk::Bin,
|
59
|
+
Gtk::Container,
|
60
|
+
Gtk::Widget,
|
61
|
+
Gtk::Object,
|
62
|
+
GObject::InitiallyUnowned,
|
63
|
+
GObject::Object
|
64
|
+
], Gtk::Window.ancestors[0..6]
|
62
65
|
end
|
63
66
|
|
64
67
|
should "create a Gtk::Window#to_ptr method" do
|
65
|
-
assert_contains
|
66
|
-
end
|
67
|
-
|
68
|
-
should "attach gtk_window_new to Gtk::Lib" do
|
69
|
-
assert NS3::Gtk::Lib.respond_to? :gtk_window_new
|
68
|
+
assert_contains Gtk::Window.instance_methods.map(&:to_sym), :to_ptr
|
70
69
|
end
|
71
70
|
|
72
71
|
should "result in Gtk::Window.new to succeed" do
|
73
|
-
assert_nothing_raised {
|
72
|
+
assert_nothing_raised {Gtk::Window.new(:toplevel)}
|
74
73
|
end
|
75
74
|
end
|
76
75
|
|
77
76
|
context "building Gtk" do
|
78
77
|
setup do
|
79
|
-
|
78
|
+
cleanup_module :Gtk
|
79
|
+
GirFFI::Builder.build_module 'Gtk'
|
80
80
|
end
|
81
81
|
|
82
82
|
should "create a Lib module ready to attach functions from gtk-x11-2.0" do
|
83
83
|
# The Gtk module has more than one library on my current machine.
|
84
84
|
gir = GirFFI::IRepository.default
|
85
85
|
expected = (gir.shared_library 'Gtk').split(',')
|
86
|
-
assert_same_elements expected,
|
86
|
+
assert_same_elements expected, Gtk::Lib.ffi_libraries.map(&:name)
|
87
87
|
end
|
88
88
|
|
89
89
|
should "create an array CALLBACKS inside the Gtk::Lib module" do
|
90
|
-
assert_equal [],
|
90
|
+
assert_equal [], Gtk::Lib::CALLBACKS
|
91
91
|
end
|
92
92
|
|
93
93
|
should "not replace existing module" do
|
94
|
-
oldmodule =
|
95
|
-
GirFFI::Builder.build_module 'Gtk'
|
96
|
-
assert_equal oldmodule,
|
94
|
+
oldmodule = Gtk
|
95
|
+
GirFFI::Builder.build_module 'Gtk'
|
96
|
+
assert_equal oldmodule, Gtk
|
97
97
|
end
|
98
98
|
|
99
99
|
should "not replace existing Lib module" do
|
100
|
-
oldmodule =
|
101
|
-
GirFFI::Builder.build_module 'Gtk'
|
102
|
-
assert_equal oldmodule,
|
100
|
+
oldmodule = Gtk::Lib
|
101
|
+
GirFFI::Builder.build_module 'Gtk'
|
102
|
+
assert_equal oldmodule, Gtk::Lib
|
103
103
|
end
|
104
104
|
end
|
105
105
|
|
@@ -131,7 +131,7 @@ class BuilderTest < Test::Unit::TestCase
|
|
131
131
|
ffi_lib "gtk-x11-2.0"
|
132
132
|
end
|
133
133
|
|
134
|
-
GirFFI::Builder.send :attach_ffi_function,
|
134
|
+
GirFFI::Builder.send :attach_ffi_function, libmod, @go
|
135
135
|
assert_contains libmod.public_methods.map(&:to_sym), :gtk_main
|
136
136
|
end
|
137
137
|
end
|
@@ -151,11 +151,11 @@ class BuilderTest < Test::Unit::TestCase
|
|
151
151
|
should "have :pointer, :pointer as types of the arguments for the attached function" do
|
152
152
|
# FIXME: Ideally, we attach the function and test that it requires
|
153
153
|
# the correct argument types.
|
154
|
-
assert_equal [:pointer, :pointer], GirFFI::Builder.send(:ffi_function_argument_types,
|
154
|
+
assert_equal [:pointer, :pointer], GirFFI::Builder.send(:ffi_function_argument_types, @go)
|
155
155
|
end
|
156
156
|
|
157
157
|
should "have :void as return type for the attached function" do
|
158
|
-
assert_equal :void, GirFFI::Builder.send(:ffi_function_return_type,
|
158
|
+
assert_equal :void, GirFFI::Builder.send(:ffi_function_return_type, @go)
|
159
159
|
end
|
160
160
|
end
|
161
161
|
|
@@ -171,14 +171,15 @@ class BuilderTest < Test::Unit::TestCase
|
|
171
171
|
end
|
172
172
|
|
173
173
|
should "have :pointer as types of the arguments for the attached function" do
|
174
|
-
assert_equal [:pointer], GirFFI::Builder.send(:ffi_function_argument_types,
|
174
|
+
assert_equal [:pointer], GirFFI::Builder.send(:ffi_function_argument_types, @go)
|
175
175
|
end
|
176
176
|
|
177
177
|
end
|
178
178
|
|
179
179
|
context "looking at GObject.signal_connect_data" do
|
180
180
|
setup do
|
181
|
-
|
181
|
+
cleanup_module :GObject
|
182
|
+
GirFFI::Builder.build_module 'GObject'
|
182
183
|
@go = get_function_introspection_data 'GObject', 'signal_connect_data'
|
183
184
|
end
|
184
185
|
|
@@ -189,14 +190,14 @@ class BuilderTest < Test::Unit::TestCase
|
|
189
190
|
end
|
190
191
|
|
191
192
|
should "have the correct types of the arguments for the attached function" do
|
192
|
-
assert_equal [:pointer, :string, :Callback, :pointer, :ClosureNotify,
|
193
|
-
GirFFI::Builder.send(:ffi_function_argument_types,
|
193
|
+
assert_equal [:pointer, :string, :Callback, :pointer, :ClosureNotify, GObject::ConnectFlags],
|
194
|
+
GirFFI::Builder.send(:ffi_function_argument_types, @go)
|
194
195
|
end
|
195
196
|
|
196
197
|
should "define ffi callback types :Callback and :ClosureNotify" do
|
197
|
-
GirFFI::Builder.setup_function 'GObject',
|
198
|
-
cb =
|
199
|
-
cn =
|
198
|
+
GirFFI::Builder.setup_function 'GObject', 'signal_connect_data'
|
199
|
+
cb = GObject::Lib.find_type :Callback
|
200
|
+
cn = GObject::Lib.find_type :ClosureNotify
|
200
201
|
|
201
202
|
assert_equal FFI.find_type(:void), cb.result_type
|
202
203
|
assert_equal FFI.find_type(:void), cn.result_type
|
@@ -205,7 +206,7 @@ class BuilderTest < Test::Unit::TestCase
|
|
205
206
|
end
|
206
207
|
|
207
208
|
should "define ffi enum type ConnectFlags" do
|
208
|
-
assert_equal({:after => 1, :swapped => 2},
|
209
|
+
assert_equal({:after => 1, :swapped => 2}, GObject::ConnectFlags.to_h)
|
209
210
|
end
|
210
211
|
end
|
211
212
|
|
@@ -240,88 +241,81 @@ class BuilderTest < Test::Unit::TestCase
|
|
240
241
|
should "set up #_real_new as an alias to #new" do
|
241
242
|
assert Everything::TestBoxed.respond_to? "_real_new"
|
242
243
|
end
|
244
|
+
end
|
243
245
|
|
244
|
-
|
245
|
-
tb = Everything::TestBoxed.new
|
246
|
-
assert_instance_of Everything::TestBoxed, tb
|
247
|
-
end
|
248
|
-
|
249
|
-
should "allow creation using alternative constructors" do
|
250
|
-
tb = Everything::TestBoxed.new_alternative_constructor1 1
|
251
|
-
assert_instance_of Everything::TestBoxed, tb
|
252
|
-
assert_equal 1, tb[:some_int8]
|
253
|
-
|
254
|
-
tb = Everything::TestBoxed.new_alternative_constructor2 1, 2
|
255
|
-
assert_instance_of Everything::TestBoxed, tb
|
256
|
-
assert_equal 1 + 2, tb[:some_int8]
|
246
|
+
# TODO: Should not allow functions to be called as methods, etc.
|
257
247
|
|
258
|
-
|
259
|
-
|
260
|
-
|
248
|
+
context "building the Everything module" do
|
249
|
+
setup do
|
250
|
+
cleanup_module :Everything
|
251
|
+
GirFFI::Builder.build_module 'Everything'
|
261
252
|
end
|
262
253
|
|
263
|
-
should "
|
264
|
-
|
265
|
-
|
266
|
-
assert_equal true, tb.equals(tb2)
|
254
|
+
should "create a method_missing method for the module" do
|
255
|
+
ms = (Everything.public_methods - Module.public_methods).map(&:to_sym)
|
256
|
+
assert_contains ms, :method_missing
|
267
257
|
end
|
268
258
|
|
269
|
-
should "
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
assert_equal 123, tb2[:some_int8], "fields copied"
|
274
|
-
tb2[:some_int8] = 89
|
275
|
-
assert_equal 123, tb[:some_int8], "is a true copy"
|
259
|
+
should "cause the TestObj class to be autocreated" do
|
260
|
+
assert !Everything.const_defined?(:TestObj)
|
261
|
+
assert_nothing_raised {Everything::TestObj}
|
262
|
+
assert Everything.const_defined? :TestObj
|
276
263
|
end
|
277
264
|
end
|
278
265
|
|
279
|
-
|
266
|
+
# TODO: Turn this into full test of instance method creation, including
|
267
|
+
# inheritance issues.
|
268
|
+
context "built Everything::TestObj" do
|
280
269
|
setup do
|
281
|
-
|
270
|
+
cleanup_module :Everything
|
271
|
+
GirFFI::Builder.build_class 'Everything', 'TestObj'
|
282
272
|
end
|
283
|
-
should "create an object of type FFI::Enum" do
|
284
|
-
assert_instance_of FFI::Enum, Everything::TestEnum
|
285
|
-
end
|
286
|
-
end
|
287
|
-
|
288
|
-
# TODO: Should not allow functions to be called as methods, etc.
|
289
273
|
|
290
|
-
|
291
|
-
|
292
|
-
|
274
|
+
should "make autocreated instance method available to all instances" do
|
275
|
+
o1 = Everything::TestObj.new_from_file("foo")
|
276
|
+
o2 = Everything::TestObj.new_from_file("foo")
|
277
|
+
o1.instance_method
|
278
|
+
Everything::TestObj.class_eval do
|
279
|
+
undef method_missing
|
280
|
+
end
|
281
|
+
assert_nothing_raised { o2.instance_method }
|
293
282
|
end
|
294
283
|
|
295
|
-
should "
|
296
|
-
|
297
|
-
|
284
|
+
should "attach C functions to Everything::Lib" do
|
285
|
+
o = Everything::TestObj.new_from_file("foo")
|
286
|
+
o.instance_method
|
287
|
+
assert Everything::Lib.respond_to? :test_obj_instance_method
|
298
288
|
end
|
299
289
|
|
300
|
-
should "
|
301
|
-
|
302
|
-
result = Everything.test_callback_user_data Proc.new {|u|
|
303
|
-
a = u
|
304
|
-
5
|
305
|
-
}, :bar
|
306
|
-
assert_equal :bar, a
|
307
|
-
assert_equal 5, result
|
290
|
+
should "not have regular #new as a constructor" do
|
291
|
+
assert_raises(NoMethodError) { Everything::TestObj.new }
|
308
292
|
end
|
309
293
|
end
|
310
294
|
|
311
|
-
context "
|
295
|
+
context "built Everything::TestSubObj" do
|
312
296
|
setup do
|
313
|
-
|
297
|
+
cleanup_module :Everything
|
298
|
+
GirFFI::Builder.build_class 'Everything', 'TestSubObj'
|
314
299
|
end
|
315
300
|
|
316
|
-
should "
|
317
|
-
|
318
|
-
|
301
|
+
should "autocreate parent class' set_bare inside the parent class" do
|
302
|
+
o1 = Everything::TestSubObj.new
|
303
|
+
o2 = Everything::TestObj.new_from_file("foo")
|
304
|
+
|
305
|
+
assert_nothing_raised {o1.set_bare(nil)}
|
306
|
+
|
307
|
+
Everything::TestObj.class_eval do
|
308
|
+
undef method_missing
|
309
|
+
end
|
310
|
+
|
311
|
+
assert_nothing_raised {o2.set_bare(nil)}
|
319
312
|
end
|
320
313
|
|
321
|
-
should "
|
322
|
-
|
323
|
-
|
324
|
-
|
314
|
+
should "use its own version of instance_method when parent's version has been created" do
|
315
|
+
obj = Everything::TestObj.new_from_file("foo")
|
316
|
+
assert_equal(-1, obj.instance_method)
|
317
|
+
subobj = Everything::TestSubObj.new
|
318
|
+
assert_equal 0, subobj.instance_method
|
325
319
|
end
|
326
320
|
end
|
327
321
|
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require File.expand_path('test_helper.rb', File.dirname(__FILE__))
|
2
|
+
require 'gir_ffi'
|
3
|
+
|
4
|
+
GirFFI.setup :Everything
|
5
|
+
|
6
|
+
# Tests generated methods and functions in the Everything namespace.
|
7
|
+
class EverythingTest < Test::Unit::TestCase
|
8
|
+
context "The generated Everything module" do
|
9
|
+
should "have correct test_boolean" do
|
10
|
+
assert_equal false, Everything.test_boolean(false)
|
11
|
+
assert_equal true, Everything.test_boolean(true)
|
12
|
+
end
|
13
|
+
|
14
|
+
should "have correct test_callback_user_data" do
|
15
|
+
a = :foo
|
16
|
+
result = Everything.test_callback_user_data Proc.new {|u|
|
17
|
+
a = u
|
18
|
+
5
|
19
|
+
}, :bar
|
20
|
+
assert_equal :bar, a
|
21
|
+
assert_equal 5, result
|
22
|
+
end
|
23
|
+
|
24
|
+
should "have correct test_gtype" do
|
25
|
+
result = Everything.test_gtype 23
|
26
|
+
assert_equal 23, result
|
27
|
+
end
|
28
|
+
|
29
|
+
should "have correct test_value_return" do
|
30
|
+
result = Everything.test_value_return 3423
|
31
|
+
assert_equal 3423, result.get_int
|
32
|
+
end
|
33
|
+
|
34
|
+
context "the Everything::TestBoxed class" do
|
35
|
+
should "create an instance using #new" do
|
36
|
+
tb = Everything::TestBoxed.new
|
37
|
+
assert_instance_of Everything::TestBoxed, tb
|
38
|
+
end
|
39
|
+
|
40
|
+
should "allow creating an instance using alternative constructors" do
|
41
|
+
tb = Everything::TestBoxed.new_alternative_constructor1 1
|
42
|
+
assert_instance_of Everything::TestBoxed, tb
|
43
|
+
assert_equal 1, tb[:some_int8]
|
44
|
+
|
45
|
+
tb = Everything::TestBoxed.new_alternative_constructor2 1, 2
|
46
|
+
assert_instance_of Everything::TestBoxed, tb
|
47
|
+
assert_equal 1 + 2, tb[:some_int8]
|
48
|
+
|
49
|
+
tb = Everything::TestBoxed.new_alternative_constructor3 "54"
|
50
|
+
assert_instance_of Everything::TestBoxed, tb
|
51
|
+
assert_equal 54, tb[:some_int8]
|
52
|
+
end
|
53
|
+
|
54
|
+
should "have a working equals method" do
|
55
|
+
tb = Everything::TestBoxed.new_alternative_constructor1 123
|
56
|
+
tb2 = Everything::TestBoxed.new_alternative_constructor2 120, 3
|
57
|
+
assert_equal true, tb.equals(tb2)
|
58
|
+
end
|
59
|
+
|
60
|
+
should "have a working copy method" do
|
61
|
+
tb = Everything::TestBoxed.new_alternative_constructor1 123
|
62
|
+
tb2 = tb.copy
|
63
|
+
assert_instance_of Everything::TestBoxed, tb2
|
64
|
+
assert_equal 123, tb2[:some_int8], "fields copied"
|
65
|
+
tb2[:some_int8] = 89
|
66
|
+
assert_equal 123, tb[:some_int8], "is a true copy"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
context "the Everything::TestEnum type" do
|
71
|
+
should "be of type FFI::Enum" do
|
72
|
+
assert_instance_of FFI::Enum, Everything::TestEnum
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
@@ -1,6 +1,5 @@
|
|
1
1
|
require File.expand_path('test_helper.rb', File.dirname(__FILE__))
|
2
|
-
require 'gir_ffi
|
3
|
-
require 'gir_ffi/function_definition_builder'
|
2
|
+
require 'gir_ffi'
|
4
3
|
|
5
4
|
class FunctionDefinitionBuilderTest < Test::Unit::TestCase
|
6
5
|
context "The FunctionDefinition builder" do
|
data/test/gtk_overrides_test.rb
CHANGED
@@ -1,13 +1,18 @@
|
|
1
1
|
require File.expand_path('test_helper.rb', File.dirname(__FILE__))
|
2
2
|
require 'gir_ffi'
|
3
|
-
GirFFI.setup :Gtk
|
4
3
|
|
5
4
|
class GtkOverridesTest < Test::Unit::TestCase
|
6
5
|
context "The Gtk.init function" do
|
6
|
+
setup do
|
7
|
+
cleanup_module :Gtk
|
8
|
+
GirFFI.setup :Gtk
|
9
|
+
end
|
10
|
+
|
7
11
|
should "not take any arguments" do
|
8
12
|
assert_raises(ArgumentError) { Gtk.init 1, ["foo"] }
|
9
13
|
assert_nothing_raised { Gtk.init }
|
10
14
|
end
|
15
|
+
|
11
16
|
# FIXME: The following test doesn't actually work.
|
12
17
|
# In practice however, the Gtk.init function does exactly this.
|
13
18
|
if false
|
data/test/test_helper.rb
CHANGED
@@ -36,4 +36,10 @@ class Test::Unit::TestCase
|
|
36
36
|
GirFFI::IRepository.default.require namespace, nil
|
37
37
|
GirFFI::Builder.send :method_introspection_data, namespace, klass, function
|
38
38
|
end
|
39
|
+
|
40
|
+
def cleanup_module name
|
41
|
+
if Object.const_defined? name
|
42
|
+
Object.send(:remove_const, name)
|
43
|
+
end
|
44
|
+
end
|
39
45
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gir_ffi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 27
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 2
|
10
|
+
version: 0.0.2
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Matijs van Zuijlen
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-
|
18
|
+
date: 2010-11-14 00:00:00 +01:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -84,7 +84,6 @@ files:
|
|
84
84
|
- lib/gir_ffi/i_repository.rb
|
85
85
|
- lib/gir_ffi/i_vfunc_info.rb
|
86
86
|
- lib/gir_ffi/i_constant_info.rb
|
87
|
-
- lib/gir_ffi/class_base.rb
|
88
87
|
- lib/gir_ffi/i_struct_info.rb
|
89
88
|
- lib/gir_ffi/i_callable_info.rb
|
90
89
|
- lib/gir_ffi/function_definition_builder.rb
|
@@ -108,6 +107,8 @@ files:
|
|
108
107
|
- test/test_helper.rb
|
109
108
|
- test/girffi_test.rb
|
110
109
|
- test/constructor_definition_builder_test.rb
|
110
|
+
- test/base_test.rb
|
111
|
+
- test/everything_test.rb
|
111
112
|
- test/builder_test.rb
|
112
113
|
- test/gtk_overrides_test.rb
|
113
114
|
- tasks/bones.rake
|
@@ -164,8 +165,10 @@ specification_version: 3
|
|
164
165
|
summary: Ruby-FFI-based binding of the GObject Introspection Repository
|
165
166
|
test_files:
|
166
167
|
- test/arg_helper_test.rb
|
168
|
+
- test/base_test.rb
|
167
169
|
- test/builder_test.rb
|
168
170
|
- test/constructor_definition_builder_test.rb
|
171
|
+
- test/everything_test.rb
|
169
172
|
- test/function_definition_builder_test.rb
|
170
173
|
- test/g_type_test.rb
|
171
174
|
- test/girffi_test.rb
|