Module: DL::Importer

Extended by:
Importer
Includes:
DL, CParser
Included in:
Importer
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_INTPTR_T, ALIGN_LONG, ALIGN_LONG_LONG, ALIGN_PTRDIFF_T, ALIGN_SHORT, ALIGN_SIZE_T, ALIGN_SSIZE_T, ALIGN_UINTPTR_T, 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_INTPTR_T, SIZEOF_LONG, SIZEOF_LONG_LONG, SIZEOF_PTRDIFF_T, SIZEOF_SHORT, SIZEOF_SIZE_T, SIZEOF_SSIZE_T, SIZEOF_UINTPTR_T, SIZEOF_VOIDP, StdcallCallbackAddrs, StdcallCallbackProcs, TYPE_CHAR, TYPE_DOUBLE, TYPE_FLOAT, TYPE_INT, TYPE_INTPTR_T, TYPE_LONG, TYPE_LONG_LONG, TYPE_PTRDIFF_T, TYPE_SHORT, TYPE_SIZE_T, TYPE_SSIZE_T, TYPE_UINTPTR_T, 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


203
204
205
# File 'lib/dl/import.rb', line 203

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

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


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
181
182
183
# File '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(<<-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


244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
# File '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) ⇒ Object


264
265
266
# File '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) ⇒ Object


260
261
262
# File '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) ⇒ Object Also known as: value


207
208
209
210
211
212
213
214
# File '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

#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


131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# File '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(<<-EOS, file, line)
    def #{name}(*args, &block)
      @func_map['#{name}'].call(*args,&block)
    end
  EOS
  module_function(name)
  f
end

#handlerObject


223
224
225
226
# File '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) ⇒ Object


236
237
238
239
240
241
242
# File '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) ⇒ Object


228
229
230
231
232
233
234
# File '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) ⇒ Object


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

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
112
# File '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) ⇒ Object

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

MyStruct = struct ['int i', 'char c']

188
189
190
191
192
# File '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) ⇒ 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

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

MyUnion = union ['int i', 'char c']

197
198
199
200
201
# File '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