gir_ffi 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|