module FFI module Tcl # Nicer introspection and some accessors. class PrettyStruct < FFI::Struct ACCESSOR_CODE = <<-CODE def {name}; self[{sym}]; end def {name}=(value) self[{sym}] = value; end CODE def self.layout(*kvs) kvs.each_slice(2) do |key, value| eval ACCESSOR_CODE.gsub(/\{(.*?)\}/, '{name}' => key, '{sym}' => ":#{key}") end super end def inspect kvs = members.zip(values) kvs.map!{|key, value| "%s=%s" % [key, value.inspect] } "<%s %s>" % [self.class, kvs.join(' ')] end end # The following structure represents a type of object, which is a particular # internal representation for an object plus a set of functions that provide # standard operations on objects of that type. class ObjType < PrettyStruct layout( :name, :string, :free_internal_rep_proc, :pointer, :dup_internal_rep_proc, :pointer, :update_string_proc, :pointer, :set_from_any_proc, :pointer ) def to_i pointer.get_pointer(0).to_i end def inspect "#<ObjType name=%p>" % [self[:name]] end end class Obj < PrettyStruct class InternalRep < Union class TwoPtrValue < PrettyStruct layout( :ptr1, :pointer, :ptr2, :pointer ) end class PtrAndLongRep < PrettyStruct layout( :ptr, :pointer, :value, :ulong ) end layout( :longValue, :long, :doubleValue, :double, :otherValuePtr, :pointer, :wideValue, :int64, :twoPtrValue, TwoPtrValue, :ptrAndLongRep, PtrAndLongRep ) end layout( :refCount, :int, :bytes, :string, :length, :int, :type, ObjType, :internalRep, InternalRep ) def pretty_type EvalResult::TYPES[type.to_i] end def inspect "#<Obj bytes=%p type=%p>" % [self[:bytes], pretty_type] end end end end