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_INT16_T, ALIGN_INT32_T, ALIGN_INT64_T, ALIGN_INT8_T, 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_CONST_STRING, SIZEOF_DOUBLE, SIZEOF_FLOAT, SIZEOF_INT, SIZEOF_INT16_T, SIZEOF_INT32_T, SIZEOF_INT64_T, SIZEOF_INT8_T, 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_CONST_STRING, TYPE_DOUBLE, TYPE_FLOAT, TYPE_INT, TYPE_INT16_T, TYPE_INT32_T, TYPE_INT64_T, TYPE_INT8_T, TYPE_INTPTR_T, TYPE_LONG, TYPE_LONG_LONG, TYPE_PTRDIFF_T, TYPE_SHORT, TYPE_SIZE_T, TYPE_SSIZE_T, TYPE_UINTPTR_T, TYPE_VARIADIC, TYPE_VOID, TYPE_VOIDP, VERSION, 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
235 236 237 |
# File 'lib/fiddle/import.rb', line 235 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.
191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 |
# File 'lib/fiddle/import.rb', line 191 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
311 312 313 314 315 316 317 318 |
# File 'lib/fiddle/import.rb', line 311 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
242 243 244 245 246 247 248 249 |
# File 'lib/fiddle/import.rb', line 242 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
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/fiddle/import.rb', line 76 def dlload(*libs) handles = libs.collect{|lib| case lib when nil nil when Handle lib when Importer lib.handlers else Fiddle.dlopen(lib) end }.flatten() @handler = CompositeHandler.new(handles) @func_map = {} @type_alias = {} end |
#extern(signature, *opts) ⇒ Object
Creates a global method from the given C signature
.
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
# File 'lib/fiddle/import.rb', line 167 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.
264 265 266 |
# File 'lib/fiddle/import.rb', line 264 def handler (@handler ||= nil) 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
294 295 296 297 298 299 300 301 |
# File 'lib/fiddle/import.rb', line 294 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
274 275 276 277 278 279 280 |
# File 'lib/fiddle/import.rb', line 274 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.
254 255 256 257 258 |
# File 'lib/fiddle/import.rb', line 254 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 132 133 134 135 136 |
# 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_FLOAT return SIZEOF_FLOAT when TYPE_DOUBLE return SIZEOF_DOUBLE when TYPE_VOIDP return SIZEOF_VOIDP when TYPE_CONST_STRING return SIZEOF_CONST_STRING else if defined?(TYPE_LONG_LONG) and ty == TYPE_LONG_LONG return SIZEOF_LONG_LONG else raise(DLError, "unknown type: #{ty}") end 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']
220 221 222 223 |
# File 'lib/fiddle/import.rb', line 220 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']
228 229 230 231 |
# File 'lib/fiddle/import.rb', line 228 def union(signature) tys, mems = parse_struct_signature(signature, type_alias) Fiddle::CStructBuilder.create(CUnion, tys, mems) end |