module DL::Importer

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

Public Instance Methods

[](name) click to toggle source
# File ext/dl/lib/dl/import.rb, line 203
def [](name)
  @func_map[name]
end
bind(signature, *opts, &blk) click to toggle source
# File ext/dl/lib/dl/import.rb, line 154
    def bind(signature, *opts, &blk)
      @type_alias ||= nil
      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)
      when :temp, :temporal
        f = create_temp_function(name, ctype, argtype, h[:call_type])
      when :carried
        f = create_carried_function(name, ctype, argtype, h[:call_type], h[:carrier])
      else
        raise(RuntimeError, "unknown callback type: #{h[:callback_type]}")
      end
      @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("        def #{name}(*args,&block)
          @func_map['#{name}'].call(*args,&block)
        end
", file, line)
      module_function(name)
      f
    end
bind_function(name, ctype, argtype, call_type = nil, &block) click to toggle source
# File ext/dl/lib/dl/import.rb, line 244
def bind_function(name, ctype, argtype, call_type = nil, &block)
  if DL.fiddle?
    klass = Function.instance_eval { class_fiddle_closure_cfunc }
    abi = Function.instance_eval { call_type_to_abi(call_type) }
    closure = Class.new(klass) {
      define_method(:call, block)
    }.new(ctype, argtype, abi, name)

    Function.new(closure, argtype, abi)
  else
    f = Function.new(CFunc.new(0, ctype, name, call_type || :cdecl), argtype)
    f.bind(&block)
    f
  end
end
create_carried_function(name, ctype, argtype, call_type = nil, n = 0) click to toggle source
# File ext/dl/lib/dl/import.rb, line 264
def create_carried_function(name, ctype, argtype, call_type = nil, n = 0)
  CarriedFunction.new(CFunc.new(0, ctype, name, call_type || :cdecl), argtype, n)
end
create_temp_function(name, ctype, argtype, call_type = nil) click to toggle source
# File ext/dl/lib/dl/import.rb, line 260
def create_temp_function(name, ctype, argtype, call_type = nil)
  TempFunction.new(CFunc.new(0, ctype, name, call_type || :cdecl), argtype)
end
create_value(ty, val=nil) click to toggle source
# File ext/dl/lib/dl/import.rb, line 207
def create_value(ty, val=nil)
  s = struct([ty + " value"])
  ptr = s.malloc()
  if( val )
    ptr.value = val
  end
  return ptr
end
Also aliased as: value
dlload(*libs) click to toggle source
# File ext/dl/lib/dl/import.rb, line 55
def dlload(*libs)
  handles = libs.collect{|lib|
    case lib
    when nil
      nil
    when Handle
      lib
    when Importer
      lib.handlers
    else
      begin
        DL.dlopen(lib)
      rescue DLError
        raise(DLError, "can't load #{lib}")
      end
    end
  }.flatten()
  @handler = CompositeHandler.new(handles)
  @func_map = {}
  @type_alias = {}
end
extern(signature, *opts) click to toggle source
# File ext/dl/lib/dl/import.rb, line 131
    def extern(signature, *opts)
      @type_alias ||= nil
      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("        def #{name}(*args, &block)
          @func_map['#{name}'].call(*args,&block)
        end
", file, line)
      module_function(name)
      f
    end
handler() click to toggle source
# File ext/dl/lib/dl/import.rb, line 223
def handler
  defined?(@handler) or raise "call dlload before importing symbols and functions"
  @handler
end
import_function(name, ctype, argtype, call_type = nil) click to toggle source
# File ext/dl/lib/dl/import.rb, line 236
def import_function(name, ctype, argtype, call_type = nil)
  addr = handler.sym(name)
  if( !addr )
    raise(DLError, "cannot find the function: #{name}()")
  end
  Function.new(CFunc.new(addr, ctype, name, call_type || :cdecl), argtype)
end
import_symbol(name) click to toggle source
# File ext/dl/lib/dl/import.rb, line 228
def import_symbol(name)
  addr = handler.sym(name)
  if( !addr )
    raise(DLError, "cannot find the symbol: #{name}")
  end
  CPtr.new(addr)
end
import_value(ty, addr) click to toggle source
# File ext/dl/lib/dl/import.rb, line 217
def import_value(ty, addr)
  s = struct([ty + " value"])
  ptr = s.new(addr)
  return ptr
end
sizeof(ty) click to toggle source
# File ext/dl/lib/dl/import.rb, line 81
def sizeof(ty)
  @type_alias ||= nil
  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
struct(signature) click to toggle source

Creates a class to wrap the C struct described by signature.

MyStruct = struct ['int i', 'char c']
# File ext/dl/lib/dl/import.rb, line 188
def struct(signature)
  @type_alias ||= nil
  tys, mems = parse_struct_signature(signature, @type_alias)
  DL::CStructBuilder.create(CStruct, tys, mems)
end
typealias(alias_type, orig_type) click to toggle source
# File ext/dl/lib/dl/import.rb, line 77
def typealias(alias_type, orig_type)
  @type_alias[alias_type] = orig_type
end
union(signature) click to toggle source

Creates a class to wrap the C union described by signature.

MyUnion = union ['int i', 'char c']
# File ext/dl/lib/dl/import.rb, line 197
def union(signature)
  @type_alias ||= nil
  tys, mems = parse_struct_signature(signature, @type_alias)
  DL::CStructBuilder.create(CUnion, tys, mems)
end
value(ty, val=nil)
Alias for: create_value

Private Instance Methods

parse_bind_options(opts) click to toggle source
# File ext/dl/lib/dl/import.rb, line 114
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