Module: DL::Importer

Extended by:
Importer
Includes:
DL, CParser
Included in:
Importer, Win32::Registry::API, Win32::Registry::Error::Kernel32, Win32::Resolv::Kernel32
Defined in:
lib/dl/import.rb

Overview

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

Constant Summary

Constants included from DL

ALIGN_CHAR, ALIGN_DOUBLE, ALIGN_FLOAT, ALIGN_INT, ALIGN_LONG, ALIGN_LONG_LONG, ALIGN_SHORT, ALIGN_VOIDP, BUILD_RUBY_PLATFORM, BUILD_RUBY_VERSION, CdeclCallbackAddrs, CdeclCallbackProcs, DLSTACK_SIZE, MAX_CALLBACK, NULL, RTLD_GLOBAL, RTLD_LAZY, RTLD_NOW, RUBY_FREE, SEM, SIZEOF_CHAR, SIZEOF_DOUBLE, SIZEOF_FLOAT, SIZEOF_INT, SIZEOF_LONG, SIZEOF_LONG_LONG, SIZEOF_SHORT, SIZEOF_VOIDP, StdcallCallbackAddrs, StdcallCallbackProcs, TYPE_CHAR, TYPE_DOUBLE, TYPE_FLOAT, TYPE_INT, TYPE_LONG, TYPE_LONG_LONG, TYPE_SHORT, TYPE_VOID, TYPE_VOIDP

Instance Method Summary collapse

Methods included from CParser

#parse_ctype, #parse_signature, #parse_struct_signature

Methods included from DL

dlopen, dlunwrap, dlwrap, fiddle?, free, malloc, realloc, #remove_callback_internal, #remove_cdecl_callback, #remove_stdcall_callback, #set_callback_internal, #set_cdecl_callback, #set_stdcall_callback

Instance Method Details

#[](name) ⇒ Object



192
193
194
# File 'lib/dl/import.rb', line 192

def [](name)
  @func_map[name]
end

#bind(signature, *opts, &blk) ⇒ Object



152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
# File 'lib/dl/import.rb', line 152

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)
  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(<<-EOS, file, line)
    def #{name}(*args,&block)
      @func_map['#{name}'].call(*args,&block)
    end
  EOS
  module_function(name)
  f
end

#bind_function(name, ctype, argtype, call_type = nil, &block) ⇒ Object



232
233
234
235
236
237
238
239
240
241
242
243
244
# File 'lib/dl/import.rb', line 232

def bind_function(name, ctype, argtype, call_type = nil, &block)
  if DL.fiddle?
    closure = Class.new(Fiddle::Closure) {
      define_method(:call, block)
    }.new(ctype, argtype)

    Function.new(closure, argtype)
  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) ⇒ Object



250
251
252
# File 'lib/dl/import.rb', line 250

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) ⇒ Object



246
247
248
# File 'lib/dl/import.rb', line 246

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) ⇒ Object Also known as: value



196
197
198
199
200
201
202
203
# File 'lib/dl/import.rb', line 196

def create_value(ty, val=nil)
  s = struct([ty + " value"])
  ptr = s.malloc()
  if( val )
    ptr.value = val
  end
  return ptr
end

#dlload(*libs) ⇒ Object



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File '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) ⇒ Object



130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/dl/import.rb', line 130

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

#handlerObject



212
213
214
# File 'lib/dl/import.rb', line 212

def handler
  @handler or raise "call dlload before importing symbols and functions"
end

#import_function(name, ctype, argtype, call_type = nil) ⇒ Object



224
225
226
227
228
229
230
# File 'lib/dl/import.rb', line 224

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) ⇒ Object



216
217
218
219
220
221
222
# File 'lib/dl/import.rb', line 216

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) ⇒ Object



206
207
208
209
210
# File 'lib/dl/import.rb', line 206

def import_value(ty, addr)
  s = struct([ty + " value"])
  ptr = s.new(addr)
  return ptr
end

#sizeof(ty) ⇒ Object



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/dl/import.rb', line 81

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

#struct(signature) ⇒ Object



182
183
184
185
# File 'lib/dl/import.rb', line 182

def struct(signature)
  tys, mems = parse_struct_signature(signature, @type_alias)
  DL::CStructBuilder.create(CStruct, tys, mems)
end

#typealias(alias_type, orig_type) ⇒ Object



77
78
79
# File 'lib/dl/import.rb', line 77

def typealias(alias_type, orig_type)
  @type_alias[alias_type] = orig_type
end

#union(signature) ⇒ Object



187
188
189
190
# File 'lib/dl/import.rb', line 187

def union(signature)
  tys, mems = parse_struct_signature(signature, @type_alias)
  DL::CStructBuilder.create(CUnion, tys, mems)
end