[前][次][番号順一覧][スレッド一覧]

ruby-changes:25857

From: tenderlove <ko1@a...>
Date: Wed, 28 Nov 2012 09:09:32 +0900 (JST)
Subject: [ruby-changes:25857] tenderlove:r37914 (trunk): * ext/fiddle/fiddle.c: adding alignment constants for compatibility

tenderlove	2012-11-28 09:02:49 +0900 (Wed, 28 Nov 2012)

  New Revision: 37914

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=37914

  Log:
    * ext/fiddle/fiddle.c: adding alignment constants for compatibility
      with DL.
    * ext/fiddle/fiddle.h: ditto
    * ext/fiddle/lib/fiddle/cparser.rb: importing the C parser for DL
      backwards compatibility.
    * ext/fiddle/lib/fiddle/import.rb: importing the import DSL for DL
      backwards compatibility.
    * ext/fiddle/lib/fiddle/pack.rb: importing structure pack for DL
      backwards compatibility.
    * ext/fiddle/lib/fiddle/value.rb: ditto
    * ext/fiddle/lib/fiddle/struct.rb: importing struct DSL for DL backwards
      compatibility.
    * test/dl/test_c_struct_entry.rb: importing tests
    * test/dl/test_c_union_entity.rb: ditto
    * test/dl/test_cparser.rb: ditto
    * test/dl/test_import.rb: ditto
    * test/fiddle/test_c_struct_entry.rb: ditto
    * test/fiddle/test_c_union_entity.rb: ditto
    * test/fiddle/test_cparser.rb: ditto
    * test/fiddle/test_import.rb: ditto

  Added files:
    trunk/ext/fiddle/lib/fiddle/cparser.rb
    trunk/ext/fiddle/lib/fiddle/import.rb
    trunk/ext/fiddle/lib/fiddle/pack.rb
    trunk/ext/fiddle/lib/fiddle/struct.rb
    trunk/ext/fiddle/lib/fiddle/value.rb
    trunk/test/fiddle/test_c_struct_entry.rb
    trunk/test/fiddle/test_c_union_entity.rb
    trunk/test/fiddle/test_cparser.rb
    trunk/test/fiddle/test_import.rb
  Modified files:
    trunk/ChangeLog
    trunk/ext/fiddle/fiddle.c
    trunk/ext/fiddle/fiddle.h
    trunk/test/dl/test_c_struct_entry.rb
    trunk/test/dl/test_c_union_entity.rb
    trunk/test/dl/test_cparser.rb
    trunk/test/dl/test_import.rb

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 37913)
+++ ChangeLog	(revision 37914)
@@ -1,3 +1,26 @@
+Wed Nov 28 09:00:34 2012  Aaron Patterson <aaron@t...>
+
+	* ext/fiddle/fiddle.c: adding alignment constants for compatibility
+	  with DL.
+	* ext/fiddle/fiddle.h: ditto
+	* ext/fiddle/lib/fiddle/cparser.rb: importing the C parser for DL
+	  backwards compatibility.
+	* ext/fiddle/lib/fiddle/import.rb: importing the import DSL for DL
+	  backwards compatibility.
+	* ext/fiddle/lib/fiddle/pack.rb: importing structure pack for DL
+	  backwards compatibility.
+	* ext/fiddle/lib/fiddle/value.rb: ditto
+	* ext/fiddle/lib/fiddle/struct.rb: importing struct DSL for DL backwards
+	  compatibility.
+	* test/dl/test_c_struct_entry.rb: importing tests
+	* test/dl/test_c_union_entity.rb: ditto
+	* test/dl/test_cparser.rb: ditto
+	* test/dl/test_import.rb: ditto
+	* test/fiddle/test_c_struct_entry.rb: ditto
+	* test/fiddle/test_c_union_entity.rb: ditto
+	* test/fiddle/test_cparser.rb: ditto
+	* test/fiddle/test_import.rb: ditto
+
 Wed Nov 28 08:56:00 2012  Zachary Scott <zachary@z...>
 
 	* doc/globals.rdoc: Add documentation file for magic globals
