Convenience tweaks to FFI::Struct
This commit is contained in:
@@ -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
|
||||
|
@@ -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]
|
||||
|
Reference in New Issue
Block a user