In Files

  • dl/lib/dl/func.rb

DL::Function

Public Class Methods

new(cfunc, argtypes, abi = nil, &block) click to toggle source
 
               # File dl/lib/dl/func.rb, line 51
def initialize cfunc, argtypes, abi = nil, &block
  if DL.fiddle?
    abi ||= CALL_TYPE_TO_ABI[(cfunc.calltype rescue nil)]
    if block_given?
      @cfunc = Class.new(FiddleClosureCFunc) {
        define_method(:call, block)
      }.new(cfunc.ctype, argtypes, abi, cfunc.name)
    else
      @cfunc  = cfunc
    end

    @args   = argtypes
    super(@cfunc, @args.reject { |x| x == TYPE_VOID }, cfunc.ctype, abi)
  else
    @cfunc = cfunc
    @stack = Stack.new(argtypes.collect{|ty| ty.abs})
    if( @cfunc.ctype < 0 )
      @cfunc.ctype = @cfunc.ctype.abs
      @unsigned = true
    else
      @unsigned = false
    end
    if block_given?
      bind(&block)
    end
  end
end
            

Public Instance Methods

bind(&block) click to toggle source
 
               # File dl/lib/dl/func.rb, line 117
def bind(&block)
  if DL.fiddle?
    @cfunc = Class.new(FiddleClosureCFunc) {
      def initialize ctype, args, abi, name, block
        super(ctype, args, abi, name)
        @block = block
      end

      def call *args
        @block.call(*args)
      end
    }.new(@cfunc.ctype, @args, abi, name, block)
    @ptr = @cfunc
    return nil
  else
    if( !block )
      raise(RuntimeError, "block must be given.")
    end
    if( @cfunc.ptr == 0 )
      cb = Proc.new{|*args|
        ary = @stack.unpack(args)
        @stack.types.each_with_index{|ty, idx|
          case ty
          when TYPE_VOIDP
            ary[idx] = CPtr.new(ary[idx])
          end
        }
        r = block.call(*ary)
        wrap_arg(r, @cfunc.ctype, [])
      }
      case @cfunc.calltype
      when :cdecl
        @cfunc.ptr = set_cdecl_callback(@cfunc.ctype, @stack.size, &cb)
      when :stdcall
        @cfunc.ptr = set_stdcall_callback(@cfunc.ctype, @stack.size, &cb)
      else
        raise(RuntimeError, "unsupported calltype: #{@cfunc.calltype}")
      end
      if( @cfunc.ptr == 0 )
        raise(RuntimeException, "can't bind C function.")
      end
    end
  end
end
            
bind_at_call(&block) click to toggle source
 
               # File dl/lib/dl/func.rb, line 199
def bind_at_call(&block)
  bind(&block)
end
            
bound?() click to toggle source
 
               # File dl/lib/dl/func.rb, line 195
def bound?()
  @cfunc.ptr != 0
end
            
call(*args, &block) click to toggle source
 
               # File dl/lib/dl/func.rb, line 87
def call(*args, &block)
  if DL.fiddle?
    if block_given?
      args.find { |a| DL::Function === a }.bind_at_call(&block)
    end
    super
  else
    funcs = []
    if $SAFE >= 1 && args.any? { |x| x.tainted? }
      raise SecurityError, "tainted parameter not allowed"
    end
    _args = wrap_args(args, @stack.types, funcs, &block)
    r = @cfunc.call(@stack.pack(_args))
    funcs.each{|f| f.unbind_at_call()}
    return wrap_result(r)
  end
end
            
name() click to toggle source
 
               # File dl/lib/dl/func.rb, line 83
def name
  @cfunc.name
end
            
to_i() click to toggle source
 
               # File dl/lib/dl/func.rb, line 79
def to_i()
  @cfunc.to_i
end
            
unbind() click to toggle source
 
               # File dl/lib/dl/func.rb, line 162
def unbind()
  if DL.fiddle? then
    if @cfunc.kind_of?(Fiddle::Closure) and @cfunc.ptr != 0 then
      call_type = case abi
                  when CALL_TYPE_TO_ABI[nil]
                    nil
                  when CALL_TYPE_TO_ABI[:stdcall]
                    :stdcall
                  else
                    raise(RuntimeError, "unsupported abi: #{abi}")
                  end
      @cfunc = CFunc.new(0, @cfunc.ctype, name, call_type)
      return 0
    elsif @cfunc.ptr != 0 then
      @cfunc.ptr = 0
      return 0
    else
      return nil
    end
  end
  if( @cfunc.ptr != 0 )
    case @cfunc.calltype
    when :cdecl
      remove_cdecl_callback(@cfunc.ptr, @cfunc.ctype)
    when :stdcall
      remove_stdcall_callback(@cfunc.ptr, @cfunc.ctype)
    else
      raise(RuntimeError, "unsupported calltype: #{@cfunc.calltype}")
    end
    @cfunc.ptr = 0
  end
end
            
unbind_at_call() click to toggle source
 
               # File dl/lib/dl/func.rb, line 203
def unbind_at_call()
end
            
wrap_result(r) click to toggle source
 
               # File dl/lib/dl/func.rb, line 105
def wrap_result(r)
  case @cfunc.ctype
  when TYPE_VOIDP
    r = CPtr.new(r)
  else
    if( @unsigned )
      r = unsigned_value(r, @cfunc.ctype)
    end
  end
  r
end
            

Commenting is here to help enhance the documentation. For example, code samples, or clarification of the documentation.

If you have questions about Ruby or the documentation, please post to one of the Ruby mailing lists. You will get better, faster, help that way.

If you wish to post a correction of the docs, please do so, but also file bug report so that it can be corrected for the next release. Thank you.

If you want to help improve the Ruby documentation, please visit Documenting-ruby.org.

blog comments powered by Disqus