ffi_dry 0.1.4 → 0.1.5
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/.gitignore +1 -0
- data/History.txt +4 -0
- data/README.rdoc +13 -17
- data/VERSION +1 -1
- data/ffi_dry.gemspec +2 -2
- data/lib/ffi/dry.rb +40 -8
- metadata +2 -2
data/.gitignore
CHANGED
data/History.txt
CHANGED
data/README.rdoc
CHANGED
@@ -5,14 +5,14 @@ things and add support for some uncommon ones.
|
|
5
5
|
|
6
6
|
== Requirements
|
7
7
|
|
8
|
-
* ffi
|
8
|
+
* ffi (>= 0.5.0) - github.com/ffi/ffi
|
9
9
|
|
10
10
|
|
11
11
|
== Synopsis
|
12
12
|
|
13
13
|
(samples/ in the package for code)
|
14
14
|
|
15
|
-
|
15
|
+
One major feature is a DSL"-like" syntax for declaring structure members
|
16
16
|
in FFI::Struct or FFI::ManagedStruct definitions.
|
17
17
|
|
18
18
|
require 'rubygems'
|
@@ -34,16 +34,14 @@ in FFI::Struct or FFI::ManagedStruct definitions.
|
|
34
34
|
|
35
35
|
ss0=SomeStruct.new
|
36
36
|
|
37
|
-
With the declarations above, we specified :desc hash value in metadata
|
38
|
-
|
37
|
+
With the declarations above, we specified :desc hash value in metadata. Extra
|
38
|
+
metadata can have arbitrary keys and is accessible in every instance and class.
|
39
39
|
|
40
40
|
pp ss0.dsl_metadata
|
41
41
|
[{:type=>:uint16, :name=>:field1, :desc=>"this is field 1"},
|
42
42
|
{:type=>:uint16, :name=>:field2, :desc=>"this is field 2"}]
|
43
43
|
# => nil
|
44
44
|
|
45
|
-
Or class.
|
46
|
-
|
47
45
|
pp SomeStruct.dsl_metadata
|
48
46
|
#...
|
49
47
|
|
@@ -57,13 +55,10 @@ during initialization. (The FFI standard ways still work too)
|
|
57
55
|
ss3=SomeStruct.new {|x| x.field1=1 }
|
58
56
|
ss4=SomeStruct.new(:raw => raw_data) {|x| x.field1=1 }
|
59
57
|
|
60
|
-
[ ss0,
|
61
|
-
|
62
|
-
ss2,
|
63
|
-
ss3,
|
64
|
-
ss4 ].each_with_index {|x,i| p ["ss#{i}",[x.field1, x.field2]]}
|
58
|
+
[ ss0, ss1, ss2, ss3, ss4
|
59
|
+
].each_with_index {|x,i| p ["ss#{i}",[x.field1, x.field2]]}
|
65
60
|
|
66
|
-
# which
|
61
|
+
# which produces...
|
67
62
|
# ["ss0", [0, 0]]
|
68
63
|
# ["ss1", [0, 65535]]
|
69
64
|
# ["ss2", [1, 2]]
|
@@ -72,8 +67,8 @@ during initialization. (The FFI standard ways still work too)
|
|
72
67
|
|
73
68
|
|
74
69
|
Here's a broader example which utilizes that arbitrary ':desc' parameter in a
|
75
|
-
"neighborly" way. This also demonstrates superclasses to add common
|
76
|
-
features, declaring array fields, as well as nesting other structs.
|
70
|
+
"neighborly" way. This also demonstrates using superclasses to add common
|
71
|
+
struct features, declaring array fields, as well as nesting other structs.
|
77
72
|
|
78
73
|
require 'rubygems'
|
79
74
|
require 'ffi'
|
@@ -190,9 +185,10 @@ features, declaring array fields, as well as nesting other structs.
|
|
190
185
|
# type: :uint8
|
191
186
|
# desc: test field 2
|
192
187
|
|
193
|
-
There's also some
|
194
|
-
and handy thing when porting various libraries. We use
|
195
|
-
|
188
|
+
There's also some helper modules for collecting lookup maps for constants, a
|
189
|
+
common and handy thing when porting various libraries. We use the Ruby Socket
|
190
|
+
socket namespace here for demonstration purposes. You can 'slurp' constants
|
191
|
+
from any namespace this way.
|
196
192
|
|
197
193
|
require 'ffi/dry'
|
198
194
|
require 'socket'
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.5
|
data/ffi_dry.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{ffi_dry}
|
8
|
-
s.version = "0.1.
|
8
|
+
s.version = "0.1.5"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Eric Monti"]
|
12
|
-
s.date = %q{2010-01-
|
12
|
+
s.date = %q{2010-01-15}
|
13
13
|
s.description = %q{Provides some useful modules, classes, and methods for FFI bindings as well as a DSL-like syntax for FFI::Struct layouts}
|
14
14
|
s.email = %q{emonti@matasano.com}
|
15
15
|
s.extra_rdoc_files = [
|
data/lib/ffi/dry.rb
CHANGED
@@ -108,7 +108,7 @@ module FFI::DRY
|
|
108
108
|
# the layout.
|
109
109
|
#
|
110
110
|
# This method is called automatically if you are using the initialize()
|
111
|
-
# method provided in the
|
111
|
+
# method provided in the Struct class and passing it a Hash as its only
|
112
112
|
# argument.
|
113
113
|
def set_fields(params=nil)
|
114
114
|
(params || {}).keys.each do |p|
|
@@ -169,13 +169,20 @@ module FFI::DRY
|
|
169
169
|
def _class_meths_from_dsl_metadata(meta)
|
170
170
|
(@dsl_metadata = meta).each do |spec|
|
171
171
|
name = spec[:name]
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
172
|
+
ftype = spec[:type]
|
173
|
+
unless instance_methods.include?(:"#{name}")
|
174
|
+
if p=spec[:p_struct] and p.kind_of?(Class)
|
175
|
+
define_method(:"#{name}") do
|
176
|
+
p.new(self[name]) unless self[name].null?
|
177
|
+
end
|
178
|
+
else
|
179
|
+
define_method(:"#{name}") { self[name] }
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
unless instance_methods.include?(:"#{name}=")
|
184
|
+
define_method(:"#{name}=") {|val| self[name]=val }
|
185
|
+
end
|
179
186
|
end
|
180
187
|
end
|
181
188
|
end
|
@@ -183,6 +190,19 @@ module FFI::DRY
|
|
183
190
|
def self.included(base)
|
184
191
|
base.extend(ClassMethods)
|
185
192
|
end
|
193
|
+
|
194
|
+
alias inspect_orig inspect
|
195
|
+
|
196
|
+
# Overrides inspect to show field names and values
|
197
|
+
def inspect
|
198
|
+
ret = "#<#{self.class}"
|
199
|
+
if not @_inspecting_in_progress
|
200
|
+
@_inspecting_in_progress = true
|
201
|
+
ret << " " << members.map {|m| "#{m}=#{self[m].inspect}"}.join(', ')
|
202
|
+
@_inspecting_in_progress = nil
|
203
|
+
end
|
204
|
+
ret << ">"
|
205
|
+
end
|
186
206
|
end # class StructHelper
|
187
207
|
|
188
208
|
# This is a wrapper around the FFI::StructLayoutBuilder. Its goal is to
|
@@ -235,6 +255,18 @@ module FFI::DRY
|
|
235
255
|
return ret
|
236
256
|
end
|
237
257
|
|
258
|
+
# A pointer to a structure. The structure does not allocate the entire
|
259
|
+
# space for the structure, just a pointer. When calling the accessors for
|
260
|
+
# a p_struct field, a new instance of the FFI::Struct will be returned.
|
261
|
+
def p_struct(name, klass, o={})
|
262
|
+
unless klass.kind_of?(Class)
|
263
|
+
raise(::ArgumentError, "klass must be a Class")
|
264
|
+
end
|
265
|
+
opts = o.merge(:p_struct => klass)
|
266
|
+
offset = opts[:offset]
|
267
|
+
field(name, :pointer, opts)
|
268
|
+
end
|
269
|
+
|
238
270
|
# Calls StructLayoutBuider.add_array() on the builder and stores
|
239
271
|
# a metadata hash entry (the opts hash with name and type overridden)
|
240
272
|
#
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ffi_dry
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Eric Monti
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2010-01-
|
12
|
+
date: 2010-01-15 00:00:00 -06:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|