Module: Fiddle::Importer
Overview
A DSL that provides 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 'fiddle'
require 'fiddle/import'
module LibSum
extend Fiddle::Importer
dlload './libsum.so'
extern 'double sum(double*, int)'
extern 'double split(double)'
end
Constant Summary
Constants included from Fiddle
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, NULL, RTLD_GLOBAL, RTLD_LAZY, RTLD_NOW, RUBY_FREE, 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, 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, WINDOWS
Instance Method Summary collapse
-
#[](name) ⇒ Object
Returns the function mapped to
name
, that was created by either Fiddle::Importer.extern or Fiddle::Importer.bind. -
#bind(signature, *opts, &blk) ⇒ Object
Creates a global method from the given C
signature
using the givenopts
as bind parameters with the given block. -
#bind_function(name, ctype, argtype, call_type = nil, &block) ⇒ Object
Returns a new closure wrapper for the
name
function. -
#create_value(ty, val = nil) ⇒ Object
(also: #value)
Creates a class to wrap the C struct with the value
ty
. -
#dlload(*libs) ⇒ Object
Creates an array of handlers for the given
libs
, can be an instance of Fiddle::Handle, Fiddle::Importer, or will create a new instance of Fiddle::Handle using Fiddle.dlopen. -
#extern(signature, *opts) ⇒ Object
Creates a global method from the given C
signature
. -
#handler ⇒ Object
The Fiddle::CompositeHandler instance.
-
#import_function(name, ctype, argtype, call_type = nil) ⇒ Object
Returns a new Fiddle::Function instance at the memory address of the given
name
function. -
#import_symbol(name) ⇒ Object
Returns a new Fiddle::Pointer instance at the memory address of the given
name
symbol. -
#import_value(ty, addr) ⇒ Object
Returns a new instance of the C struct with the value
ty
at theaddr
address. -
#sizeof(ty) ⇒ Object
Returns the sizeof
ty
, using Fiddle::Importer.parse_ctype to determine the C type and the appropriate Fiddle constant. -
#struct(signature) ⇒ Object
Creates a class to wrap the C struct described by
signature
. -
#typealias(alias_type, orig_type) ⇒ Object
Sets the type alias for
alias_type
asorig_type
. -
#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 Fiddle
dlopen, dlunwrap, dlwrap, free, last_error, last_error=, malloc, realloc, win32_last_error, win32_last_error=
Instance Method Details
#[](name) ⇒ Object
Returns the function mapped to name
, that was created by either Fiddle::Importer.extern or Fiddle::Importer.bind
229 230 231 |
# File 'lib/fiddle/import.rb', line 229 def [](name) @func_map[name] end |
#bind(signature, *opts, &blk) ⇒ Object
Creates a global method from the given C signature
using the given opts
as bind parameters with the given block.
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 |
# File 'lib/fiddle/import.rb', line 185 def bind(signature, *opts, &blk) name, ctype, argtype = parse_signature(signature, @type_alias) h = (opts) case h[:callback_type] when :bind, nil f = bind_function(name, ctype, argtype, h[:call_type], &blk) 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
Returns a new closure wrapper for the name
function.
-
ctype
is the return type of the function -
argtype
is an Array of arguments, passed to the callback function -
call_type
is the abi of the closure -
block
is passed to the callback
See Fiddle::Closure
305 306 307 308 309 310 311 312 |
# File 'lib/fiddle/import.rb', line 305 def bind_function(name, ctype, argtype, call_type = nil, &block) abi = CALL_TYPE_TO_ABI[call_type] closure = Class.new(Fiddle::Closure) { define_method(:call, block) }.new(ctype, argtype, abi) Function.new(closure, argtype, ctype, abi, name: name) end |
#create_value(ty, val = nil) ⇒ Object Also known as: value
Creates a class to wrap the C struct with the value ty
See also Fiddle::Importer.struct
236 237 238 239 240 241 242 243 |
# File 'lib/fiddle/import.rb', line 236 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
Creates an array of handlers for the given libs
, can be an instance of Fiddle::Handle, Fiddle::Importer, or will create a new instance of Fiddle::Handle using Fiddle.dlopen
Raises a DLError if the library cannot be loaded.
See Fiddle.dlopen
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/fiddle/import.rb', line 72 def dlload(*libs) handles = libs.collect{|lib| case lib when nil nil when Handle lib when Importer lib.handlers else begin Fiddle.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
Creates a global method from the given C signature
.
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 |
# File 'lib/fiddle/import.rb', line 161 def extern(signature, *opts) symname, ctype, argtype = parse_signature(signature, @type_alias) opt = (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 |
#handler ⇒ Object
The Fiddle::CompositeHandler instance
Will raise an error if no handlers are open.
258 259 260 |
# File 'lib/fiddle/import.rb', line 258 def handler @handler or raise "call dlload before importing symbols and functions" end |
#import_function(name, ctype, argtype, call_type = nil) ⇒ Object
Returns a new Fiddle::Function instance at the memory address of the given name
function.
Raises a DLError if the name
doesn’t exist.
-
argtype
is an Array of arguments, passed to thename
function. -
ctype
is the return type of the function -
call_type
is the ABI of the function
See also Fiddle:Function.new
See Fiddle::CompositeHandler.sym and Fiddle::Handler.sym
288 289 290 291 292 293 294 295 |
# File 'lib/fiddle/import.rb', line 288 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(addr, argtype, ctype, CALL_TYPE_TO_ABI[call_type], name: name) end |
#import_symbol(name) ⇒ Object
Returns a new Fiddle::Pointer instance at the memory address of the given name
symbol.
Raises a DLError if the name
doesn’t exist.
See Fiddle::CompositeHandler.sym and Fiddle::Handle.sym
268 269 270 271 272 273 274 |
# File 'lib/fiddle/import.rb', line 268 def import_symbol(name) addr = handler.sym(name) if( !addr ) raise(DLError, "cannot find the symbol: #{name}") end Pointer.new(addr) end |
#import_value(ty, addr) ⇒ Object
Returns a new instance of the C struct with the value ty
at the addr
address.
248 249 250 251 252 |
# File 'lib/fiddle/import.rb', line 248 def import_value(ty, addr) s = struct([ty + " value"]) ptr = s.new(addr) return ptr end |
#sizeof(ty) ⇒ Object
Returns the sizeof ty
, using Fiddle::Importer.parse_ctype to determine the C type and the appropriate Fiddle constant.
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
# File 'lib/fiddle/import.rb', line 101 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_LONG 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 Pointer[ty].size() end |
#struct(signature) ⇒ Object
Creates a class to wrap the C struct described by signature
.
MyStruct = struct ['int i', 'char c']
214 215 216 217 |
# File 'lib/fiddle/import.rb', line 214 def struct(signature) tys, mems = parse_struct_signature(signature, @type_alias) Fiddle::CStructBuilder.create(CStruct, tys, mems) end |
#typealias(alias_type, orig_type) ⇒ Object
Sets the type alias for alias_type
as orig_type
95 96 97 |
# File 'lib/fiddle/import.rb', line 95 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']
222 223 224 225 |
# File 'lib/fiddle/import.rb', line 222 def union(signature) tys, mems = parse_struct_signature(signature, @type_alias) Fiddle::CStructBuilder.create(CUnion, tys, mems) end |