Module: DL::Importer
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
-
#[](name) ⇒ Object
-
#bind(signature, *opts, &blk) ⇒ Object
-
#bind_function(name, ctype, argtype, call_type = nil, &block) ⇒ Object
-
#create_carried_function(name, ctype, argtype, call_type = nil, n = 0) ⇒ Object
-
#create_temp_function(name, ctype, argtype, call_type = nil) ⇒ Object
-
#create_value(ty, val = nil) ⇒ Object
(also: #value)
-
#dlload(*libs) ⇒ Object
-
#extern(signature, *opts) ⇒ Object
-
#handler ⇒ Object
-
#import_function(name, ctype, argtype, call_type = nil) ⇒ Object
-
#import_symbol(name) ⇒ Object
-
#import_value(ty, addr) ⇒ Object
-
#sizeof(ty) ⇒ Object
-
#struct(signature) ⇒ Object
Creates a class to wrap the C struct described by signature
.
-
#typealias(alias_type, orig_type) ⇒ Object
-
#union(signature) ⇒ Object
Creates a class to wrap the C union described by signature
.
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
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
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
|
#handler ⇒ Object
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
|
#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
|