fiddle 1.0.0.beta1
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.
- checksums.yaml +7 -0
 - data/.gitignore +12 -0
 - data/.travis.yml +5 -0
 - data/Gemfile +4 -0
 - data/LICENSE.txt +21 -0
 - data/README.md +41 -0
 - data/Rakefile +13 -0
 - data/bin/console +14 -0
 - data/bin/setup +8 -0
 - data/ext/fiddle/closure.c +345 -0
 - data/ext/fiddle/closure.h +8 -0
 - data/ext/fiddle/conversions.c +141 -0
 - data/ext/fiddle/conversions.h +44 -0
 - data/ext/fiddle/extconf.rb +183 -0
 - data/ext/fiddle/extlibs +2 -0
 - data/ext/fiddle/fiddle.c +454 -0
 - data/ext/fiddle/fiddle.h +138 -0
 - data/ext/fiddle/function.c +315 -0
 - data/ext/fiddle/function.h +8 -0
 - data/ext/fiddle/handle.c +479 -0
 - data/ext/fiddle/pointer.c +721 -0
 - data/ext/fiddle/win32/fficonfig.h +29 -0
 - data/ext/fiddle/win32/libffi-3.2.1-mswin.patch +191 -0
 - data/ext/fiddle/win32/libffi-config.rb +48 -0
 - data/ext/fiddle/win32/libffi.mk.tmpl +96 -0
 - data/fiddle.gemspec +23 -0
 - data/lib/fiddle.rb +56 -0
 - data/lib/fiddle/closure.rb +49 -0
 - data/lib/fiddle/cparser.rb +194 -0
 - data/lib/fiddle/function.rb +18 -0
 - data/lib/fiddle/import.rb +318 -0
 - data/lib/fiddle/pack.rb +129 -0
 - data/lib/fiddle/struct.rb +244 -0
 - data/lib/fiddle/types.rb +72 -0
 - data/lib/fiddle/value.rb +113 -0
 - metadata +136 -0
 
    
        data/lib/fiddle/pack.rb
    ADDED
    
    | 
         @@ -0,0 +1,129 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: false
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'fiddle'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            module Fiddle
         
     | 
| 
      
 5 
     | 
    
         
            +
              module PackInfo # :nodoc: all
         
     | 
| 
      
 6 
     | 
    
         
            +
                ALIGN_MAP = {
         
     | 
| 
      
 7 
     | 
    
         
            +
                  TYPE_VOIDP => ALIGN_VOIDP,
         
     | 
| 
      
 8 
     | 
    
         
            +
                  TYPE_CHAR  => ALIGN_CHAR,
         
     | 
| 
      
 9 
     | 
    
         
            +
                  TYPE_SHORT => ALIGN_SHORT,
         
     | 
| 
      
 10 
     | 
    
         
            +
                  TYPE_INT   => ALIGN_INT,
         
     | 
| 
      
 11 
     | 
    
         
            +
                  TYPE_LONG  => ALIGN_LONG,
         
     | 
| 
      
 12 
     | 
    
         
            +
                  TYPE_FLOAT => ALIGN_FLOAT,
         
     | 
| 
      
 13 
     | 
    
         
            +
                  TYPE_DOUBLE => ALIGN_DOUBLE,
         
     | 
| 
      
 14 
     | 
    
         
            +
                  -TYPE_CHAR  => ALIGN_CHAR,
         
     | 
| 
      
 15 
     | 
    
         
            +
                  -TYPE_SHORT => ALIGN_SHORT,
         
     | 
| 
      
 16 
     | 
    
         
            +
                  -TYPE_INT   => ALIGN_INT,
         
     | 
| 
      
 17 
     | 
    
         
            +
                  -TYPE_LONG  => ALIGN_LONG,
         
     | 
| 
      
 18 
     | 
    
         
            +
                }
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                PACK_MAP = {
         
     | 
| 
      
 21 
     | 
    
         
            +
                  TYPE_VOIDP => ((SIZEOF_VOIDP == SIZEOF_LONG_LONG) ? "q" : "l!"),
         
     | 
| 
      
 22 
     | 
    
         
            +
                  TYPE_CHAR  => "c",
         
     | 
| 
      
 23 
     | 
    
         
            +
                  TYPE_SHORT => "s!",
         
     | 
| 
      
 24 
     | 
    
         
            +
                  TYPE_INT   => "i!",
         
     | 
| 
      
 25 
     | 
    
         
            +
                  TYPE_LONG  => "l!",
         
     | 
| 
      
 26 
     | 
    
         
            +
                  TYPE_FLOAT => "f",
         
     | 
| 
      
 27 
     | 
    
         
            +
                  TYPE_DOUBLE => "d",
         
     | 
| 
      
 28 
     | 
    
         
            +
                  -TYPE_CHAR  => "c",
         
     | 
| 
      
 29 
     | 
    
         
            +
                  -TYPE_SHORT => "s!",
         
     | 
| 
      
 30 
     | 
    
         
            +
                  -TYPE_INT   => "i!",
         
     | 
| 
      
 31 
     | 
    
         
            +
                  -TYPE_LONG  => "l!",
         
     | 
| 
      
 32 
     | 
    
         
            +
                }
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                SIZE_MAP = {
         
     | 
| 
      
 35 
     | 
    
         
            +
                  TYPE_VOIDP => SIZEOF_VOIDP,
         
     | 
| 
      
 36 
     | 
    
         
            +
                  TYPE_CHAR  => SIZEOF_CHAR,
         
     | 
| 
      
 37 
     | 
    
         
            +
                  TYPE_SHORT => SIZEOF_SHORT,
         
     | 
| 
      
 38 
     | 
    
         
            +
                  TYPE_INT   => SIZEOF_INT,
         
     | 
| 
      
 39 
     | 
    
         
            +
                  TYPE_LONG  => SIZEOF_LONG,
         
     | 
| 
      
 40 
     | 
    
         
            +
                  TYPE_FLOAT => SIZEOF_FLOAT,
         
     | 
| 
      
 41 
     | 
    
         
            +
                  TYPE_DOUBLE => SIZEOF_DOUBLE,
         
     | 
| 
      
 42 
     | 
    
         
            +
                  -TYPE_CHAR  => SIZEOF_CHAR,
         
     | 
| 
      
 43 
     | 
    
         
            +
                  -TYPE_SHORT => SIZEOF_SHORT,
         
     | 
| 
      
 44 
     | 
    
         
            +
                  -TYPE_INT   => SIZEOF_INT,
         
     | 
| 
      
 45 
     | 
    
         
            +
                  -TYPE_LONG  => SIZEOF_LONG,
         
     | 
| 
      
 46 
     | 
    
         
            +
                }
         
     | 
