Module: Fiddle::Importer
Relationships & Source Files | |
Super Chains via Extension / Inclusion / Inheritance | |
Instance Chain:
|
|
Defined in: | ext/fiddle/lib/fiddle/import.rb |
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
-
CALL_TYPE_TO_ABI =
private
Internal use only
# File 'ext/fiddle/lib/fiddle/import.rb', line 158Hash.new { |h, k| raise RuntimeError, "unsupported call type: #{k}" }.merge({ :stdcall => Function.const_defined?(:STDCALL) ? Function::STDCALL : Function::DEFAULT, :cdecl => Function::DEFAULT, nil => Function::DEFAULT }).freeze
::Fiddle
- Included
ALIGN_BOOL, 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, Qfalse, Qnil, Qtrue, Qundef, RTLD_GLOBAL, RTLD_LAZY, RTLD_NOW, RUBY_FREE, SIZEOF_BOOL, 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_UCHAR, SIZEOF_UINT, SIZEOF_UINT16_T, SIZEOF_UINT32_T, SIZEOF_UINT64_T, SIZEOF_UINT8_T, SIZEOF_UINTPTR_T, SIZEOF_ULONG, SIZEOF_ULONG_LONG, SIZEOF_USHORT, SIZEOF_VOIDP, VERSION, WINDOWS
Instance Attribute Summary
- #type_alias readonly private
Instance Method Summary
- #[](name)
-
#bind(signature, *opts, &blk)
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)
Returns a new closure wrapper for the
name
function. -
#create_value(ty, val = nil)
(also: #value)
Creates a class to wrap the C struct with the value
ty
- #dlload(*libs)
-
#extern(signature, *opts)
Creates a global method from the given C
signature
. -
#handler
The
CompositeHandler
instance. -
#import_function(name, ctype, argtype, call_type = nil)
Returns a new
Function
instance at the memory address of the givenname
function. -
#import_symbol(name)
Returns a new
Pointer
instance at the memory address of the givenname
symbol. -
#import_value(ty, addr)
Returns a new instance of the C struct with the value
ty
at theaddr
address. -
#sizeof(ty)
Returns the sizeof
ty
, usingFiddle::Importer.parse_ctype
to determine the C type and the appropriate::Fiddle
constant. -
#struct(signature)
Creates a class to wrap the C struct described by
signature
. -
#typealias(alias_type, orig_type)
Sets the type alias for
alias_type
asorig_type
-
#union(signature)
Creates a class to wrap the C union described by
signature
. -
#value(ty, val = nil)
Alias for #create_value.
- #parse_bind_options(opts) private
CParser
- Included
#parse_ctype | Given a String of C type |
#parse_signature | Parses a C prototype signature. |
#parse_struct_signature | Parses a C struct’s members. |
#compact, #split_arguments |
::Fiddle
- Included
#dlopen | Creates a new handler that opens |
#dlunwrap | Returns the Ruby object stored at the memory address |
#dlwrap | Returns the memory address of the Ruby object stored at |
#free | Free the memory at address |
#malloc | Allocate |
#realloc | Change the size of the memory allocated at the memory location |
Instance Attribute Details
#type_alias (readonly, private)
[ GitHub ]# File 'ext/fiddle/lib/fiddle/import.rb', line 66
attr_reader :type_alias
Instance Method Details
#[](name)
[ GitHub ]# File 'ext/fiddle/lib/fiddle/import.rb', line 237
def [](name) @func_map[name] end
#bind(signature, *opts, &blk)
Creates a global method from the given C signature
using the given opts
as bind parameters with the given block.
# File 'ext/fiddle/lib/fiddle/import.rb', line 193
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)
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 Closure
# File 'ext/fiddle/lib/fiddle/import.rb', line 313
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) Also known as: #value
Creates a class to wrap the C struct with the value ty
See also #struct
#dlload(*libs)
Creates an array of handlers for the given libs
, can be an instance of Handle
, Importer
, or will create a new instance of Handle
using Fiddle.dlopen
Raises a DLError
if the library cannot be loaded.
See Fiddle.dlopen
# File 'ext/fiddle/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)
Creates a global method from the given C signature
.
# File 'ext/fiddle/lib/fiddle/import.rb', line 169
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
The CompositeHandler
instance
Will raise an error if no handlers are open.
# File 'ext/fiddle/lib/fiddle/import.rb', line 266
def handler (@handler ||= nil) or raise "call dlload before importing symbols and functions" end
#import_function(name, ctype, argtype, call_type = nil)
Returns a new 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
# File 'ext/fiddle/lib/fiddle/import.rb', line 296
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)
Returns a new 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 Handle.sym
#import_value(ty, addr)
Returns a new instance of the C struct with the value ty
at the addr
address.
# File 'ext/fiddle/lib/fiddle/import.rb', line 256
def import_value(ty, addr) s = struct([ty + " value"]) ptr = s.new(addr) return ptr end
#parse_bind_options(opts) (private)
[ GitHub ]# File 'ext/fiddle/lib/fiddle/import.rb', line 140
def (opts) h = {} while( opt = opts.shift() ) case opt when :stdcall, :cdecl h[:call_type] = opt when :carried, :temp, :temporal, :bind h[:callback_type] = opt h[:carrier] = opts.shift() else h[opt] = true end end h end
#sizeof(ty)
Returns the sizeof ty
, using Fiddle::Importer.parse_ctype
to determine the C type and the appropriate ::Fiddle
constant.
# File 'ext/fiddle/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 when TYPE_BOOL return SIZEOF_BOOL 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)
Creates a class to wrap the C struct described by signature
.
MyStruct = struct ['int i', 'char c']
# File 'ext/fiddle/lib/fiddle/import.rb', line 222
def struct(signature) tys, mems = parse_struct_signature(signature, type_alias) Fiddle::CStructBuilder.create(CStruct, tys, mems) end
#typealias(alias_type, orig_type)
Sets the type alias for alias_type
as orig_type
# File 'ext/fiddle/lib/fiddle/import.rb', line 95
def typealias(alias_type, orig_type) @type_alias[alias_type] = orig_type end
#union(signature)
Creates a class to wrap the C union described by signature
.
MyUnion = union ['int i', 'char c']
# File 'ext/fiddle/lib/fiddle/import.rb', line 230
def union(signature) tys, mems = parse_struct_signature(signature, type_alias) Fiddle::CStructBuilder.create(CUnion, tys, mems) end
#value(ty, val = nil)
Alias for #create_value.
# File 'ext/fiddle/lib/fiddle/import.rb', line 252
alias value create_value