Attach C function name to this module.
If you want to provide an alternate name for the module function, supply it after the name, otherwise the C function name will be used.#
After the name, the C function argument types are provided as an Array.
The C function return type is provided last.
# File lib/ffi/library.rb, line 93 93: def attach_function(mname, a3, a4, a5=nil) 94: cname, arg_types, ret_type = a5 ? [ a3, a4, a5 ] : [ mname.to_s, a3, a4 ] 95: 96: # Convert :foo to the native type 97: arg_types.map! { |e| find_type(e) } 98: has_callback = arg_types.any? {|t| t.kind_of?(FFI::CallbackInfo)} 99: options = Hash.new 100: options[:convention] = defined?(@ffi_convention) ? @ffi_convention : :default 101: options[:type_map] = @ffi_typedefs if defined?(@ffi_typedefs) 102: options[:enums] = @ffi_enums if defined?(@ffi_enums) 103: 104: # Try to locate the function in any of the libraries 105: invokers = [] 106: ffi_libraries.each do |lib| 107: begin 108: invokers << FFI.create_invoker(lib, cname.to_s, arg_types, find_type(ret_type), options) 109: rescue LoadError => ex 110: end if invokers.empty? 111: end 112: invoker = invokers.compact.shift 113: raise FFI::NotFoundError.new(cname.to_s, ffi_libraries.map { |lib| lib.name }) unless invoker 114: 115: # Setup the parameter list for the module function as (a1, a2) 116: arity = arg_types.length 117: params = (1..arity).map {|i| "a#{i}" }.join(",") 118: 119: # Always use rest args for functions with callback parameters 120: if has_callback || invoker.kind_of?(FFI::VariadicInvoker) 121: params = "*args, &block" 122: end 123: call = arity <= 3 && !has_callback && !invoker.kind_of?(FFI::VariadicInvoker)? "call#{arity}" : "call" 124: 125: # 126: # Attach the invoker to this module as 'mname'. 127: # 128: if !has_callback && !invoker.kind_of?(FFI::VariadicInvoker) 129: invoker.attach(self, mname.to_s) 130: else 131: self.module_eval @@#{mname} = invoker def self.#{mname}(#{params}) @@#{mname}.#{call}(#{params}) end def #{mname}(#{params}) @@#{mname}.#{call}(#{params}) end 132: end 133: invoker 134: end
# File lib/ffi/library.rb, line 143 143: def attach_variable(mname, a1, a2 = nil) 144: cname, type = a2 ? [ a1, a2 ] : [ mname.to_s, a1 ] 145: address = nil 146: ffi_libraries.each do |lib| 147: begin 148: address = lib.find_variable(cname.to_s) 149: break unless address.nil? 150: rescue LoadError 151: end 152: end 153: 154: raise FFI::NotFoundError.new(cname, ffi_libraries) if address.nil? || address.null? 155: if type.is_a?(Class) && type < FFI::Struct 156: # If it is a global struct, just attach directly to the pointer 157: s = type.new(address) 158: self.module_eval @@ffi_gvar_#{mname} = s def self.#{mname} @@ffi_gvar_#{mname} end, __FILE__, __LINE__ 159: 160: else 161: sc = Class.new(FFI::Struct) 162: sc.layout :gvar, find_type(type) 163: s = sc.new(address) 164: # 165: # Attach to this module as mname/mname= 166: # 167: self.module_eval @@ffi_gvar_#{mname} = s def self.#{mname} @@ffi_gvar_#{mname}[:gvar] end def self.#{mname}=(value) @@ffi_gvar_#{mname}[:gvar] = value end, __FILE__, __LINE__ 168: 169: end 170: 171: address 172: end
# File lib/ffi/library.rb, line 187 187: def callback(*args) 188: raise ArgumentError, "wrong number of arguments" if args.length < 2 || args.length > 3 189: name, params, ret = if args.length == 3 190: args 191: else 192: [ nil, args[0], args[1] ] 193: end 194: 195: options = Hash.new 196: options[:convention] = defined?(@ffi_convention) ? @ffi_convention : :default 197: options[:enums] = @ffi_enums if defined?(@ffi_enums) 198: cb = FFI::CallbackInfo.new(find_type(ret), params.map { |e| find_type(e) }, options) 199: 200: # Add to the symbol -> type map (unless there was no name) 201: unless name.nil? 202: @ffi_callbacks = Hash.new unless defined?(@ffi_callbacks) 203: @ffi_callbacks[name] = cb 204: end 205: 206: cb 207: end
# File lib/ffi/library.rb, line 226 226: def enum(*args) 227: # 228: # enum can be called as: 229: # enum :zero, :one, :two # unnamed enum 230: # enum [ :zero, :one, :two ] # equivalent to above 231: # enum :foo, [ :zero, :one, :two ] create an enum named :foo 232: # 233: name, values = if args[0].kind_of?(Symbol) && args[1].kind_of?(Array) 234: [ args[0], args[1] ] 235: elsif args[0].kind_of?(Array) 236: [ nil, args[0] ] 237: else 238: [ nil, args ] 239: end 240: @ffi_enums = FFI::Enums.new unless defined?(@ffi_enums) 241: @ffi_enums << (e = FFI::Enum.new(values, name)) 242: 243: # If called as enum :foo, [ :zero, :one, :two ], add a typedef alias 244: typedef(e, name) if name 245: e 246: end
# File lib/ffi/library.rb, line 248 248: def enum_type(name) 249: @ffi_enums.find(name) if defined?(@ffi_enums) 250: end
# File lib/ffi/library.rb, line 252 252: def enum_value(symbol) 253: @ffi_enums.__map_symbol(symbol) 254: end
# File lib/ffi/library.rb, line 73 73: def ffi_convention(convention) 74: @ffi_convention = convention 75: end
# File lib/ffi/library.rb, line 41 41: def ffi_lib(*names) 42: 43: ffi_libs = names.map do |name| 44: if name == FFI::CURRENT_PROCESS 45: FFI::DynamicLibrary.open(nil, FFI::DynamicLibrary::RTLD_LAZY | FFI::DynamicLibrary::RTLD_LOCAL) 46: else 47: libnames = (name.is_a?(::Array) ? name : [ name ]).map { |n| [ n, FFI.map_library_name(n) ].uniq }.flatten.compact 48: lib = nil 49: errors = {} 50: 51: libnames.each do |libname| 52: begin 53: lib = FFI::DynamicLibrary.open(libname, FFI::DynamicLibrary::RTLD_LAZY | FFI::DynamicLibrary::RTLD_LOCAL) 54: break if lib 55: rescue Exception => ex 56: errors[libname] = ex 57: end 58: end 59: 60: if lib.nil? 61: raise LoadError.new(errors.values.join('. ')) 62: end 63: 64: # return the found lib 65: lib 66: end 67: end 68: 69: @ffi_libs = ffi_libs 70: end
# File lib/ffi/library.rb, line 78 78: def ffi_libraries 79: raise LoadError.new("no library specified") if !defined?(@ffi_libs) || @ffi_libs.empty? 80: @ffi_libs 81: end
# File lib/ffi/library.rb, line 256 256: def find_type(name) 257: code = if defined?(@ffi_typedefs) && @ffi_typedefs.has_key?(name) 258: @ffi_typedefs[name] 259: elsif defined?(@ffi_callbacks) && @ffi_callbacks.has_key?(name) 260: @ffi_callbacks[name] 261: elsif name.is_a?(Class) && name < FFI::Struct 262: FFI::NativeType::POINTER 263: elsif name.kind_of?(FFI::Type) 264: name 265: end 266: if code.nil? || code.kind_of?(Symbol) 267: FFI.find_type(name) 268: else 269: code 270: end 271: end
# File lib/ffi/library.rb, line 209 209: def typedef(current, add, info=nil) 210: @ffi_typedefs = Hash.new unless defined?(@ffi_typedefs) 211: code = if current.kind_of?(FFI::Type) 212: current 213: elsif current == :enum 214: if add.kind_of?(Array) 215: self.enum(add) 216: else 217: self.enum(info, add) 218: end 219: else 220: @ffi_typedefs[current] || FFI.find_type(current) 221: end 222: 223: @ffi_typedefs[add] = code 224: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.