From 4ed6a88b74be65894b580dba81e7b8e3e8b0c3ce Mon Sep 17 00:00:00 2001 From: zzak Date: Wed, 28 Nov 2012 02:08:39 +0000 Subject: * ext/fiddle/closure.c: Documentation for Fiddle * ext/fiddle/lib/fiddle/import.rb: ditto * ext/fiddle/lib/fiddle/value.rb: ditto * ext/fiddle/lib/fiddle/pack.rb: ditto * ext/fiddle/lib/fiddle/cparser.rb: ditto * ext/fiddle/lib/fiddle/struct.rb: ditto * ext/fiddle/lib/fiddle/function.rb: ditto git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@37917 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ext/fiddle/closure.c | 2 +- ext/fiddle/lib/fiddle/cparser.rb | 40 ++++++++++++++++------ ext/fiddle/lib/fiddle/function.rb | 1 + ext/fiddle/lib/fiddle/import.rb | 71 ++++++++++++++++++++++++++++++++++++--- ext/fiddle/lib/fiddle/pack.rb | 4 +-- ext/fiddle/lib/fiddle/struct.rb | 49 +++++++++++++++------------ ext/fiddle/lib/fiddle/value.rb | 2 +- 7 files changed, 129 insertions(+), 40 deletions(-) (limited to 'ext/fiddle') diff --git a/ext/fiddle/closure.c b/ext/fiddle/closure.c index 3c6dccf51b..6690b87c25 100644 --- a/ext/fiddle/closure.c +++ b/ext/fiddle/closure.c @@ -289,7 +289,7 @@ Init_fiddle_closure() * Construct a new Closure object. * * * +ret+ is the C type to be returned - * * +args+ are passed the callback + * * +args+is an Array of arguments, passed to the callback function * * +abi+ is the abi of the closure * * If there is an error in preparing the ffi_cif or ffi_prep_closure, diff --git a/ext/fiddle/lib/fiddle/cparser.rb b/ext/fiddle/lib/fiddle/cparser.rb index ede88ae668..43fb184a12 100644 --- a/ext/fiddle/lib/fiddle/cparser.rb +++ b/ext/fiddle/lib/fiddle/cparser.rb @@ -1,12 +1,25 @@ module Fiddle - # Methods for parsing C struct and C prototype signatures. + # A mixin that provides methods for parsing C struct and prototype signatures. + # + # == Example + # require 'fiddle/import' + # + # include Fiddle::CParser + # #=> Object + # + # parse_ctype('int increment(int)') + # #=> ["increment", Fiddle::TYPE_INT, [Fiddle::TYPE_INT]] + # module CParser # Parses a C struct's members # # Example: # + # include Fiddle::CParser + # #=> Object + # # parse_struct_signature(['int i', 'char c']) - # => [[Fiddle::TYPE_INT, Fiddle::TYPE_CHAR], ["i", "c"]] + # #=> [[Fiddle::TYPE_INT, Fiddle::TYPE_CHAR], ["i", "c"]] # def parse_struct_signature(signature, tymap=nil) if( signature.is_a?(String) ) @@ -45,13 +58,17 @@ module Fiddle # Parses a C prototype signature # + # If Hash +tymap+ is provided, the return value and the arguments from the + # +signature+ are expected to be keys, and the value will be the C type to + # be looked up. + # # Example: # # include Fiddle::CParser - # => Object + # #=> Object # # parse_signature('double sum(double, double)') - # => ["sum", Fiddle::TYPE_DOUBLE, [Fiddle::TYPE_DOUBLE, Fiddle::TYPE_DOUBLE]] + # #=> ["sum", Fiddle::TYPE_DOUBLE, [Fiddle::TYPE_DOUBLE, Fiddle::TYPE_DOUBLE]] # def parse_signature(signature, tymap=nil) tymap ||= {} @@ -74,24 +91,27 @@ module Fiddle end end - # Given a String of C type +ty+, return the corresponding DL constant. + # Given a String of C type +ty+, returns the corresponding Fiddle constant. # - # +ty+ can also accept an Array of C type Strings, and will returned in a - # corresponding Array. + # +ty+ can also accept an Array of C type Strings, and will be returned in + # a corresponding Array. # # If Hash +tymap+ is provided, +ty+ is expected to be the key, and the # value will be the C type to be looked up. # # Example: # + # include Fiddle::CParser + # #=> Object + # # parse_ctype('int') - # => Fiddle::TYPE_INT + # #=> Fiddle::TYPE_INT # # parse_ctype('double') - # => Fiddle::TYPE_DOUBLE + # #=> Fiddle::TYPE_DOUBLE # # parse_ctype('unsigned char') - # => -Fiddle::TYPE_CHAR + # #=> -Fiddle::TYPE_CHAR # def parse_ctype(ty, tymap=nil) tymap ||= {} diff --git a/ext/fiddle/lib/fiddle/function.rb b/ext/fiddle/lib/fiddle/function.rb index f4d41e6a82..07a072e021 100644 --- a/ext/fiddle/lib/fiddle/function.rb +++ b/ext/fiddle/lib/fiddle/function.rb @@ -6,6 +6,7 @@ module Fiddle # The address of this function attr_reader :ptr + # The integer memory location of this function def to_i ptr.to_i end diff --git a/ext/fiddle/lib/fiddle/import.rb b/ext/fiddle/lib/fiddle/import.rb index 10b4fad2b5..ba0f716a9a 100644 --- a/ext/fiddle/lib/fiddle/import.rb +++ b/ext/fiddle/lib/fiddle/import.rb @@ -3,15 +3,25 @@ require 'fiddle/struct' require 'fiddle/cparser' module Fiddle + + # Used internally by Fiddle::Importer class CompositeHandler + # Create a new handler with the open +handlers+ + # + # Used internally by Fiddle::Importer.dlload def initialize(handlers) @handlers = handlers end + # Array of the currently loaded libraries. def handlers() @handlers end + # Returns the address as an Integer from any handlers with the function + # named +symbol+. + # + # Raises a DLError if the handle is closed. def sym(symbol) @handlers.each{|handle| if( handle ) @@ -25,32 +35,40 @@ module Fiddle return nil end + # See Fiddle::CompositeHandler.sym def [](symbol) sym(symbol) end end - # DL::Importer includes the means to dynamically load libraries and build + # 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 'dl' - # require 'dl/import' + # require 'fiddle' + # require 'fiddle/import' # # module LibSum - # extend DL::Importer + # extend Fiddle::Importer # dlload './libsum.so' # extern 'double sum(double*, int)' # extern 'double split(double)' # end - # + # module Importer include Fiddle include CParser extend Importer + # Creates an array of handlers for the given +libs+, can be an instance of + # Fiddle::Handle, Fiddle::Importer, or will create a new istance of + # Fiddle::Handle using Fiddle.dlopen + # + # Raises a DLError if the library cannot be loaded. + # + # See Fiddle.dlopen def dlload(*libs) handles = libs.collect{|lib| case lib @@ -73,10 +91,13 @@ module Fiddle @type_alias = {} end + # Sets the type alias for +alias_type+ as +orig_type+ def typealias(alias_type, orig_type) @type_alias[alias_type] = orig_type end + # Returns the sizeof +ty+, using Fiddle::Importer.parse_ctype to determine + # the C type and the appropriate Fiddle constant. def sizeof(ty) case ty when String @@ -126,6 +147,7 @@ module Fiddle end private :parse_bind_options + # Creates a global method from the given C +signature+. def extern(signature, *opts) symname, ctype, argtype = parse_signature(signature, @type_alias) opt = parse_bind_options(opts) @@ -148,6 +170,8 @@ module Fiddle f end + # Creates a global method from the given C +signature+ using the given + # +opts+ as bind parameters with the given block. def bind(signature, *opts, &blk) name, ctype, argtype = parse_signature(signature, @type_alias) h = parse_bind_options(opts) @@ -190,10 +214,15 @@ module Fiddle Fiddle::CStructBuilder.create(CUnion, tys, mems) end + # Returns the function mapped to +name+, that was created by either + # Fiddle::Importer.extern or Fiddle::Importer.bind def [](name) @func_map[name] end + # Creates a class to wrap the C struct with the value +ty+ + # + # See also Fiddle::Importer.struct def create_value(ty, val=nil) s = struct([ty + " value"]) ptr = s.malloc() @@ -204,16 +233,28 @@ module Fiddle end alias value create_value + # Returns a new instance of the C struct with the value +ty+ at the +addr+ + # address. def import_value(ty, addr) s = struct([ty + " value"]) ptr = s.new(addr) return ptr end + + # The Fiddle::CompositeHandler instance + # + # Will raise an error if no handlers are open. def handler @handler or raise "call dlload before importing symbols and functions" end + # 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 def import_symbol(name) addr = handler.sym(name) if( !addr ) @@ -222,6 +263,18 @@ module Fiddle Pointer.new(addr) end + # 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 the +name+ 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 def import_function(name, ctype, argtype, call_type = nil) addr = handler.sym(name) if( !addr ) @@ -230,6 +283,14 @@ module Fiddle Function.new(addr, argtype, ctype, call_type) end + # 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 def bind_function(name, ctype, argtype, call_type = nil, &block) closure = Class.new(Fiddle::Closure) { define_method(:call, block) diff --git a/ext/fiddle/lib/fiddle/pack.rb b/ext/fiddle/lib/fiddle/pack.rb index f406d374f9..e4e9542cc0 100644 --- a/ext/fiddle/lib/fiddle/pack.rb +++ b/ext/fiddle/lib/fiddle/pack.rb @@ -1,7 +1,7 @@ require 'fiddle' module Fiddle - module PackInfo + module PackInfo # :nodoc: all ALIGN_MAP = { TYPE_VOIDP => ALIGN_VOIDP, TYPE_CHAR => ALIGN_CHAR, @@ -60,7 +60,7 @@ module Fiddle module_function :align end - class Packer + class Packer # :nodoc: all include PackInfo def self.[](*types) diff --git a/ext/fiddle/lib/fiddle/struct.rb b/ext/fiddle/lib/fiddle/struct.rb index 043b3885b3..5a70699bf3 100644 --- a/ext/fiddle/lib/fiddle/struct.rb +++ b/ext/fiddle/lib/fiddle/struct.rb @@ -36,14 +36,14 @@ module Fiddle # # Example: # - # require 'dl/struct' - # require 'dl/cparser' + # require 'fiddle/struct' + # require 'fiddle/cparser' # # include Fiddle::CParser # # types, members = parse_struct_signature(['int i','char c']) # - # MyStruct = Fiddle::CStructBuilder.create(CUnion, types, members) + # MyStruct = Fiddle::CStructBuilder.create(Fiddle::CUnion, types, members) # # obj = MyStruct.allocate # @@ -80,18 +80,21 @@ module Fiddle include PackInfo include ValueUtil - # Allocates a C struct the +types+ provided. The C function +func+ is - # called when the instance is garbage collected. + # Allocates a C struct with the +types+ provided. + # + # When the instance is garbage collected, the C function +func+ is called. def CStructEntity.malloc(types, func = nil) addr = Fiddle.malloc(CStructEntity.size(types)) CStructEntity.new(addr, types, func) end - # Given +types+, returns the offset for the packed sizes of those types + # Returns the offset for the packed sizes for the given +types+. # - # Fiddle::CStructEntity.size([Fiddle::TYPE_DOUBLE, Fiddle::TYPE_INT, Fiddle::TYPE_CHAR, - # Fiddle::TYPE_VOIDP]) - # => 24 + # Fiddle::CStructEntity.size( + # [ Fiddle::TYPE_DOUBLE, + # Fiddle::TYPE_INT, + # Fiddle::TYPE_CHAR, + # Fiddle::TYPE_VOIDP ]) #=> 24 def CStructEntity.size(types) offset = 0 @@ -108,10 +111,11 @@ module Fiddle PackInfo.align(offset, max_align) end - # Wraps the C pointer +addr+ as a C struct with the given +types+. The C - # function +func+ is called when the instance is garbage collected. + # Wraps the C pointer +addr+ as a C struct with the given +types+. + # + # When the instance is garbage collected, the C function +func+ is called. # - # See also Fiddle::CPtr.new + # See also Fiddle::Pointer.new def initialize(addr, types, func = nil) set_ctypes(types) super(addr, @size, func) @@ -122,8 +126,7 @@ module Fiddle @members = members end - # Given +types+, calculate the offsets and sizes for the types in the - # struct. + # Calculates the offsets and sizes for the given +types+ in the struct. def set_ctypes(types) @ctypes = types @offset = [] @@ -207,25 +210,29 @@ module Fiddle class CUnionEntity < CStructEntity include PackInfo - # Allocates a C union the +types+ provided. The C function +func+ is - # called when the instance is garbage collected. + # Allocates a C union the +types+ provided. + # + # When the instance is garbage collected, the C function +func+ is called. def CUnionEntity.malloc(types, func=nil) addr = Fiddle.malloc(CUnionEntity.size(types)) CUnionEntity.new(addr, types, func) end - # Given +types+, returns the size needed for the union. + # Returns the size needed for the union with the given +types+. # - # Fiddle::CUnionEntity.size([Fiddle::TYPE_DOUBLE, Fiddle::TYPE_INT, Fiddle::TYPE_CHAR, - # Fiddle::TYPE_VOIDP]) - # => 8 + # Fiddle::CUnionEntity.size( + # [ Fiddle::TYPE_DOUBLE, + # Fiddle::TYPE_INT, + # Fiddle::TYPE_CHAR, + # Fiddle::TYPE_VOIDP ]) #=> 8 def CUnionEntity.size(types) types.map { |type, count = 1| PackInfo::SIZE_MAP[type] * count }.max end - # Given +types+, calculate the necessary offset and for each union member + # Calculate the necessary offset and for each union member with the given + # +types+ def set_ctypes(types) @ctypes = types @offset = Array.new(types.length, 0) diff --git a/ext/fiddle/lib/fiddle/value.rb b/ext/fiddle/lib/fiddle/value.rb index 0849e4ac35..d1d02cccf5 100644 --- a/ext/fiddle/lib/fiddle/value.rb +++ b/ext/fiddle/lib/fiddle/value.rb @@ -1,7 +1,7 @@ require 'fiddle' module Fiddle - module ValueUtil + module ValueUtil #:nodoc: all def unsigned_value(val, ty) case ty.abs when TYPE_CHAR -- cgit v1.2.3