eaiovnaovbqoebvqoeavibavo types.rb000064400000003531147634044470006254 0ustar00module Fiddle # Adds Windows type aliases to the including class for use with # Fiddle::Importer. # # The aliases added are: # * ATOM # * BOOL # * BYTE # * DWORD # * DWORD32 # * DWORD64 # * HANDLE # * HDC # * HINSTANCE # * HWND # * LPCSTR # * LPSTR # * PBYTE # * PDWORD # * PHANDLE # * PVOID # * PWORD # * UCHAR # * UINT # * ULONG # * WORD module Win32Types def included(m) # :nodoc: m.module_eval{ typealias "DWORD", "unsigned long" typealias "PDWORD", "unsigned long *" typealias "DWORD32", "unsigned long" typealias "DWORD64", "unsigned long long" typealias "WORD", "unsigned short" typealias "PWORD", "unsigned short *" typealias "BOOL", "int" typealias "ATOM", "int" typealias "BYTE", "unsigned char" typealias "PBYTE", "unsigned char *" typealias "UINT", "unsigned int" typealias "ULONG", "unsigned long" typealias "UCHAR", "unsigned char" typealias "HANDLE", "uintptr_t" typealias "PHANDLE", "void*" typealias "PVOID", "void*" typealias "LPCSTR", "char*" typealias "LPSTR", "char*" typealias "HINSTANCE", "unsigned int" typealias "HDC", "unsigned int" typealias "HWND", "unsigned int" } end module_function :included end # Adds basic type aliases to the including class for use with Fiddle::Importer. # # The aliases added are +uint+ and +u_int+ (unsigned int) and # +ulong+ and +u_long+ (unsigned long) module BasicTypes def included(m) # :nodoc: m.module_eval{ typealias "uint", "unsigned int" typealias "u_int", "unsigned int" typealias "ulong", "unsigned long" typealias "u_long", "unsigned long" } end module_function :included end end struct.rb000064400000014507147634044470006441 0ustar00require 'fiddle' require 'fiddle/value' require 'fiddle/pack' module Fiddle # C struct shell class CStruct # accessor to Fiddle::CStructEntity def CStruct.entity_class CStructEntity end end # C union shell class CUnion # accessor to Fiddle::CUnionEntity def CUnion.entity_class CUnionEntity end end # Used to construct C classes (CUnion, CStruct, etc) # # Fiddle::Importer#struct and Fiddle::Importer#union wrap this functionality in an # easy-to-use manner. module CStructBuilder # Construct a new class given a C: # * class +klass+ (CUnion, CStruct, or other that provide an # #entity_class) # * +types+ (Fiddle::TYPE_INT, Fiddle::TYPE_SIZE_T, etc., see the C types # constants) # * corresponding +members+ # # Fiddle::Importer#struct and Fiddle::Importer#union wrap this functionality in an # easy-to-use manner. # # Example: # # require 'fiddle/struct' # require 'fiddle/cparser' # # include Fiddle::CParser # # types, members = parse_struct_signature(['int i','char c']) # # MyStruct = Fiddle::CStructBuilder.create(Fiddle::CUnion, types, members) # # obj = MyStruct.allocate # def create(klass, types, members) new_class = Class.new(klass){ define_method(:initialize){|addr| @entity = klass.entity_class.new(addr, types) @entity.assign_names(members) } define_method(:to_ptr){ @entity } define_method(:to_i){ @entity.to_i } members.each{|name| define_method(name){ @entity[name] } define_method(name + "="){|val| @entity[name] = val } } } size = klass.entity_class.size(types) new_class.module_eval(<<-EOS, __FILE__, __LINE__+1) def new_class.size() #{size} end def new_class.malloc() addr = Fiddle.malloc(#{size}) new(addr) end EOS return new_class end module_function :create end # A C struct wrapper class CStructEntity < Fiddle::Pointer include PackInfo include ValueUtil # 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 # 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 def CStructEntity.size(types) offset = 0 max_align = types.map { |type, count = 1| last_offset = offset align = PackInfo::ALIGN_MAP[type] offset = PackInfo.align(last_offset, align) + (PackInfo::SIZE_MAP[type] * count) align }.max PackInfo.align(offset, max_align) end # 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::Pointer.new def initialize(addr, types, func = nil) set_ctypes(types) super(addr, @size, func) end # Set the names of the +members+ in this C struct def assign_names(members) @members = members end # Calculates the offsets and sizes for the given +types+ in the struct. def set_ctypes(types) @ctypes = types @offset = [] offset = 0 max_align = types.map { |type, count = 1| orig_offset = offset align = ALIGN_MAP[type] offset = PackInfo.align(orig_offset, align) @offset << offset offset += (SIZE_MAP[type] * count) align }.max @size = PackInfo.align(offset, max_align) end # Fetch struct member +name+ def [](name) idx = @members.index(name) if( idx.nil? ) raise(ArgumentError, "no such member: #{name}") end ty = @ctypes[idx] if( ty.is_a?(Array) ) r = super(@offset[idx], SIZE_MAP[ty[0]] * ty[1]) else r = super(@offset[idx], SIZE_MAP[ty.abs]) end packer = Packer.new([ty]) val = packer.unpack([r]) case ty when Array case ty[0] when TYPE_VOIDP val = val.collect{|v| Pointer.new(v)} end when TYPE_VOIDP val = Pointer.new(val[0]) else val = val[0] end if( ty.is_a?(Integer) && (ty < 0) ) return unsigned_value(val, ty) elsif( ty.is_a?(Array) && (ty[0] < 0) ) return val.collect{|v| unsigned_value(v,ty[0])} else return val end end # Set struct member +name+, to value +val+ def []=(name, val) idx = @members.index(name) if( idx.nil? ) raise(ArgumentError, "no such member: #{name}") end ty = @ctypes[idx] packer = Packer.new([ty]) val = wrap_arg(val, ty, []) buff = packer.pack([val].flatten()) super(@offset[idx], buff.size, buff) if( ty.is_a?(Integer) && (ty < 0) ) return unsigned_value(val, ty) elsif( ty.is_a?(Array) && (ty[0] < 0) ) return val.collect{|v| unsigned_value(v,ty[0])} else return val end end def to_s() # :nodoc: super(@size) end end # A C union wrapper class CUnionEntity < CStructEntity include PackInfo # 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 # 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 def CUnionEntity.size(types) types.map { |type, count = 1| PackInfo::SIZE_MAP[type] * count }.max end # 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) @size = self.class.size types end end end import.rb000064400000021141147634044470006417 0ustar00require 'fiddle' 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 ) begin addr = handle.sym(symbol) return addr rescue DLError end end } return nil end # See Fiddle::CompositeHandler.sym def [](symbol) sym(symbol) end end # 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 # 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 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 # 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 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 def parse_bind_options(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 private :parse_bind_options # :stopdoc: CALL_TYPE_TO_ABI = Hash.new { |h, k| raise RuntimeError, "unsupported call type: #{k}" }.merge({ :stdcall => (Function::STDCALL rescue Function::DEFAULT), :cdecl => Function::DEFAULT, nil => Function::DEFAULT }).freeze private_constant :CALL_TYPE_TO_ABI # :startdoc: # 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) 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 # 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) 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 # Creates a class to wrap the C struct described by +signature+. # # MyStruct = struct ['int i', 'char c'] def struct(signature) tys, mems = parse_struct_signature(signature, @type_alias) Fiddle::CStructBuilder.create(CStruct, tys, mems) end # Creates a class to wrap the C union described by +signature+. # # MyUnion = union ['int i', 'char c'] def union(signature) tys, mems = parse_struct_signature(signature, @type_alias) 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() if( val ) ptr.value = val end return ptr 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 ) raise(DLError, "cannot find the symbol: #{name}") end 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 ) raise(DLError, "cannot find the function: #{name}()") end Function.new(addr, argtype, ctype, CALL_TYPE_TO_ABI[call_type], name: name) 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) 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 end end closure.rb000064400000002273147634044470006566 0ustar00module Fiddle class Closure # the C type of the return of the FFI closure attr_reader :ctype # arguments of the FFI closure attr_reader :args # Extends Fiddle::Closure to allow for building the closure in a block class BlockCaller < Fiddle::Closure # == Description # # Construct a new BlockCaller object. # # * +ctype+ is the C type to be returned # * +args+ are passed the callback # * +abi+ is the abi of the closure # # If there is an error in preparing the +ffi_cif+ or +ffi_prep_closure+, # then a RuntimeError will be raised. # # == Example # # include Fiddle # # cb = Closure::BlockCaller.new(TYPE_INT, [TYPE_INT]) do |one| # one # end # # func = Function.new(cb, [TYPE_INT], TYPE_INT) # def initialize ctype, args, abi = Fiddle::Function::DEFAULT, &block super(ctype, args, abi) @block = block end # Calls the constructed BlockCaller, with +args+ # # For an example see Fiddle::Closure::BlockCaller.new # def call *args @block.call(*args) end end end end function.rb000064400000000445147634044470006736 0ustar00module Fiddle class Function # The ABI of the Function. attr_reader :abi # The address of this function attr_reader :ptr # The name of this function attr_reader :name # The integer memory location of this function def to_i ptr.to_i end end end value.rb000064400000005134147634044470006225 0ustar00require 'fiddle' module Fiddle module ValueUtil #:nodoc: all def unsigned_value(val, ty) case ty.abs when TYPE_CHAR [val].pack("c").unpack("C")[0] when TYPE_SHORT [val].pack("s!").unpack("S!")[0] when TYPE_INT [val].pack("i!").unpack("I!")[0] when TYPE_LONG [val].pack("l!").unpack("L!")[0] when TYPE_LONG_LONG [val].pack("q").unpack("Q")[0] else val end end def signed_value(val, ty) case ty.abs when TYPE_CHAR [val].pack("C").unpack("c")[0] when TYPE_SHORT [val].pack("S!").unpack("s!")[0] when TYPE_INT [val].pack("I!").unpack("i!")[0] when TYPE_LONG [val].pack("L!").unpack("l!")[0] when TYPE_LONG_LONG [val].pack("Q").unpack("q")[0] else val end end def wrap_args(args, tys, funcs, &block) result = [] tys ||= [] args.each_with_index{|arg, idx| result.push(wrap_arg(arg, tys[idx], funcs, &block)) } result end def wrap_arg(arg, ty, funcs = [], &block) funcs ||= [] case arg when nil return 0 when Pointer return arg.to_i when IO case ty when TYPE_VOIDP return Pointer[arg].to_i else return arg.to_i end when Function if( block ) arg.bind_at_call(&block) funcs.push(arg) elsif !arg.bound? raise(RuntimeError, "block must be given.") end return arg.to_i when String if( ty.is_a?(Array) ) return arg.unpack('C*') else case SIZEOF_VOIDP when SIZEOF_LONG return [arg].pack("p").unpack("l!")[0] when SIZEOF_LONG_LONG return [arg].pack("p").unpack("q")[0] else raise(RuntimeError, "sizeof(void*)?") end end when Float, Integer return arg when Array if( ty.is_a?(Array) ) # used only by struct case ty[0] when TYPE_VOIDP return arg.collect{|v| Integer(v)} when TYPE_CHAR if( arg.is_a?(String) ) return val.unpack('C*') end end return arg else return arg end else if( arg.respond_to?(:to_ptr) ) return arg.to_ptr.to_i else begin return Integer(arg) rescue raise(ArgumentError, "unknown argument type: #{arg.class}") end end end end end end pack.rb000064400000005645147634044470006036 0ustar00require 'fiddle' module Fiddle module PackInfo # :nodoc: all ALIGN_MAP = { TYPE_VOIDP => ALIGN_VOIDP, TYPE_CHAR => ALIGN_CHAR, TYPE_SHORT => ALIGN_SHORT, TYPE_INT => ALIGN_INT, TYPE_LONG => ALIGN_LONG, TYPE_FLOAT => ALIGN_FLOAT, TYPE_DOUBLE => ALIGN_DOUBLE, -TYPE_CHAR => ALIGN_CHAR, -TYPE_SHORT => ALIGN_SHORT, -TYPE_INT => ALIGN_INT, -TYPE_LONG => ALIGN_LONG, } PACK_MAP = { TYPE_VOIDP => ((SIZEOF_VOIDP == SIZEOF_LONG_LONG) ? "q" : "l!"), TYPE_CHAR => "c", TYPE_SHORT => "s!", TYPE_INT => "i!", TYPE_LONG => "l!", TYPE_FLOAT => "f", TYPE_DOUBLE => "d", -TYPE_CHAR => "c", -TYPE_SHORT => "s!", -TYPE_INT => "i!", -TYPE_LONG => "l!", } SIZE_MAP = { TYPE_VOIDP => SIZEOF_VOIDP, TYPE_CHAR => SIZEOF_CHAR, TYPE_SHORT => SIZEOF_SHORT, TYPE_INT => SIZEOF_INT, TYPE_LONG => SIZEOF_LONG, TYPE_FLOAT => SIZEOF_FLOAT, TYPE_DOUBLE => SIZEOF_DOUBLE, -TYPE_CHAR => SIZEOF_CHAR, -TYPE_SHORT => SIZEOF_SHORT, -TYPE_INT => SIZEOF_INT, -TYPE_LONG => SIZEOF_LONG, } if defined?(TYPE_LONG_LONG) ALIGN_MAP[TYPE_LONG_LONG] = ALIGN_MAP[-TYPE_LONG_LONG] = ALIGN_LONG_LONG PACK_MAP[TYPE_LONG_LONG] = PACK_MAP[-TYPE_LONG_LONG] = "q" SIZE_MAP[TYPE_LONG_LONG] = SIZE_MAP[-TYPE_LONG_LONG] = SIZEOF_LONG_LONG end def align(addr, align) d = addr % align if( d == 0 ) addr else addr + (align - d) end end module_function :align end class Packer # :nodoc: all include PackInfo def self.[](*types) new(types) end def initialize(types) parse_types(types) end def size() @size end def pack(ary) case SIZEOF_VOIDP when SIZEOF_LONG ary.pack(@template) when SIZEOF_LONG_LONG ary.pack(@template) else raise(RuntimeError, "sizeof(void*)?") end end def unpack(ary) case SIZEOF_VOIDP when SIZEOF_LONG ary.join().unpack(@template) when SIZEOF_LONG_LONG ary.join().unpack(@template) else raise(RuntimeError, "sizeof(void*)?") end end private def parse_types(types) @template = "" addr = 0 types.each{|t| orig_addr = addr if( t.is_a?(Array) ) addr = align(orig_addr, ALIGN_MAP[TYPE_VOIDP]) else addr = align(orig_addr, ALIGN_MAP[t]) end d = addr - orig_addr if( d > 0 ) @template << "x#{d}" end if( t.is_a?(Array) ) @template << (PACK_MAP[t[0]] * t[1]) addr += (SIZE_MAP[t[0]] * t[1]) else @template << PACK_MAP[t] addr += SIZE_MAP[t] end } addr = align(addr, ALIGN_MAP[TYPE_VOIDP]) @size = addr end end end cparser.rb000064400000011004147634044470006541 0ustar00module Fiddle # 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"]] # def parse_struct_signature(signature, tymap=nil) if( signature.is_a?(String) ) signature = signature.split(/\s*,\s*/) end mems = [] tys = [] signature.each{|msig| tks = msig.split(/\s+(\*)?/) ty = tks[0..-2].join(" ") member = tks[-1] case ty when /\[(\d+)\]/ n = $1.to_i ty.gsub!(/\s*\[\d+\]/,"") ty = [ty, n] when /\[\]/ ty.gsub!(/\s*\[\]/, "*") end case member when /\[(\d+)\]/ ty = [ty, $1.to_i] member.gsub!(/\s*\[\d+\]/,"") when /\[\]/ ty = ty + "*" member.gsub!(/\s*\[\]/, "") end mems.push(member) tys.push(parse_ctype(ty,tymap)) } return tys, mems end # 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 # # parse_signature('double sum(double, double)') # #=> ["sum", Fiddle::TYPE_DOUBLE, [Fiddle::TYPE_DOUBLE, Fiddle::TYPE_DOUBLE]] # def parse_signature(signature, tymap=nil) tymap ||= {} signature = signature.gsub(/\s+/, " ").strip case signature when /^([\w@\*\s]+)\(([\w\*\s\,\[\]]*)\)$/ ret = $1 (args = $2).strip! ret = ret.split(/\s+/) args = args.split(/\s*,\s*/) func = ret.pop if( func =~ /^\*/ ) func.gsub!(/^\*+/,"") ret.push("*") end ret = ret.join(" ") return [func, parse_ctype(ret, tymap), args.collect{|arg| parse_ctype(arg, tymap)}] else raise(RuntimeError,"can't parse the function prototype: #{signature}") end end # Given a String of C type +ty+, returns the corresponding Fiddle constant. # # +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 # # parse_ctype('double') # #=> Fiddle::TYPE_DOUBLE # # parse_ctype('unsigned char') # #=> -Fiddle::TYPE_CHAR # def parse_ctype(ty, tymap=nil) tymap ||= {} case ty when Array return [parse_ctype(ty[0], tymap), ty[1]] when "void" return TYPE_VOID when "char" return TYPE_CHAR when "unsigned char" return -TYPE_CHAR when "short" return TYPE_SHORT when "unsigned short" return -TYPE_SHORT when "int" return TYPE_INT when "unsigned int", 'uint' return -TYPE_INT when "long" return TYPE_LONG when "unsigned long" return -TYPE_LONG when "long long" if( defined?(TYPE_LONG_LONG) ) return TYPE_LONG_LONG else raise(RuntimeError, "unsupported type: #{ty}") end when "unsigned long long" if( defined?(TYPE_LONG_LONG) ) return -TYPE_LONG_LONG else raise(RuntimeError, "unsupported type: #{ty}") end when "float" return TYPE_FLOAT when "double" return TYPE_DOUBLE when "size_t" return TYPE_SIZE_T when "ssize_t" return TYPE_SSIZE_T when "ptrdiff_t" return TYPE_PTRDIFF_T when "intptr_t" return TYPE_INTPTR_T when "uintptr_t" return TYPE_UINTPTR_T when /\*/, /\[\s*\]/ return TYPE_VOIDP else if( tymap[ty] ) return parse_ctype(tymap[ty], tymap) else raise(DLError, "unknown type: #{ty}") end end end end end