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