| 
      
 47 
     | 
    
         
            +
                if defined?(TYPE_LONG_LONG)
         
     | 
| 
      
 48 
     | 
    
         
            +
                  ALIGN_MAP[TYPE_LONG_LONG] = ALIGN_MAP[-TYPE_LONG_LONG] = ALIGN_LONG_LONG
         
     | 
| 
      
 49 
     | 
    
         
            +
                  PACK_MAP[TYPE_LONG_LONG] = PACK_MAP[-TYPE_LONG_LONG] = "q"
         
     | 
| 
      
 50 
     | 
    
         
            +
                  SIZE_MAP[TYPE_LONG_LONG] = SIZE_MAP[-TYPE_LONG_LONG] = SIZEOF_LONG_LONG
         
     | 
| 
      
 51 
     | 
    
         
            +
                end
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                def align(addr, align)
         
     | 
| 
      
 54 
     | 
    
         
            +
                  d = addr % align
         
     | 
| 
      
 55 
     | 
    
         
            +
                  if( d == 0 )
         
     | 
| 
      
 56 
     | 
    
         
            +
                    addr
         
     | 
| 
      
 57 
     | 
    
         
            +
                  else
         
     | 
| 
      
 58 
     | 
    
         
            +
                    addr + (align - d)
         
     | 
| 
      
 59 
     | 
    
         
            +
                  end
         
     | 
| 
      
 60 
     | 
    
         
            +
                end
         
     | 
| 
      
 61 
     | 
    
         
            +
                module_function :align
         
     | 
| 
      
 62 
     | 
    
         
            +
              end
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
              class Packer # :nodoc: all
         
     | 
| 
      
 65 
     | 
    
         
            +
                include PackInfo
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
                def self.[](*types)
         
     | 
| 
      
 68 
     | 
    
         
            +
                  new(types)
         
     | 
| 
      
 69 
     | 
    
         
            +
                end
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
                def initialize(types)
         
     | 
| 
      
 72 
     | 
    
         
            +
                  parse_types(types)
         
     | 
| 
      
 73 
     | 
    
         
            +
                end
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
                def size()
         
     | 
| 
      
 76 
     | 
    
         
            +
                  @size
         
     | 
| 
      
 77 
     | 
    
         
            +
                end
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
                def pack(ary)
         
     | 
| 
      
 80 
     | 
    
         
            +
                  case SIZEOF_VOIDP
         
     | 
| 
      
 81 
     | 
    
         
            +
                  when SIZEOF_LONG
         
     | 
| 
      
 82 
     | 
    
         
            +
                    ary.pack(@template)
         
     | 
| 
      
 83 
     | 
    
         
            +
                  when SIZEOF_LONG_LONG
         
     | 
| 
      
 84 
     | 
    
         
            +
                    ary.pack(@template)
         
     | 
| 
      
 85 
     | 
    
         
            +
                  else
         
     | 
| 
      
 86 
     | 
    
         
            +
                    raise(RuntimeError, "sizeof(void*)?")
         
     | 
| 
      
 87 
     | 
    
         
            +
                  end
         
     | 
| 
      
 88 
     | 
    
         
            +
                end
         
     | 
| 
      
 89 
     | 
    
         
            +
             
     | 
| 
      
 90 
     | 
    
         
            +
                def unpack(ary)
         
     | 
| 
      
 91 
     | 
    
         
            +
                  case SIZEOF_VOIDP
         
     | 
| 
      
 92 
     | 
    
         
            +
                  when SIZEOF_LONG
         
     | 
| 
      
 93 
     | 
    
         
            +
                    ary.join().unpack(@template)
         
     | 
| 
      
 94 
     | 
    
         
            +
                  when SIZEOF_LONG_LONG
         
     | 
| 
      
 95 
     | 
    
         
            +
                    ary.join().unpack(@template)
         
     | 
| 
      
 96 
     | 
    
         
            +
                  else
         
     | 
| 
      
 97 
     | 
    
         
            +
                    raise(RuntimeError, "sizeof(void*)?")
         
     | 
| 
      
 98 
     | 
    
         
            +
                  end
         
     | 
| 
      
 99 
     | 
    
         
            +
                end
         
     | 
| 
      
 100 
     | 
    
         
            +
             
     | 
| 
      
 101 
     | 
    
         
            +
                private
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
                def parse_types(types)
         
     | 
| 
      
 104 
     | 
    
         
            +
                  @template = ""
         
     | 
| 
      
 105 
     | 
    
         
            +
                  addr     = 0
         
     | 
| 
      
 106 
     | 
    
         
            +
                  types.each{|t|
         
     | 
| 
      
 107 
     | 
    
         
            +
                    orig_addr = addr
         
     | 
| 
      
 108 
     | 
    
         
            +
                    if( t.is_a?(Array) )
         
     | 
| 
      
 109 
     | 
    
         
            +
                      addr = align(orig_addr, ALIGN_MAP[TYPE_VOIDP])
         
     | 
| 
      
 110 
     | 
    
         
            +
                    else
         
     | 
| 
      
 111 
     | 
    
         
            +
                      addr = align(orig_addr, ALIGN_MAP[t])
         
     | 
| 
      
 112 
     | 
    
         
            +
                    end
         
     | 
| 
      
 113 
     | 
    
         
            +
                    d = addr - orig_addr
         
     | 
| 
      
 114 
     | 
    
         
            +
                    if( d > 0 )
         
     | 
| 
      
 115 
     | 
    
         
            +
                      @template << "x#{d}"
         
     | 
| 
      
 116 
     | 
    
         
            +
                    end
         
     | 
| 
      
 117 
     | 
    
         
            +
                    if( t.is_a?(Array) )
         
     | 
| 
      
 118 
     | 
    
         
            +
                      @template << (PACK_MAP[t[0]] * t[1])
         
     | 
| 
      
 119 
     | 
    
         
            +
                      addr += (SIZE_MAP[t[0]] * t[1])
         
     | 
| 
      
 120 
     | 
    
         
            +
                    else
         
     | 
| 
      
 121 
     | 
    
         
            +
                      @template << PACK_MAP[t]
         
     | 
| 
      
 122 
     | 
    
         
            +
                      addr += SIZE_MAP[t]
         
     | 
| 
      
 123 
     | 
    
         
            +
                    end
         
     | 
| 
      
 124 
     | 
    
         
            +
                  }
         
     | 
