nice-ffi 0.1 → 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/ChangeLog.txt +493 -0
- data/README.rdoc +23 -11
- data/docs/usage.rdoc +144 -37
- data/lib/nice-ffi.rb +10 -4
- data/lib/nice-ffi/autorelease.rb +112 -0
- data/lib/nice-ffi/{nicelibrary.rb → library.rb} +73 -45
- data/lib/nice-ffi/opaquestruct.rb +109 -0
- data/lib/nice-ffi/pathset.rb +404 -144
- data/lib/nice-ffi/{nicestruct.rb → struct.rb} +64 -19
- data/lib/nice-ffi/typedpointer.rb +20 -7
- metadata +11 -20
@@ -28,11 +28,6 @@
|
|
28
28
|
#++
|
29
29
|
|
30
30
|
|
31
|
-
require 'ffi'
|
32
|
-
|
33
|
-
need{ 'typedpointer' }
|
34
|
-
|
35
|
-
|
36
31
|
# A class to be used as a baseclass where you would use FFI::Struct.
|
37
32
|
# It acts mostly like FFI::Struct, but with nice extra features and
|
38
33
|
# conveniences to make life easier:
|
@@ -49,16 +44,32 @@ need{ 'typedpointer' }
|
|
49
44
|
# * Implements a nicer #new method which allows you to create a new
|
50
45
|
# struct and set its data in one shot by passing an Array, Hash, or
|
51
46
|
# another instance of the class (to copy data). You can also use it
|
52
|
-
# to wrap a FFI::Pointer
|
47
|
+
# to wrap a FFI::Pointer like FFI::Struct can.
|
53
48
|
#
|
54
49
|
# * Implements #to_ary and #to_hash to dump the struct data.
|
55
50
|
#
|
56
51
|
# * Implements #to_s and #inspect for nice debugging output.
|
57
52
|
#
|
53
|
+
# * Adds ::typed_pointer convenience alias to create a TypedPointer
|
54
|
+
# for this klass.
|
55
|
+
#
|
56
|
+
# * Provides automatic memory management for Pointers if you define
|
57
|
+
# MyClass.release( pointer). (This can be disabled per-instance by
|
58
|
+
# providing {:autorelease => false} as an option to #new).
|
59
|
+
#
|
58
60
|
class NiceFFI::Struct < FFI::Struct
|
61
|
+
include NiceFFI::AutoRelease
|
59
62
|
|
60
63
|
class << self
|
61
64
|
|
65
|
+
# Returns a NiceFFI::TypedPointer instance for this class.
|
66
|
+
# Equivalent to NiceFFI::TypedPointer.new( this_class, options )
|
67
|
+
#
|
68
|
+
def typed_pointer( options={} )
|
69
|
+
NiceFFI::TypedPointer.new(self, options)
|
70
|
+
end
|
71
|
+
|
72
|
+
|
62
73
|
# Same syntax as FFI::Struct#layout, but also defines nice
|
63
74
|
# accessors for the attributes.
|
64
75
|
#
|
@@ -254,11 +265,8 @@ class NiceFFI::Struct < FFI::Struct
|
|
254
265
|
else
|
255
266
|
self.class_eval do
|
256
267
|
define_method( member ) do
|
257
|
-
|
258
|
-
|
259
|
-
rescue FFI::NullPointerError
|
260
|
-
nil
|
261
|
-
end
|
268
|
+
return nil if self.pointer.null?
|
269
|
+
return self[member]
|
262
270
|
end
|
263
271
|
end
|
264
272
|
end
|
@@ -306,14 +314,27 @@ class NiceFFI::Struct < FFI::Struct
|
|
306
314
|
|
307
315
|
|
308
316
|
# Create a new instance of the class, reading data from a Hash or
|
309
|
-
# Array of attributes,
|
310
|
-
# or wrapping (not copying!) a
|
317
|
+
# Array of attributes, a bytestring of raw data, copying from
|
318
|
+
# another instance of the class, or wrapping (not copying!) a
|
319
|
+
# FFI::Pointer.
|
320
|
+
#
|
321
|
+
# If val is an instance of FFI::Pointer and you have defined
|
322
|
+
# MyClass.release, the pointer will be passed to MyClass.release
|
323
|
+
# when the memory is no longer being used. Use MyClass.release to
|
324
|
+
# free the memory for the struct, as appropriate for your class. To
|
325
|
+
# disable autorelease for this instance, set {:autorelease => false}
|
326
|
+
# in +options+.
|
311
327
|
#
|
312
|
-
|
328
|
+
# (Note: FFI::MemoryPointer and FFI::Buffer have built-in memory
|
329
|
+
# management, so MyClass.release is never called for them.)
|
330
|
+
#
|
331
|
+
def initialize( val, options={} )
|
313
332
|
# Stores certain kinds of member values so that we don't need
|
314
333
|
# to create a new object every time they are read.
|
315
334
|
@member_cache = {}
|
316
335
|
|
336
|
+
options = {:autorelease => true}.merge!( options )
|
337
|
+
|
317
338
|
case val
|
318
339
|
|
319
340
|
when Hash
|
@@ -325,11 +346,17 @@ class NiceFFI::Struct < FFI::Struct
|
|
325
346
|
super() # Create empty struct
|
326
347
|
init_from_array( val ) # Read the values from an Array.
|
327
348
|
|
328
|
-
when
|
349
|
+
when String
|
329
350
|
super() # Create empty struct
|
330
|
-
|
351
|
+
init_from_bytes( val ) # Read the values from a bytestring.
|
352
|
+
|
353
|
+
when self.class
|
354
|
+
super() # Create empty struct
|
355
|
+
init_from_bytes( val.to_bytes ) # Read the values from another instance.
|
356
|
+
|
357
|
+
when FFI::Pointer
|
358
|
+
val = _make_autopointer( val, options[:autorelease] )
|
331
359
|
|
332
|
-
when FFI::Pointer, FFI::MemoryPointer
|
333
360
|
# Normal FFI::Struct behavior to wrap the pointer.
|
334
361
|
super( val )
|
335
362
|
|
@@ -356,6 +383,12 @@ class NiceFFI::Struct < FFI::Struct
|
|
356
383
|
private :init_from_array
|
357
384
|
|
358
385
|
|
386
|
+
def init_from_bytes( val ) # :nodoc:
|
387
|
+
self.pointer.put_bytes(0, val)
|
388
|
+
end
|
389
|
+
private :init_from_bytes
|
390
|
+
|
391
|
+
|
359
392
|
|
360
393
|
# Dump this instance as an Array of its struct data.
|
361
394
|
# The array contains only the data, not the member names.
|
@@ -372,12 +405,20 @@ class NiceFFI::Struct < FFI::Struct
|
|
372
405
|
members.collect{ |m| self[m] }
|
373
406
|
end
|
374
407
|
|
408
|
+
|
409
|
+
# Dump this instance as a string of raw bytes of its struct data.
|
410
|
+
#
|
411
|
+
def to_bytes
|
412
|
+
return self.pointer.get_bytes(0, self.size)
|
413
|
+
end
|
414
|
+
|
415
|
+
|
375
416
|
# Dump this instance as a Hash containing {member => data} pairs
|
376
417
|
# for every member in the struct.
|
377
418
|
#
|
378
419
|
# Example:
|
379
420
|
#
|
380
|
-
# Rect.new( :x=>1, :y=>2, :w=>3, :h=>4 ).
|
421
|
+
# Rect.new( :x=>1, :y=>2, :w=>3, :h=>4 ).to_hash
|
381
422
|
# # => {:h=>4, :w=>3, :x=>1, :y=>2}
|
382
423
|
#
|
383
424
|
def to_hash
|
@@ -387,12 +428,16 @@ class NiceFFI::Struct < FFI::Struct
|
|
387
428
|
|
388
429
|
|
389
430
|
def to_s
|
431
|
+
if self.pointer.null?
|
432
|
+
return "#<NULL %s:%#.x>"%[self.class.name, self.object_id]
|
433
|
+
end
|
434
|
+
|
390
435
|
mems = members.collect{ |m|
|
391
436
|
unless self.class.hidden?( m )
|
392
437
|
val = self.send(m)
|
393
438
|
|
394
439
|
# Cleanup/simplify for display
|
395
|
-
if val.is_a? FFI::
|
440
|
+
if val.nil? or (val.is_a? FFI::Pointer and val.null?)
|
396
441
|
val = "NULL"
|
397
442
|
elsif val.kind_of? FFI::Struct
|
398
443
|
val = "#<#{val.class}:%#.x>"%val.object_id
|
@@ -28,9 +28,6 @@
|
|
28
28
|
#++
|
29
29
|
|
30
30
|
|
31
|
-
require 'ffi'
|
32
|
-
|
33
|
-
|
34
31
|
# TypedPointer represents a :pointer (FFI type) that is a specific
|
35
32
|
# struct type. You can use TypedPointer( SomeStructClass ) instead
|
36
33
|
# of :pointer in these situations:
|
@@ -46,22 +43,38 @@ class NiceFFI::TypedPointer
|
|
46
43
|
# type must be a class (not an instance) which is a descendent of
|
47
44
|
# FFI::Struct (or is FFI::Struct itself).
|
48
45
|
#
|
49
|
-
|
46
|
+
# options must be a Hash of zero or more options.
|
47
|
+
# The current meaningful options are:
|
48
|
+
#
|
49
|
+
# * :autorelease - If false, instances of NiceStruct and
|
50
|
+
# OpaqueStruct (and subclasses) created via this TypedPointer will
|
51
|
+
# be passed {:autorelease => false} to disable automatic memory
|
52
|
+
# management. Use this for return values of functions that should
|
53
|
+
# not be autoreleased.
|
54
|
+
#
|
55
|
+
def initialize( type, options={} )
|
50
56
|
# unless type.is_a? Class and type.ancestors.include? FFI::Struct
|
51
57
|
# raise TypeError, "#{self.class} only wraps FFI::Struct and subclasses."
|
52
58
|
# end
|
53
59
|
@type = type
|
60
|
+
options = {:autorelease => true}.merge!( options )
|
61
|
+
@autorelease = options[:autorelease]
|
54
62
|
end
|
55
63
|
|
56
64
|
attr_reader :type
|
57
65
|
|
58
66
|
|
59
|
-
# Wrap a FFI::Pointer
|
67
|
+
# Wrap a FFI::Pointer in a new struct of this type.
|
60
68
|
def wrap( pointer )
|
61
|
-
unless pointer.is_a? FFI::Pointer
|
69
|
+
unless pointer.is_a? FFI::Pointer
|
62
70
|
raise TypeError, "#{self.class}[ #{@type} ] cannot wrap #{pointer.type}"
|
63
71
|
end
|
64
|
-
|
72
|
+
|
73
|
+
if @type.included_modules.include?( NiceFFI::AutoRelease )
|
74
|
+
@type.new( pointer, :autorelease => @autorelease )
|
75
|
+
else
|
76
|
+
@type.new( pointer )
|
77
|
+
end
|
65
78
|
end
|
66
79
|
|
67
80
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nice-ffi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: "0.
|
4
|
+
version: "0.2"
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Croisant
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-10-24 00:00:00 -05:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -20,22 +20,11 @@ dependencies:
|
|
20
20
|
requirements:
|
21
21
|
- - ">="
|
22
22
|
- !ruby/object:Gem::Version
|
23
|
-
version: 0.
|
24
|
-
version:
|
25
|
-
- !ruby/object:Gem::Dependency
|
26
|
-
name: need
|
27
|
-
type: :runtime
|
28
|
-
version_requirement:
|
29
|
-
version_requirements: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - ">="
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: 1.1.0
|
23
|
+
version: 0.5.0
|
34
24
|
version:
|
35
25
|
description: |
|
36
|
-
Nice-FFI is a layer on top of Ruby-FFI (and compatible FFI
|
37
|
-
|
38
|
-
development of FFI-based libraries.
|
26
|
+
Nice-FFI is a layer on top of Ruby-FFI (and compatible FFI systems)
|
27
|
+
with features to ease development of FFI-based libraries.
|
39
28
|
|
40
29
|
email: jacius@gmail.com
|
41
30
|
executables: []
|
@@ -48,10 +37,12 @@ files:
|
|
48
37
|
- docs/usage.rdoc
|
49
38
|
- TODO.rdoc
|
50
39
|
- README.rdoc
|
40
|
+
- lib/nice-ffi/autorelease.rb
|
51
41
|
- lib/nice-ffi/pathset.rb
|
52
|
-
- lib/nice-ffi/
|
42
|
+
- lib/nice-ffi/struct.rb
|
43
|
+
- lib/nice-ffi/opaquestruct.rb
|
53
44
|
- lib/nice-ffi/typedpointer.rb
|
54
|
-
- lib/nice-ffi/
|
45
|
+
- lib/nice-ffi/library.rb
|
55
46
|
- lib/nice-ffi.rb
|
56
47
|
- ChangeLog.txt
|
57
48
|
has_rdoc: true
|
@@ -77,8 +68,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
77
68
|
version:
|
78
69
|
requirements: []
|
79
70
|
|
80
|
-
rubyforge_project:
|
81
|
-
rubygems_version: 1.3.
|
71
|
+
rubyforge_project: nice-ffi
|
72
|
+
rubygems_version: 1.3.5
|
82
73
|
signing_key:
|
83
74
|
specification_version: 3
|
84
75
|
summary: Convenience layer atop Ruby-FFI
|