Convenience tweaks to FFI::Struct

This commit is contained in:
Brian Candler
2011-05-08 11:21:58 +01:00
parent c0cb310761
commit 0df9fc6b32
2 changed files with 37 additions and 9 deletions

View File

@@ -6,13 +6,15 @@ require 'ffi'
# - robust pre-existing code
# - good handling of nested structures and nested arrays
# Bad things about FFI::Struct:
# - no Hash initialization: MyStruct.new(:foo=>1, :bar=>2)
# - no accessor methods m.foo = 1
# - no Hash initialization: MyStruct.new(:foo=>1, :bar=>2) [*]
# - no accessor methods m.foo = 1 [*]
# - can't do zero size array at end of struct: layout :foo, [Foo, 0]
# - no network-order fields? (in_addr)
# - no decent inspect (fix this below)
# - no decent inspect [*]
# [*] Fixed below in FFI::AStruct
class FFI::Struct
class FFI::AStruct < FFI::Struct
# https://github.com/ffi/ffi/issues/102
def inspect
res = "#<#{self.class}"
members.zip(values).each do |m,v|
@@ -20,8 +22,34 @@ class FFI::Struct
end
res << ">"
end
# https://github.com/ffi/ffi/issues/106
def initialize(*args)
if args.first.is_a? Hash
super(nil, *args[1..-1])
src.each { |k,v| self[k] = v }
else
super
end
end
# https://github.com/ffi/ffi/issues/107
def self.layout(*fields)
super
fields.each_slice(2) do |name,type|
# Structure building is screwed up if there's a 'size' member!
next if instance_methods.find { |m| m.to_sym == name }
define_method name do
self[name]
end
define_method "#{name}=" do |v|
self[name] = v
end
end
end
end
# https://github.com/ffi/ffi/issues/102
class FFI::StructLayout::CharArray
def inspect
to_s.inspect

View File

@@ -7,7 +7,7 @@ module Linux
#+
# struct ipt_getinfo
class IPTGetInfo < FFI::Struct
class IPTGetInfo < FFI::AStruct
layout :name, [:char, IPT_TABLE_MAXNAMELEN],
:valid_hooks, :uint,
:hook_entry, [:uint, NF_INET_NUMHOOKS],
@@ -16,7 +16,7 @@ module Linux
:size, :uint
end
class IPTIP < FFI::Struct
class IPTIP < FFI::AStruct
layout :src, :int32, # FIXME: needs ntohl
:dst, :int32,
:smsk, :int32,
@@ -31,13 +31,13 @@ module Linux
end
# struct xt_counters (netfilter/x_tables.h)
class XTCounters < FFI::Struct
class XTCounters < FFI::AStruct
layout :pcnt, :uint64,
:bcnt, :uint64
end
# struct ipt_entry
class IPTEntry < FFI::Struct
class IPTEntry < FFI::AStruct
layout :ip, IPTIP,
:nfcache, :uint,
:target_offset, :uint16, # size of ipt_entry + matches
@@ -48,7 +48,7 @@ module Linux
end
# struct ipt_get_entries
class IPTGetEntries < FFI::Struct
class IPTGetEntries < FFI::AStruct
layout :name, [:uchar, IPT_TABLE_MAXNAMELEN],
:size, :uint,
:entrytable, [IPTEntry, 1] # should be [IPTEntry, 0]