| 
      
 125 
     | 
    
         
            +
                  addr = align(addr, ALIGN_MAP[TYPE_VOIDP])
         
     | 
| 
      
 126 
     | 
    
         
            +
                  @size = addr
         
     | 
| 
      
 127 
     | 
    
         
            +
                end
         
     | 
| 
      
 128 
     | 
    
         
            +
              end
         
     | 
| 
      
 129 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,244 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: false
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'fiddle'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require 'fiddle/value'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'fiddle/pack'
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            module Fiddle
         
     | 
| 
      
 7 
     | 
    
         
            +
              # C struct shell
         
     | 
| 
      
 8 
     | 
    
         
            +
              class CStruct
         
     | 
| 
      
 9 
     | 
    
         
            +
                # accessor to Fiddle::CStructEntity
         
     | 
| 
      
 10 
     | 
    
         
            +
                def CStruct.entity_class
         
     | 
| 
      
 11 
     | 
    
         
            +
                  CStructEntity
         
     | 
| 
      
 12 
     | 
    
         
            +
                end
         
     | 
| 
      
 13 
     | 
    
         
            +
              end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
              # C union shell
         
     | 
| 
      
 16 
     | 
    
         
            +
              class CUnion
         
     | 
| 
      
 17 
     | 
    
         
            +
                # accessor to Fiddle::CUnionEntity
         
     | 
| 
      
 18 
     | 
    
         
            +
                def CUnion.entity_class
         
     | 
| 
      
 19 
     | 
    
         
            +
                  CUnionEntity
         
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
      
 21 
     | 
    
         
            +
              end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
              # Used to construct C classes (CUnion, CStruct, etc)
         
     | 
| 
      
 24 
     | 
    
         
            +
              #
         
     | 
| 
      
 25 
     | 
    
         
            +
              # Fiddle::Importer#struct and Fiddle::Importer#union wrap this functionality in an
         
     | 
| 
      
 26 
     | 
    
         
            +
              # easy-to-use manner.
         
     | 
| 
      
 27 
     | 
    
         
            +
              module CStructBuilder
         
     | 
| 
      
 28 
     | 
    
         
            +
                # Construct a new class given a C:
         
     | 
| 
      
 29 
     | 
    
         
            +
                # * class +klass+ (CUnion, CStruct, or other that provide an
         
     | 
| 
      
 30 
     | 
    
         
            +
                #   #entity_class)
         
     | 
| 
      
 31 
     | 
    
         
            +
                # * +types+ (Fiddle::TYPE_INT, Fiddle::TYPE_SIZE_T, etc., see the C types
         
     | 
| 
      
 32 
     | 
    
         
            +
                #   constants)
         
     | 
| 
      
 33 
     | 
    
         
            +
                # * corresponding +members+
         
     | 
| 
      
 34 
     | 
    
         
            +
                #
         
     | 
| 
      
 35 
     | 
    
         
            +
                # Fiddle::Importer#struct and Fiddle::Importer#union wrap this functionality in an
         
     | 
| 
      
 36 
     | 
    
         
            +
                # easy-to-use manner.
         
     | 
| 
      
 37 
     | 
    
         
            +
                #
         
     | 
| 
      
 38 
     | 
    
         
            +
                # Example:
         
     | 
| 
      
 39 
     | 
    
         
            +
                #
         
     | 
| 
      
 40 
     | 
    
         
            +
                #   require 'fiddle/struct'
         
     | 
| 
      
 41 
     | 
    
         
            +
                #   require 'fiddle/cparser'
         
     | 
| 
      
 42 
     | 
    
         
            +
                #
         
     | 
| 
      
 43 
     | 
    
         
            +
                #   include Fiddle::CParser
         
     | 
| 
      
 44 
     | 
    
         
            +
                #
         
     | 
| 
      
 45 
     | 
    
         
            +
                #   types, members = parse_struct_signature(['int i','char c'])
         
     | 
| 
      
 46 
     | 
    
         
            +
                #
         
     | 
| 
      
 47 
     | 
    
         
            +
                #   MyStruct = Fiddle::CStructBuilder.create(Fiddle::CUnion, types, members)
         
     | 
| 
      
 48 
     | 
    
         
            +
                #
         
     | 
| 
      
 49 
     | 
    
         
            +
                #   obj = MyStruct.allocate
         
     | 
| 
      
 50 
     | 
    
         
            +
                #
         
     | 
| 
      
 51 
     | 
    
         
            +
                def create(klass, types, members)
         
     | 
| 
      
 52 
     | 
    
         
            +
                  new_class = Class.new(klass){
         
     | 
| 
      
 53 
     | 
    
         
            +
                    define_method(:initialize){|addr|
         
     | 
| 
      
 54 
     | 
    
         
            +
                      @entity = klass.entity_class.new(addr, types)
         
     | 
| 
      
 55 
     | 
    
         
            +
                      @entity.assign_names(members)
         
     | 
| 
      
 56 
     | 
    
         
            +
                    }
         
     | 
| 
      
 57 
     | 
    
         
            +
                    define_method(:to_ptr){ @entity }
         
     | 
| 
      
 58 
     | 
    
         
            +
                    define_method(:to_i){ @entity.to_i }
         
     | 
| 
      
 59 
     | 
    
         
            +
                    members.each{|name|
         
     | 
| 
      
 60 
     | 
    
         
            +
                      define_method(name){ @entity[name] }
         
     | 
| 
      
 61 
     | 
    
         
            +
                      define_method(name + "="){|val| @entity[name] = val }
         
     | 
| 
      
 62 
     | 
    
         
            +
                    }
         
     | 
| 
      
 63 
     | 
    
         
            +
                  }
         
     | 
| 
      
 64 
     | 
    
         
            +
                  size = klass.entity_class.size(types)
         
     | 
| 
      
 65 
     | 
    
         
            +
                  new_class.module_eval(<<-EOS, __FILE__, __LINE__+1)
         
     | 
| 
      
 66 
     | 
    
         
            +
                    def new_class.size()
         
     | 
| 
      
 67 
     | 
    
         
            +
                      #{size}
         
     | 
| 
      
 68 
     | 
    
         
            +
                    end
         
     | 
| 
      
 69 
     | 
    
         
            +
                    def new_class.malloc()
         
     | 
