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.