Index: ext/fiddle/lib/fiddle/pack.rb
===================================================================
--- ext/fiddle/lib/fiddle/pack.rb	(revision 0)
+++ ext/fiddle/lib/fiddle/pack.rb	(revision 37914)
@@ -0,0 +1,128 @@
+require 'fiddle'
+
+module Fiddle
+  module PackInfo
+    ALIGN_MAP = {
+      TYPE_VOIDP => ALIGN_VOIDP,
+      TYPE_CHAR  => ALIGN_CHAR,
+      TYPE_SHORT => ALIGN_SHORT,
+      TYPE_INT   => ALIGN_INT,
+      TYPE_LONG  => ALIGN_LONG,
+      TYPE_FLOAT => ALIGN_FLOAT,
+      TYPE_DOUBLE => ALIGN_DOUBLE,
+      -TYPE_CHAR  => ALIGN_CHAR,
+      -TYPE_SHORT => ALIGN_SHORT,
+      -TYPE_INT   => ALIGN_INT,
+      -TYPE_LONG  => ALIGN_LONG,
+    }
+
+    PACK_MAP = {
+      TYPE_VOIDP => ((SIZEOF_VOIDP == SIZEOF_LONG_LONG) ? "q" : "l!"),
+      TYPE_CHAR  => "c",
+      TYPE_SHORT => "s!",
+      TYPE_INT   => "i!",
+      TYPE_LONG  => "l!",
+      TYPE_FLOAT => "f",
+      TYPE_DOUBLE => "d",
+      -TYPE_CHAR  => "c",
+      -TYPE_SHORT => "s!",
+      -TYPE_INT   => "i!",
+      -TYPE_LONG  => "l!",
+    }
+
+    SIZE_MAP = {
+      TYPE_VOIDP => SIZEOF_VOIDP,
+      TYPE_CHAR  => SIZEOF_CHAR,
+      TYPE_SHORT => SIZEOF_SHORT,
+      TYPE_INT   => SIZEOF_INT,
+      TYPE_LONG  => SIZEOF_LONG,
+      TYPE_FLOAT => SIZEOF_FLOAT,
+      TYPE_DOUBLE => SIZEOF_DOUBLE,
+      -TYPE_CHAR  => SIZEOF_CHAR,
+      -TYPE_SHORT => SIZEOF_SHORT,
+      -TYPE_INT   => SIZEOF_INT,
+      -TYPE_LONG  => SIZEOF_LONG,
+    }
+    if defined?(TYPE_LONG_LONG)
+      ALIGN_MAP[TYPE_LONG_LONG] = ALIGN_MAP[-TYPE_LONG_LONG] = ALIGN_LONG_LONG
+      PACK_MAP[TYPE_LONG_LONG] = PACK_MAP[-TYPE_LONG_LONG] = "q"
+      SIZE_MAP[TYPE_LONG_LONG] = SIZE_MAP[-TYPE_LONG_LONG] = SIZEOF_LONG_LONG
+    end
+
+    def align(addr, align)
+      d = addr % align
+      if( d == 0 )
+        addr
+      else
+        addr + (align - d)
+      end
+    end
+    module_function :align
+  end
+
+  class Packer
+    include PackInfo
+
+    def self.[](*types)
+      new(types)
+    end
+
+    def initialize(types)
+      parse_types(types)
+    end
+
+    def size()
+      @size
+    end
+
+    def pack(ary)
+      case SIZEOF_VOIDP
+      when SIZEOF_LONG
+        ary.pack(@template)
+      when SIZEOF_LONG_LONG
+        ary.pack(@template)
+      else
+        raise(RuntimeError, "sizeof(void*)?")
+      end
+    end
+
+    def unpack(ary)
+      case SIZEOF_VOIDP
+      when SIZEOF_LONG
+        ary.join().unpack(@template)
+      when SIZEOF_LONG_LONG
+        ary.join().unpack(@template)
+      else
+        raise(RuntimeError, "sizeof(void*)?")
+      end
+    end
+
+    private
+
+    def parse_types(types)
+      @template = ""
+      addr     = 0
+      types.each{|t|
+        orig_addr = addr
+        if( t.is_a?(Array) )
+          addr = align(orig_addr, ALIGN_MAP[TYPE_VOIDP])
+        else
+          addr = align(orig_addr, ALIGN_MAP[t])
+        end
+        d = addr - orig_addr
+        if( d > 0 )
+          @template << "x#{d}"
+        end
+        if( t.is_a?(Array) )
+          @template << (PACK_MAP[t[0]] * t[1])
+          addr += (SIZE_MAP[t[0]] * t[1])
+        else
+          @template << PACK_MAP[t]
+          addr += SIZE_MAP[t]
+        end
+      }
+      addr = align(addr, ALIGN_MAP[TYPE_VOIDP])
+      @size = addr
+    end
+  end
+end
Index: ext/fiddle/lib/fiddle/cparser.rb
===================================================================
--- ext/fiddle/lib/fiddle/cparser.rb	(revision 0)
+++ ext/fiddle/lib/fiddle/cparser.rb	(revision 37914)
@@ -0,0 +1,156 @@
+module Fiddle
+  # Methods for parsing C struct and C prototype signatures.
+  module CParser
+    # Parses a C struct's members
+    #
+    # Example:
+    #
+    #   parse_struct_signature(['int i', 'char c'])
+    #   => [[Fiddle::TYPE_INT, Fiddle::TYPE_CHAR], ["i", "c"]]
+    #
+    def parse_struct_signature(signature, tymap=nil)
+      if( signature.is_a?(String) )
+        signature = signature.split(/\s*,\s*/)
+      end
+      mems = []
+      tys  = []
+      signature.each{|msig|
+        tks = msig.split(/\s+(\*)?/)
+        ty = tks[0..-2].join(" ")
+        member = tks[-1]
+
+        case ty
+        when /\[(\d+)\]/
+          n = $1.to_i
+          ty.gsub!(/\s*\[\d+\]/,"")
+          ty = [ty, n]
+        when /\[\]/
+          ty.gsub!(/\s*\[\]/, "*")
+        end
+
+        case member
+        when /\[(\d+)\]/
+          ty = [ty, $1.to_i]
+          member.gsub!(/\s*\[\d+\]/,"")
+        when /\[\]/
+          ty = ty + "*"
+          member.gsub!(/\s*\[\]/, "")
+        end
+
+        mems.push(member)
+        tys.push(parse_ctype(ty,tymap))
+      }
+      return tys, mems
+    end
+
+    # Parses a C prototype signature
+    #
+    # Example:
+    #
+    #   include Fiddle::CParser
+    #   => Object
+    #
+    #   parse_signature('double sum(double, double)')
+    #   => ["sum", Fiddle::TYPE_DOUBLE, [Fiddle::TYPE_DOUBLE, Fiddle::TYPE_DOUBLE]]
+    #
+    def parse_signature(signature, tymap=nil)
+      tymap ||= {}
+      signature = signature.gsub(/\s+/, " ").strip
+      case signature
+      when /^([\w@\*\s]+)\(([\w\*\s\,\[\]]*)\)$/
+        ret = $1
+        (args = $2).strip!
+        ret = ret.split(/\s+/)
+        args = args.split(/\s*,\s*/)
+        func = ret.pop
+        if( func =~ /^\*/ )
+          func.gsub!(/^\*+/,"")
+          ret.push("*")
+        end
+        ret  = ret.join(" ")
+        return [func, parse_ctype(ret, tymap), args.collect{|arg| parse_ctype(arg, tymap)}]
+      else
+        raise(RuntimeError,"can't parse the function prototype: #{signature}")
+      end
+    end
+
+    # Given a String of C type +ty+, return the corresponding DL constant.
+    #
+    # +ty+ can also accept an Array of C type Strings, and will returned in a
+    # corresponding Array.
+    #
+    # If Hash +tymap+ is provided, +ty+ is expected to be the key, and the
+    # value will be the C type to be looked up.
+    #
+    # Example:
+    #
+    #   parse_ctype('int')
+    #   => Fiddle::TYPE_INT
+    #
+    #   parse_ctype('double')
+    #   => Fiddle::TYPE_DOUBLE
+    #
+    #   parse_ctype('unsigned char')
+    #   => -Fiddle::TYPE_CHAR
+    #
+    def parse_ctype(ty, tymap=nil)
+      tymap ||= {}
+      case ty
+      when Array
+        return [parse_ctype(ty[0], tymap), ty[1]]
+      when "void"
+        return TYPE_VOID
+      when "char"
+        return TYPE_CHAR
+      when "unsigned char"
+        return  -TYPE_CHAR
+      when "short"
+        return TYPE_SHORT
+      when "unsigned short"
+        return -TYPE_SHORT
+      when "int"
+        return TYPE_INT
+      when "unsigned int", 'uint'
+        return -TYPE_INT
+      when "long"
+        return TYPE_LONG
+      when "unsigned long"
+        return -TYPE_LONG
+      when "long long"
+        if( defined?(TYPE_LONG_LONG) )
+          return TYPE_LONG_LONG
+        else
+          raise(RuntimeError, "unsupported type: #{ty}")
+        end
+      when "unsigned long long"
+        if( defined?(TYPE_LONG_LONG) )
+          return -TYPE_LONG_LONG
+        else
+          raise(RuntimeError, "unsupported type: #{ty}")
+        end
+      when "float"
+        return TYPE_FLOAT
+      when "double"
+        return TYPE_DOUBLE
+      when "size_t"
+        return TYPE_SIZE_T
+      when "ssize_t"
+        return TYPE_SSIZE_T
+      when "ptrdiff_t"
+        return TYPE_PTRDIFF_T
+      when "intptr_t"
+        return TYPE_INTPTR_T
+      when "uintptr_t"
+        return TYPE_UINTPTR_T
+      when /\*/, /\[\s*\]/
+        return TYPE_VOIDP
+      else
+        if( tymap[ty] )
+          return parse_ctype(tymap[ty], tymap)
+        else
+          raise(DLError, "unknown type: #{ty}")
+        end
+      end
+    end
+  end
+end
Index: ext/fiddle/lib/fiddle/struct.rb
===================================================================
--- ext/fiddle/lib/fiddle/struct.rb	(revision 0)
+++ ext/fiddle/lib/fiddle/struct.rb	(revision 37914)
@@ -0,0 +1,236 @@
+require 'fiddle'
+require 'fiddle/value'
+require 'fiddle/pack'
+
+module Fiddle
+  # C struct shell
+  class CStruct
+    # accessor to Fiddle::CStructEntity
+    def CStruct.entity_class
+      CStructEntity
+    end
+  end
+
+  # C union shell
+  class CUnion
+    # accessor to Fiddle::CUnionEntity
+    def CUnion.entity_class
+      CUnionEntity
+    end
+  end
+
+  # Used to construct C classes (CUnion, CStruct, etc)
+  #
+  # Fiddle::Importer#struct and Fiddle::Importer#union wrap this functionality in an
+  # easy-to-use manner.
+  module CStructBuilder
+    # Construct a new class given a C:
+    # * class +klass+ (CUnion, CStruct, or other that provide an
+    #   #entity_class)
+    # * +types+ (Fiddle::TYPE_INT, Fiddle::TYPE_SIZE_T, etc., see the C types
+    #   constants)
+    # * corresponding +members+
+    #
+    # Fiddle::Importer#struct and Fiddle::Importer#union wrap this functionality in an
+    # easy-to-use manner.
+    #
+    # Example:
+    #
+    #   require 'dl/struct'
+    #   require 'dl/cparser'
+    #
+    #   include Fiddle::CParser
+    #
+    #   types, members = parse_struct_signature(['int i','char c'])
+    #
+    #   MyStruct = Fiddle::CStructBuilder.create(CUnion, types, members)
+    #
+    #   obj = MyStruct.allocate
+    #
+    def create(klass, types, members)
+      new_class = Class.new(klass){
+        define_method(:initialize){|addr|
+          @entity = klass.entity_class.new(addr, types)
+          @entity.assign_names(members)
+        }
+        define_method(:to_ptr){ @entity }
+        define_method(:to_i){ @entity.to_i }
+        members.each{|name|
+          define_method(name){ @entity[name] }
+          define_method(name + "="){|val| @entity[name] = val }
+        }
+      }
+      size = klass.entity_class.size(types)
+      new_class.module_eval(<<-EOS, __FILE__, __LINE__+1)
+        def new_class.size()
+          #{size}
+        end
+        def new_class.malloc()
+          addr = Fiddle.malloc(#{size})
+          new(addr)
+        end
+      EOS
+      return new_class
+    end
+    module_function :create
+  end
+
+  # A C struct wrapper
+  class CStructEntity < Fiddle::Pointer
+    include PackInfo
+    include ValueUtil
+
+    # Allocates a C struct the +types+ provided.  The C function +func+ is
+    # called when the instance is garbage collected.
+    def CStructEntity.malloc(types, func = nil)
+      addr = Fiddle.malloc(CStructEntity.size(types))
+      CStructEntity.new(addr, types, func)
+    end
+
+    # Given +types+, returns the offset for the packed sizes of those types
+    #
+    #   Fiddle::CStructEntity.size([Fiddle::TYPE_DOUBLE, Fiddle::TYPE_INT, Fiddle::TYPE_CHAR,
+    #                           Fiddle::TYPE_VOIDP])
+    #   => 24
+    def CStructEntity.size(types)
+      offset = 0
+
+      max_align = types.map { |type, count = 1|
+        last_offset = offset
+
+        align = PackInfo::ALIGN_MAP[type]
+        offset = PackInfo.align(last_offset, align) +
+                 (PackInfo::SIZE_MAP[type] * count)
+
+        align
+      }.max
+
+      PackInfo.align(offset, max_align)
+    end
+
+    # Wraps the C pointer +addr+ as a C struct with the given +types+.  The C
+    # function +func+ is called when the instance is garbage collected.
+    #
+    # See also Fiddle::CPtr.new
+    def initialize(addr, types, func = nil)
+      set_ctypes(types)
+      super(addr, @size, func)
+    end
+
+    # Set the names of the +members+ in this C struct
+    def assign_names(members)
+      @members = members
+    end
+
+    # Given +types+, calculate the offsets and sizes for the types in the
+    # struct.
+    def set_ctypes(types)
+      @ctypes = types
+      @offset = []
+      offset = 0
+
+      max_align = types.map { |type, count = 1|
+        orig_offset = offset
+        align = ALIGN_MAP[type]
+        offset = PackInfo.align(orig_offset, align)
+
+        @offset << offset
+
+        offset += (SIZE_MAP[type] * count)
+
+        align
+      }.max
+
+      @size = PackInfo.align(offset, max_align)
+    end
+
+    # Fetch struct member +name+
+    def [](name)
+      idx = @members.index(name)
+      if( idx.nil? )
+        raise(ArgumentError, "no such member: #{name}")
+      end
+      ty = @ctypes[idx]
+      if( ty.is_a?(Array) )
+        r = super(@offset[idx], SIZE_MAP[ty[0]] * ty[1])
+      else
+        r = super(@offset[idx], SIZE_MAP[ty.abs])
+      end
+      packer = Packer.new([ty])
+      val = packer.unpack([r])
+      case ty
+      when Array
+        case ty[0]
+        when TYPE_VOIDP
+          val = val.collect{|v| CPtr.new(v)}
+        end
+      when TYPE_VOIDP
+        val = CPtr.new(val[0])
+      else
+        val = val[0]
+      end
+      if( ty.is_a?(Integer) && (ty < 0) )
+        return unsigned_value(val, ty)
+      elsif( ty.is_a?(Array) && (ty[0] < 0) )
+        return val.collect{|v| unsigned_value(v,ty[0])}
+      else
+        return val
+      end
+    end
+
+    # Set struct member +name+, to value +val+
+    def []=(name, val)
+      idx = @members.index(name)
+      if( idx.nil? )
+        raise(ArgumentError, "no such member: #{name}")
+      end
+      ty  = @ctypes[idx]
+      packer = Packer.new([ty])
+      val = wrap_arg(val, ty, [])
+      buff = packer.pack([val].flatten())
+      super(@offset[idx], buff.size, buff)
+      if( ty.is_a?(Integer) && (ty < 0) )
+        return unsigned_value(val, ty)
+      elsif( ty.is_a?(Array) && (ty[0] < 0) )
+        return val.collect{|v| unsigned_value(v,ty[0])}
+      else
+        return val
+      end
+    end
+
+    def to_s() # :nodoc:
+      super(@size)
+    end
+  end
+
+  # A C union wrapper
+  class CUnionEntity < CStructEntity
+    include PackInfo
+
+    # Allocates a C union the +types+ provided.  The C function +func+ is
+    # called when the instance is garbage collected.
+    def CUnionEntity.malloc(types, func=nil)
+      addr = Fiddle.malloc(CUnionEntity.size(types))
+      CUnionEntity.new(addr, types, func)
+    end
+
+    # Given +types+, returns the size needed for the union.
+    #
+    #   Fiddle::CUnionEntity.size([Fiddle::TYPE_DOUBLE, Fiddle::TYPE_INT, Fiddle::TYPE_CHAR,
+    #                          Fiddle::TYPE_VOIDP])
+    #   => 8
+    def CUnionEntity.size(types)
+      types.map { |type, count = 1|
+        PackInfo::SIZE_MAP[type] * count
+      }.max
+    end
+
+    # Given +types+, calculate the necessary offset and for each union member
+    def set_ctypes(types)
+      @ctypes = types
+      @offset = Array.new(types.length, 0)
+      @size   = self.class.size types
+    end
+  end
+end
+
Index: ext/fiddle/lib/fiddle/import.rb
===================================================================
--- ext/fiddle/lib/fiddle/import.rb	(revision 0)
+++ ext/fiddle/lib/fiddle/import.rb	(revision 37914)
@@ -0,0 +1,241 @@
+require 'fiddle'
+require 'fiddle/struct'
+require 'fiddle/cparser'
+
+module Fiddle
+  class CompositeHandler
+    def initialize(handlers)
+      @handlers = handlers
+    end
+
+    def handlers()
+      @handlers
+    end
+
+    def sym(symbol)
+      @handlers.each{|handle|
+        if( handle )
+          begin
+            addr = handle.sym(symbol)
+            return addr
+          rescue DLError
+          end
+        end
+      }
+      return nil
+    end
+
+    def [](symbol)
+      sym(symbol)
+    end
+  end
+
+  # DL::Importer includes the means to dynamically load libraries and build
+  # modules around them including calling extern functions within the C
+  # library that has been loaded.
+  #
+  # == Example
+  #
+  #   require 'dl'
+  #   require 'dl/import'
+  #
+  #   module LibSum
+  #   	extend DL::Importer
+  #   	dlload './libsum.so'
+  #   	extern 'double sum(double*, int)'
+  #   	extern 'double split(double)'
+  #   end
+	#
+  module Importer
+    include Fiddle
+    include CParser
+    extend Importer
+
+    def dlload(*libs)
+      handles = libs.collect{|lib|
+        case lib
+        when nil
+          nil
+        when Handle
+          lib
+        when Importer
+          lib.handlers
+        else
+          begin
+            Fiddle.dlopen(lib)
+          rescue DLError
+            raise(DLError, "can't load #{lib}")
+          end
+        end
+      }.flatten()
+      @handler = CompositeHandler.new(handles)
+      @func_map = {}
+      @type_alias = {}
+    end
+
+    def typealias(alias_type, orig_type)
+      @type_alias[alias_type] = orig_type
+    end
+
+    def sizeof(ty)
+      case ty
+      when String
+        ty = parse_ctype(ty, @type_alias).abs()
+        case ty
+        when TYPE_CHAR
+          return SIZEOF_CHAR
+        when TYPE_SHORT
+          return SIZEOF_SHORT
+        when TYPE_INT
+          return SIZEOF_INT
+        when TYPE_LONG
+          return SIZEOF_LONG
+        when TYPE_LONG_LONG
+          return SIZEOF_LONG_LON
+        when TYPE_FLOAT
+          return SIZEOF_FLOAT
+        when TYPE_DOUBLE
+          return SIZEOF_DOUBLE
+        when TYPE_VOIDP
+          return SIZEOF_VOIDP
+        else
+          raise(DLError, "unknown type: #{ty}")
+        end
+      when Class
+        if( ty.instance_methods().include?(:to_ptr) )
+          return ty.size()
+        end
+      end
+      return CPtr[ty].size()
+    end
+
+    def parse_bind_options(opts)
+      h = {}
+      while( opt = opts.shift() )
+        case opt
+        when :stdcall, :cdecl
+          h[:call_type] = opt
+        when :carried, :temp, :temporal, :bind
+          h[:callback_type] = opt
+          h[:carrier] = opts.shift()
+        else
+          h[opt] = true
+        end
+      end
+      h
+    end
+    private :parse_bind_options
+
+    def extern(signature, *opts)
+      symname, ctype, argtype = parse_signature(signature, @type_alias)
+      opt = parse_bind_options(opts)
+      f = import_function(symname, ctype, argtype, opt[:call_type])
+      name = symname.gsub(/@.+/,'')
+      @func_map[name] = f
+      # define_method(name){|*args,&block| f.call(*args,&block)}
+      begin
+        /^(.+?):(\d+)/ =~ caller.first
+        file, line = $1, $2.to_i
+      rescue
+        file, line = __FILE__, __LINE__+3
+      end
+      module_eval(<<-EOS, file, line)
+        def #{name}(*args, &block)
+          @func_map['#{name}'].call(*args,&block)
+        end
+      EOS
+      module_function(name)
+      f
+    end
+
+    def bind(signature, *opts, &blk)
+      name, ctype, argtype = parse_signature(signature, @type_alias)
+      h = parse_bind_options(opts)
+      case h[:callback_type]
+      when :bind, nil
+        f = bind_function(name, ctype, argtype, h[:call_type], &blk)
+      else
+        raise(RuntimeError, "unknown callback type: #{h[:callback_type]}")
+      end
+      @func_map[name (... truncated)

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]