| 
      
 70 
     | 
    
         
            +
                      addr = Fiddle.malloc(#{size})
         
     | 
| 
      
 71 
     | 
    
         
            +
                      new(addr)
         
     | 
| 
      
 72 
     | 
    
         
            +
                    end
         
     | 
| 
      
 73 
     | 
    
         
            +
                  EOS
         
     | 
| 
      
 74 
     | 
    
         
            +
                  return new_class
         
     | 
| 
      
 75 
     | 
    
         
            +
                end
         
     | 
| 
      
 76 
     | 
    
         
            +
                module_function :create
         
     | 
| 
      
 77 
     | 
    
         
            +
              end
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
              # A C struct wrapper
         
     | 
| 
      
 80 
     | 
    
         
            +
              class CStructEntity < Fiddle::Pointer
         
     | 
| 
      
 81 
     | 
    
         
            +
                include PackInfo
         
     | 
| 
      
 82 
     | 
    
         
            +
                include ValueUtil
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
                # Allocates a C struct with the +types+ provided.
         
     | 
| 
      
 85 
     | 
    
         
            +
                #
         
     | 
| 
      
 86 
     | 
    
         
            +
                # When the instance is garbage collected, the C function +func+ is called.
         
     | 
| 
      
 87 
     | 
    
         
            +
                def CStructEntity.malloc(types, func = nil)
         
     | 
| 
      
 88 
     | 
    
         
            +
                  addr = Fiddle.malloc(CStructEntity.size(types))
         
     | 
| 
      
 89 
     | 
    
         
            +
                  CStructEntity.new(addr, types, func)
         
     | 
| 
      
 90 
     | 
    
         
            +
                end
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
                # Returns the offset for the packed sizes for the given +types+.
         
     | 
| 
      
 93 
     | 
    
         
            +
                #
         
     | 
| 
      
 94 
     | 
    
         
            +
                #   Fiddle::CStructEntity.size(
         
     | 
| 
      
 95 
     | 
    
         
            +
                #     [ Fiddle::TYPE_DOUBLE,
         
     | 
| 
      
 96 
     | 
    
         
            +
                #       Fiddle::TYPE_INT,
         
     | 
| 
      
 97 
     | 
    
         
            +
                #       Fiddle::TYPE_CHAR,
         
     | 
| 
      
 98 
     | 
    
         
            +
                #       Fiddle::TYPE_VOIDP ]) #=> 24
         
     | 
| 
      
 99 
     | 
    
         
            +
                def CStructEntity.size(types)
         
     | 
| 
      
 100 
     | 
    
         
            +
                  offset = 0
         
     | 
| 
      
 101 
     | 
    
         
            +
             
     | 
| 
      
 102 
     | 
    
         
            +
                  max_align = types.map { |type, count = 1|
         
     | 
| 
      
 103 
     | 
    
         
            +
                    last_offset = offset
         
     | 
| 
      
 104 
     | 
    
         
            +
             
     | 
| 
      
 105 
     | 
    
         
            +
                    align = PackInfo::ALIGN_MAP[type]
         
     | 
| 
      
 106 
     | 
    
         
            +
                    offset = PackInfo.align(last_offset, align) +
         
     | 
| 
      
 107 
     | 
    
         
            +
                             (PackInfo::SIZE_MAP[type] * count)
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
      
 109 
     | 
    
         
            +
                    align
         
     | 
| 
      
 110 
     | 
    
         
            +
                  }.max
         
     | 
| 
      
 111 
     | 
    
         
            +
             
     | 
| 
      
 112 
     | 
    
         
            +
                  PackInfo.align(offset, max_align)
         
     | 
| 
      
 113 
     | 
    
         
            +
                end
         
     | 
| 
      
 114 
     | 
    
         
            +
             
     | 
| 
      
 115 
     | 
    
         
            +
                # Wraps the C pointer +addr+ as a C struct with the given +types+.
         
     | 
| 
      
 116 
     | 
    
         
            +
                #
         
     | 
| 
      
 117 
     | 
    
         
            +
                # When the instance is garbage collected, the C function +func+ is called.
         
     | 
| 
      
 118 
     | 
    
         
            +
                #
         
     | 
| 
      
 119 
     | 
    
         
            +
                # See also Fiddle::Pointer.new
         
     | 
| 
      
 120 
     | 
    
         
            +
                def initialize(addr, types, func = nil)
         
     | 
| 
      
 121 
     | 
    
         
            +
                  set_ctypes(types)
         
     | 
| 
      
 122 
     | 
    
         
            +
                  super(addr, @size, func)
         
     | 
| 
      
 123 
     | 
    
         
            +
                end
         
     | 
| 
      
 124 
     | 
    
         
            +
             
     | 
| 
      
 125 
     | 
    
         
            +
                # Set the names of the +members+ in this C struct
         
     | 
| 
      
 126 
     | 
    
         
            +
                def assign_names(members)
         
     | 
| 
      
 127 
     | 
    
         
            +
                  @members = members
         
     | 
| 
      
 128 
     | 
    
         
            +
                end
         
     | 
| 
      
 129 
     | 
    
         
            +
             
     | 
| 
      
 130 
     | 
    
         
            +
                # Calculates the offsets and sizes for the given +types+ in the struct.
         
     | 
| 
      
 131 
     | 
    
         
            +
                def set_ctypes(types)
         
     | 
| 
      
 132 
     | 
    
         
            +
                  @ctypes = types
         
     | 
| 
      
 133 
     | 
    
         
            +
                  @offset = []
         
     | 
| 
      
 134 
     | 
    
         
            +
                  offset = 0
         
     | 
| 
      
 135 
     | 
    
         
            +
             
     | 
| 
      
 136 
     | 
    
         
            +
                  max_align = types.map { |type, count = 1|
         
     | 
| 
      
 137 
     | 
    
         
            +
                    orig_offset = offset
         
     | 
| 
      
 138 
     | 
    
         
            +
                    align = ALIGN_MAP[type]
         
     | 
| 
      
 139 
     | 
    
         
            +
                    offset = PackInfo.align(orig_offset, align)
         
     | 
| 
      
 140 
     | 
    
         
            +
             
     | 
| 
      
 141 
     | 
    
         
            +
                    @offset << offset
         
     | 
| 
      
 142 
     | 
    
         
            +
             
     | 
| 
      
 143 
     | 
    
         
            +
                    offset += (SIZE_MAP[type] * count)
         
     | 
| 
      
 144 
     | 
    
         
            +
             
     | 
| 
      
 145 
     | 
    
         
            +
                    align
         
     | 
| 
      
 146 
     | 
    
         
            +
                  }.max
         
     | 
| 
      
 147 
     | 
    
         
            +
             
     | 
| 
      
 148 
     | 
    
         
            +
                  @size = PackInfo.align(offset, max_align)
         
     | 
| 
      
 149 
     | 
    
         
            +
                end
         
     | 
| 
      
 150 
     | 
    
         
            +
             
     | 
| 
      
 151 
     | 
    
         
            +
                # Fetch struct member +name+
         
     | 
| 
      
 152 
     | 
    
         
            +
                def [](name)
         
     | 
| 
      
 153 
     | 
    
         
            +
                  idx = @members.index(name)
         
     | 
| 
      
 154 
     | 
    
         
            +
                  if( idx.nil? )
         
     | 
| 
      
 155 
     | 
    
         
            +
                    raise(ArgumentError, "no such member: #{name}")
         
     | 
| 
      
 156 
     | 
    
         
            +
                  end
         
     | 
| 
      
 157 
     | 
    
         
            +
                  ty = @ctypes[idx]
         
     | 
| 
      
 158 
     | 
    
         
            +
                  if( ty.is_a?(Array) )
         
     | 
| 
      
 159 
     | 
    
         
            +
                    r = super(@offset[idx], SIZE_MAP[ty[0]] * ty[1])
         
     | 
| 
      
 160 
     | 
    
         
            +
                  else
         
     | 
| 
      
 161 
     | 
    
         
            +
                    r = super(@offset[idx], SIZE_MAP[ty.abs])
         
     | 
| 
      
 162 
     | 
    
         
            +
                  end
         
     | 
| 
      
 163 
     | 
    
         
            +
                  packer = Packer.new([ty])
         
     | 
| 
      
 164 
     | 
    
         
            +
                  val = packer.unpack([r])
         
     | 
| 
      
 165 
     | 
    
         
            +
                  case ty
         
     | 
| 
      
 166 
     | 
    
         
            +
                  when Array
         
     | 
| 
      
 167 
     | 
    
         
            +
                    case ty[0]
         
     | 
| 
      
 168 
     | 
    
         
            +
                    when TYPE_VOIDP
         
     | 
| 
      
 169 
     | 
    
         
            +
                      val = val.collect{|v| Pointer.new(v)}
         
     | 
| 
      
 170 
     | 
    
         
            +
                    end
         
     | 
| 
      
 171 
     | 
    
         
            +
                  when TYPE_VOIDP
         
     | 
| 
      
 172 
     | 
    
         
            +
                    val = Pointer.new(val[0])
         
     | 
| 
      
 173 
     | 
    
         
            +
                  else
         
     | 
| 
      
 174 
     | 
    
         
            +
                    val = val[0]
         
     | 
| 
      
 175 
     | 
    
         
            +
                  end
         
     | 
| 
      
 176 
     | 
    
         
            +
                  if( ty.is_a?(Integer) && (ty < 0) )
         
     | 
| 
      
 177 
     | 
    
         
            +
                    return unsigned_value(val, ty)
         
     | 
| 
      
 178 
     | 
    
         
            +
                  elsif( ty.is_a?(Array) && (ty[0] < 0) )
         
     | 
| 
      
 179 
     | 
    
         
            +
                    return val.collect{|v| unsigned_value(v,ty[0])}
         
     | 
| 
      
 180 
     | 
    
         
            +
                  else
         
     | 
| 
      
 181 
     | 
    
         
            +
                    return val
         
     | 
| 
      
 182 
     | 
    
         
            +
                  end
         
     | 
| 
      
 183 
     | 
    
         
            +
                end
         
     | 
| 
      
 184 
     | 
    
         
            +
             
     | 
| 
      
 185 
     | 
    
         
            +
                # Set struct member +name+, to value +val+
         
     | 
| 
      
 186 
     | 
    
         
            +
                def []=(name, val)
         
     | 
| 
      
 187 
     | 
    
         
            +
                  idx = @members.index(name)
         
     | 
| 
      
 188 
     | 
    
         
            +
                  if( idx.nil? )
         
     | 
| 
      
 189 
     | 
    
         
            +
                    raise(ArgumentError, "no such member: #{name}")
         
     | 
| 
      
 190 
     | 
    
         
            +
                  end
         
     | 
| 
      
 191 
     | 
    
         
            +
                  ty  = @ctypes[idx]
         
     | 
| 
      
 192 
     | 
    
         
            +
                  packer = Packer.new([ty])
         
     | 
| 
      
 193 
     | 
    
         
            +
                  val = wrap_arg(val, ty, [])
         
     | 
| 
      
 194 
     | 
    
         
            +
                  buff = packer.pack([val].flatten())
         
     | 
| 
      
 195 
     | 
    
         
            +
                  super(@offset[idx], buff.size, buff)
         
     | 
| 
      
 196 
     | 
    
         
            +
                  if( ty.is_a?(Integer) && (ty < 0) )
         
     | 
| 
      
 197 
     | 
    
         
            +
                    return unsigned_value(val, ty)
         
     | 
| 
      
 198 
     | 
    
         
            +
                  elsif( ty.is_a?(Array) && (ty[0] < 0) )
         
     | 
| 
      
 199 
     | 
    
         
            +
                    return val.collect{|v| unsigned_value(v,ty[0])}
         
     | 
| 
      
 200 
     | 
    
         
            +
                  else
         
     | 
| 
      
 201 
     | 
    
         
            +
                    return val
         
     | 
| 
      
 202 
     | 
    
         
            +
                  end
         
     | 
| 
      
 203 
     | 
    
         
            +
                end
         
     | 
| 
      
 204 
     | 
    
         
            +
             
     | 
| 
      
 205 
     | 
    
         
            +
                def to_s() # :nodoc:
         
     | 
| 
      
 206 
     | 
    
         
            +
                  super(@size)
         
     | 
| 
      
 207 
     | 
    
         
            +
                end
         
     | 
| 
      
 208 
     | 
    
         
            +
              end
         
     | 
| 
      
 209 
     | 
    
         
            +
             
     | 
| 
      
 210 
     | 
    
         
            +
              # A C union wrapper
         
     | 
| 
      
 211 
     | 
    
         
            +
              class CUnionEntity < CStructEntity
         
     | 
| 
      
 212 
     | 
    
         
            +
                include PackInfo
         
     | 
| 
      
 213 
     | 
    
         
            +
             
     | 
| 
      
 214 
     | 
    
         
            +
                # Allocates a C union the +types+ provided.
         
     | 
| 
      
 215 
     | 
    
         
            +
                #
         
     | 
| 
      
 216 
     | 
    
         
            +
                # When the instance is garbage collected, the C function +func+ is called.
         
     | 
| 
      
 217 
     | 
    
         
            +
                def CUnionEntity.malloc(types, func=nil)
         
     | 
| 
      
 218 
     | 
    
         
            +
                  addr = Fiddle.malloc(CUnionEntity.size(types))
         
     | 
| 
      
 219 
     | 
    
         
            +
                  CUnionEntity.new(addr, types, func)
         
     | 
| 
      
 220 
     | 
    
         
            +
                end
         
     | 
| 
      
 221 
     | 
    
         
            +
             
     | 
| 
      
 222 
     | 
    
         
            +
                # Returns the size needed for the union with the given +types+.
         
     | 
| 
      
 223 
     | 
    
         
            +
                #
         
     | 
| 
      
 224 
     | 
    
         
            +
                #   Fiddle::CUnionEntity.size(
         
     | 
| 
      
 225 
     | 
    
         
            +
                #     [ Fiddle::TYPE_DOUBLE,
         
     | 
| 
      
 226 
     | 
    
         
            +
                #       Fiddle::TYPE_INT,
         
     | 
| 
      
 227 
     | 
    
         
            +
                #       Fiddle::TYPE_CHAR,
         
     | 
| 
      
 228 
     | 
    
         
            +
                #       Fiddle::TYPE_VOIDP ]) #=> 8
         
     | 
| 
      
 229 
     | 
    
         
            +
                def CUnionEntity.size(types)
         
     | 
| 
      
 230 
     | 
    
         
            +
                  types.map { |type, count = 1|
         
     | 
| 
      
 231 
     | 
    
         
            +
                    PackInfo::SIZE_MAP[type] * count
         
     | 
| 
      
 232 
     | 
    
         
            +
                  }.max
         
     | 
| 
      
 233 
     | 
    
         
            +
                end
         
     | 
| 
      
 234 
     | 
    
         
            +
             
     | 
| 
      
 235 
     | 
    
         
            +
                # Calculate the necessary offset and for each union member with the given
         
     | 
| 
      
 236 
     | 
    
         
            +
                # +types+
         
     | 
| 
      
 237 
     | 
    
         
            +
                def set_ctypes(types)
         
     | 
| 
      
 238 
     | 
    
         
            +
                  @ctypes = types
         
     | 
| 
      
 239 
     | 
    
         
            +
                  @offset = Array.new(types.length, 0)
         
     | 
| 
      
 240 
     | 
    
         
            +
                  @size   = self.class.size types
         
     | 
| 
      
 241 
     | 
    
         
            +
                end
         
     | 
| 
      
 242 
     | 
    
         
            +
              end
         
     | 
| 
      
 243 
     | 
    
         
            +
            end
         
     | 
| 
      
 244 
     | 
    
         
            +
             
     | 
    
        data/lib/fiddle/types.rb
    ADDED
    
    | 
         @@ -0,0 +1,72 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: false
         
     | 
| 
      
 2 
     | 
    
         
            +
            module Fiddle
         
     | 
| 
      
 3 
     | 
    
         
            +
              # Adds Windows type aliases to the including class for use with
         
     | 
| 
      
 4 
     | 
    
         
            +
              # Fiddle::Importer.
         
     | 
| 
      
 5 
     | 
    
         
            +
              #
         
     | 
| 
      
 6 
     | 
    
         
            +
              # The aliases added are:
         
     | 
| 
      
 7 
     | 
    
         
            +
              # * ATOM
         
     | 
| 
      
 8 
     | 
    
         
            +
              # * BOOL
         
     | 
| 
      
 9 
     | 
    
         
            +
              # * BYTE
         
     | 
| 
      
 10 
     | 
    
         
            +
              # * DWORD
         
     | 
| 
      
 11 
     | 
    
         
            +
              # * DWORD32
         
     | 
| 
      
 12 
     | 
    
         
            +
              # * DWORD64
         
     | 
| 
      
 13 
     | 
    
         
            +
              # * HANDLE
         
     | 
| 
      
 14 
     | 
    
         
            +
              # * HDC
         
     | 
| 
      
 15 
     | 
    
         
            +
              # * HINSTANCE
         
     | 
| 
      
 16 
     | 
    
         
            +
              # * HWND
         
     | 
| 
      
 17 
     | 
    
         
            +
              # * LPCSTR
         
     | 
| 
      
 18 
     | 
    
         
            +
              # * LPSTR
         
     | 
| 
      
 19 
     | 
    
         
            +
              # * PBYTE
         
     | 
| 
      
 20 
     | 
    
         
            +
              # * PDWORD
         
     | 
| 
      
 21 
     | 
    
         
            +
              # * PHANDLE
         
     | 
| 
      
 22 
     | 
    
         
            +
              # * PVOID
         
     | 
| 
      
 23 
     | 
    
         
            +
              # * PWORD
         
     | 
| 
      
 24 
     | 
    
         
            +
              # * UCHAR
         
     | 
| 
      
 25 
     | 
    
         
            +
              # * UINT
         
     | 
| 
      
 26 
     | 
    
         
            +
              # * ULONG
         
     | 
| 
      
 27 
     | 
    
         
            +
              # * WORD
         
     | 
| 
      
 28 
     | 
    
         
            +
              module Win32Types
         
     | 
| 
      
 29 
     | 
    
         
            +
                def included(m) # :nodoc:
         
     | 
| 
      
 30 
     | 
    
         
            +
                  m.module_eval{
         
     | 
| 
      
 31 
     | 
    
         
            +
                    typealias "DWORD", "unsigned long"
         
     | 
| 
      
 32 
     | 
    
         
            +
                    typealias "PDWORD", "unsigned long *"
         
     | 
| 
      
 33 
     | 
    
         
            +
                    typealias "DWORD32", "unsigned long"
         
     | 
| 
      
 34 
     | 
    
         
            +
                    typealias "DWORD64", "unsigned long long"
         
     | 
| 
      
 35 
     | 
    
         
            +
                    typealias "WORD", "unsigned short"
         
     | 
| 
      
 36 
     | 
    
         
            +
                    typealias "PWORD", "unsigned short *"
         
     | 
| 
      
 37 
     | 
    
         
            +
                    typealias "BOOL", "int"
         
     | 
| 
      
 38 
     | 
    
         
            +
                    typealias "ATOM", "int"
         
     | 
| 
      
 39 
     | 
    
         
            +
                    typealias "BYTE", "unsigned char"
         
     | 
| 
      
 40 
     | 
    
         
            +
                    typealias "PBYTE", "unsigned char *"
         
     | 
| 
      
 41 
     | 
    
         
            +
                    typealias "UINT", "unsigned int"
         
     | 
| 
      
 42 
     | 
    
         
            +
                    typealias "ULONG", "unsigned long"
         
     | 
| 
      
 43 
     | 
    
         
            +
                    typealias "UCHAR", "unsigned char"
         
     | 
| 
      
 44 
     | 
    
         
            +
                    typealias "HANDLE", "uintptr_t"
         
     | 
| 
      
 45 
     | 
    
         
            +
                    typealias "PHANDLE", "void*"
         
     | 
| 
      
 46 
     | 
    
         
            +
                    typealias "PVOID", "void*"
         
     | 
| 
      
 47 
     | 
    
         
            +
                    typealias "LPCSTR", "char*"
         
     | 
| 
      
 48 
     | 
    
         
            +
                    typealias "LPSTR", "char*"
         
     | 
| 
      
 49 
     | 
    
         
            +
                    typealias "HINSTANCE", "unsigned int"
         
     | 
| 
      
 50 
     | 
    
         
            +
                    typealias "HDC", "unsigned int"
         
     | 
| 
      
 51 
     | 
    
         
            +
                    typealias "HWND", "unsigned int"
         
     | 
| 
      
 52 
     | 
    
         
            +
                  }
         
     | 
| 
      
 53 
     | 
    
         
            +
                end
         
     | 
| 
      
 54 
     | 
    
         
            +
                module_function :included
         
     | 
| 
      
 55 
     | 
    
         
            +
              end
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
              # Adds basic type aliases to the including class for use with Fiddle::Importer.
         
     | 
| 
      
 58 
     | 
    
         
            +
              #
         
     | 
| 
      
 59 
     | 
    
         
            +
              # The aliases added are +uint+ and +u_int+ (<tt>unsigned int</tt>) and
         
     | 
| 
      
 60 
     | 
    
         
            +
              # +ulong+ and +u_long+ (<tt>unsigned long</tt>)
         
     | 
| 
      
 61 
     | 
    
         
            +
              module BasicTypes
         
     | 
| 
      
 62 
     | 
    
         
            +
                def included(m) # :nodoc:
         
     | 
| 
      
 63 
     | 
    
         
            +
                  m.module_eval{
         
     | 
| 
      
 64 
     | 
    
         
            +
                    typealias "uint", "unsigned int"
         
     | 
| 
      
 65 
     | 
    
         
            +
                    typealias "u_int", "unsigned int"
         
     | 
| 
      
 66 
     | 
    
         
            +
                    typealias "ulong", "unsigned long"
         
     | 
| 
      
 67 
     | 
    
         
            +
                    typealias "u_long", "unsigned long"
         
     | 
| 
      
 68 
     | 
    
         
            +
                  }
         
     | 
| 
      
 69 
     | 
    
         
            +
                end
         
     | 
| 
      
 70 
     | 
    
         
            +
                module_function :included
         
     | 
| 
      
 71 
     | 
    
         
            +
              end
         
     | 
| 
      
 72 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/fiddle/value.rb
    ADDED
    
    | 
         @@ -0,0 +1,113 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: false
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'fiddle'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            module Fiddle
         
     | 
| 
      
 5 
     | 
    
         
            +
              module ValueUtil #:nodoc: all
         
     | 
| 
      
 6 
     | 
    
         
            +
                def unsigned_value(val, ty)
         
     | 
| 
      
 7 
     | 
    
         
            +
                  case ty.abs
         
     | 
| 
      
 8 
     | 
    
         
            +
                  when TYPE_CHAR
         
     | 
| 
      
 9 
     | 
    
         
            +
                    [val].pack("c").unpack("C")[0]
         
     | 
| 
      
 10 
     | 
    
         
            +
                  when TYPE_SHORT
         
     | 
| 
      
 11 
     | 
    
         
            +
                    [val].pack("s!").unpack("S!")[0]
         
     | 
| 
      
 12 
     | 
    
         
            +
                  when TYPE_INT
         
     | 
| 
      
 13 
     | 
    
         
            +
                    [val].pack("i!").unpack("I!")[0]
         
     | 
| 
      
 14 
     | 
    
         
            +
                  when TYPE_LONG
         
     | 
| 
      
 15 
     | 
    
         
            +
                    [val].pack("l!").unpack("L!")[0]
         
     | 
| 
      
 16 
     | 
    
         
            +
                  when TYPE_LONG_LONG
         
     | 
| 
      
 17 
     | 
    
         
            +
                    [val].pack("q").unpack("Q")[0]
         
     | 
| 
      
 18 
     | 
    
         
            +
                  else
         
     | 
| 
      
 19 
     | 
    
         
            +
                    val
         
     | 
| 
      
 20 
     | 
    
         
            +
                  end
         
     | 
| 
      
 21 
     | 
    
         
            +
                end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                def signed_value(val, ty)
         
     | 
| 
      
 24 
     | 
    
         
            +
                  case ty.abs
         
     | 
| 
      
 25 
     | 
    
         
            +
                  when TYPE_CHAR
         
     | 
| 
      
 26 
     | 
    
         
            +
                    [val].pack("C").unpack("c")[0]
         
     | 
| 
      
 27 
     | 
    
         
            +
                  when TYPE_SHORT
         
     | 
| 
      
 28 
     | 
    
         
            +
                    [val].pack("S!").unpack("s!")[0]
         
     | 
| 
      
 29 
     | 
    
         
            +
                  when TYPE_INT
         
     | 
| 
      
 30 
     | 
    
         
            +
                    [val].pack("I!").unpack("i!")[0]
         
     | 
| 
      
 31 
     | 
    
         
            +
                  when TYPE_LONG
         
     | 
| 
      
 32 
     | 
    
         
            +
                    [val].pack("L!").unpack("l!")[0]
         
     | 
| 
      
 33 
     | 
    
         
            +
                  when TYPE_LONG_LONG
         
     | 
| 
      
 34 
     | 
    
         
            +
                    [val].pack("Q").unpack("q")[0]
         
     | 
| 
      
 35 
     | 
    
         
            +
                  else
         
     | 
| 
      
 36 
     | 
    
         
            +
                    val
         
     | 
| 
      
 37 
     | 
    
         
            +
                  end
         
     | 
| 
      
 38 
     | 
    
         
            +
                end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                def wrap_args(args, tys, funcs, &block)
         
     | 
| 
      
 41 
     | 
    
         
            +
                  result = []
         
     | 
| 
      
 42 
     | 
    
         
            +
                  tys ||= []
         
     | 
| 
      
 43 
     | 
    
         
            +
                  args.each_with_index{|arg, idx|
         
     | 
| 
      
 44 
     | 
    
         
            +
                    result.push(wrap_arg(arg, tys[idx], funcs, &block))
         
     | 
| 
      
 45 
     | 
    
         
            +
                  }
         
     | 
| 
      
 46 
     | 
    
         
            +
                  result
         
     | 
| 
      
 47 
     | 
    
         
            +
                end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                def wrap_arg(arg, ty, funcs = [], &block)
         
     | 
| 
      
 50 
     | 
    
         
            +
                  funcs ||= []
         
     | 
| 
      
 51 
     | 
    
         
            +
                  case arg
         
     | 
| 
      
 52 
     | 
    
         
            +
                  when nil
         
     | 
| 
      
 53 
     | 
    
         
            +
                    return 0
         
     | 
| 
      
 54 
     | 
    
         
            +
                  when Pointer
         
     | 
| 
      
 55 
     | 
    
         
            +
                    return arg.to_i
         
     | 
| 
      
 56 
     | 
    
         
            +
                  when IO
         
     | 
| 
      
 57 
     | 
    
         
            +
                    case ty
         
     | 
| 
      
 58 
     | 
    
         
            +
                    when TYPE_VOIDP
         
     | 
| 
      
 59 
     | 
    
         
            +
                      return Pointer[arg].to_i
         
     | 
| 
      
 60 
     | 
    
         
            +
                    else
         
     | 
| 
      
 61 
     | 
    
         
            +
                      return arg.to_i
         
     | 
| 
      
 62 
     | 
    
         
            +
                    end
         
     | 
| 
      
 63 
     | 
    
         
            +
                  when Function
         
     | 
| 
      
 64 
     | 
    
         
            +
                    if( block )
         
     | 
| 
      
 65 
     | 
    
         
            +
                      arg.bind_at_call(&block)
         
     | 
| 
      
 66 
     | 
    
         
            +
                      funcs.push(arg)
         
     | 
| 
      
 67 
     | 
    
         
            +
                    elsif !arg.bound?
         
     | 
| 
      
 68 
     | 
    
         
            +
                      raise(RuntimeError, "block must be given.")
         
     | 
| 
      
 69 
     | 
    
         
            +
                    end
         
     | 
| 
      
 70 
     | 
    
         
            +
                    return arg.to_i
         
     | 
| 
      
 71 
     | 
    
         
            +
                  when String
         
     | 
| 
      
 72 
     | 
    
         
            +
                    if( ty.is_a?(Array) )
         
     | 
| 
      
 73 
     | 
    
         
            +
                      return arg.unpack('C*')
         
     | 
| 
      
 74 
     | 
    
         
            +
                    else
         
     | 
| 
      
 75 
     | 
    
         
            +
                      case SIZEOF_VOIDP
         
     | 
| 
      
 76 
     | 
    
         
            +
                      when SIZEOF_LONG
         
     | 
| 
      
 77 
     | 
    
         
            +
                        return [arg].pack("p").unpack("l!")[0]
         
     | 
| 
      
 78 
     | 
    
         
            +
                      when SIZEOF_LONG_LONG
         
     | 
| 
      
 79 
     | 
    
         
            +
                        return [arg].pack("p").unpack("q")[0]
         
     | 
| 
      
 80 
     | 
    
         
            +
                      else
         
     | 
| 
      
 81 
     | 
    
         
            +
                        raise(RuntimeError, "sizeof(void*)?")
         
     | 
| 
      
 82 
     | 
    
         
            +
                      end
         
     | 
| 
      
 83 
     | 
    
         
            +
                    end
         
     | 
| 
      
 84 
     | 
    
         
            +
                  when Float, Integer
         
     | 
| 
      
 85 
     | 
    
         
            +
                    return arg
         
     | 
| 
      
 86 
     | 
    
         
            +
                  when Array
         
     | 
| 
      
 87 
     | 
    
         
            +
                    if( ty.is_a?(Array) ) # used only by struct
         
     | 
| 
      
 88 
     | 
    
         
            +
                      case ty[0]
         
     | 
| 
      
 89 
     | 
    
         
            +
                      when TYPE_VOIDP
         
     | 
| 
      
 90 
     | 
    
         
            +
                        return arg.collect{|v| Integer(v)}
         
     | 
| 
      
 91 
     | 
    
         
            +
                      when TYPE_CHAR
         
     | 
| 
      
 92 
     | 
    
         
            +
                        if( arg.is_a?(String) )
         
     | 
| 
      
 93 
     | 
    
         
            +
                          return val.unpack('C*')
         
     | 
| 
      
 94 
     | 
    
         
            +
                        end
         
     | 
| 
      
 95 
     | 
    
         
            +
                      end
         
     | 
| 
      
 96 
     | 
    
         
            +
                      return arg
         
     | 
| 
      
 97 
     | 
    
         
            +
                    else
         
     | 
| 
      
 98 
     | 
    
         
            +
                      return arg
         
     | 
| 
      
 99 
     | 
    
         
            +
                    end
         
     | 
| 
      
 100 
     | 
    
         
            +
                  else
         
     | 
| 
      
 101 
     | 
    
         
            +
                    if( arg.respond_to?(:to_ptr) )
         
     | 
| 
      
 102 
     | 
    
         
            +
                      return arg.to_ptr.to_i
         
     | 
| 
      
 103 
     | 
    
         
            +
                    else
         
     | 
| 
      
 104 
     | 
    
         
            +
                      begin
         
     | 
| 
      
 105 
     | 
    
         
            +
                        return Integer(arg)
         
     | 
| 
      
 106 
     | 
    
         
            +
                      rescue
         
     | 
| 
      
 107 
     | 
    
         
            +
                        raise(ArgumentError, "unknown argument type: #{arg.class}")
         
     | 
| 
      
 108 
     | 
    
         
            +
                      end
         
     | 
| 
      
 109 
     | 
    
         
            +
                    end
         
     | 
| 
      
 110 
     | 
    
         
            +
                  end
         
     | 
| 
      
 111 
     | 
    
         
            +
                end
         
     | 
| 
      
 112 
     | 
    
         
            +
              end
         
     | 
| 
      
 113 
     | 
    
         
            +
            end
         
     |