Subject:
Re: [ruby-ffi] Behavior of ffi_lib with Arrays (Was: lists only one lib?)
From:
Vladimir Sizikov
Date:
12/22/09 1:56 AM
To:
ruby-ffi@googlegroups.com

Hi Jon,

If memory serves, Wayne tweaked ffi_lib behavior in such a way that:

a) doing ffil_lib 'one', 'two', 'three' would load up all three
libraries, or fail if any of them couldn't be found for some reason

b) doing ffi_lib ['var1', 'var2', 'var3'] would load some variant of
the same library

c) doing ffi_lib 'lib1', 'lib2', ['lib3-1', 'lib3-2', 'lib3-3'] would
load lib1, lib2 and one variant of lib3 from the array of
alternatives.

Thanks,
  --Vladimir

On Mon, Dec 21, 2009 at 11:49 PM, John Croisant <jacius@gmail.com> wrote:
> On Sat, Dec 19, 2009 at 6:35 AM, Wayne Meissner <wmeissner@gmail.com> wrote:
>> You need to list them all on the same line.
>>
>> i.e.
>>
>>  ffi_lib 'user32', 'msvcrt'
>
> I always thought that giving multiple args to ffi_lib was a way of
> providing fallback libraries /alternate names in case the first one
> failed. I guess I assumed that it didn't make sense (or wouldn't work)
> to load more than one library into the same module, anyway. I'm not
> sure why I assumed that, though.
>
> Actually, looking at the code... it seems like it was written to
> possibly expect to be given an Array (or even multiple Arrays), and
> only to load the first library per array that succeeds. I guess that's
> what confused me.
>
> Simplified code to show what I mean:
>
>> def ffi_lib(*names)
>>   ffi_libs = names.map do |name|
>>     libnames = (name.is_a?(::Array) ? name : [ name ]).map { |n| [ n, FFI.map_library_name(n) ].uniq }.flatten.compact
>>
>>     libnames.each do |libname|
>>       lib = FFI::DynamicLibrary.open(libname, ...)
>>       break if lib
>>     end
>>
>>     # return the found lib
>>     lib
>>   end
>>
>>   @ffi_libs = ffi_libs
>> end
>
> Digging through the commit history, it looks like this was carried
> over from a time when ffi_lib expected an explicit array of library
> names. Is the Array form still supported? If not, the ffi_lib function
> can be simplified. If yes, there is a TypeError when passing an Array
> that should be fixed:
>
>> module SDL
>>   extend FFI::Library
>>   ffi_lib ["SDL"]
>> end
>
>> TypeError: can't convert Array into String
>>       from /usr/lib/ruby19/gems/1.9.1/gems/ffi-0.5.4/lib/ffi/ffi.rb:61:in `basename'
>>       from /usr/lib/ruby19/gems/1.9.1/gems/ffi-0.5.4/lib/ffi/ffi.rb:61:in `map_library_name'
>>       from /usr/lib/ruby19/gems/1.9.1/gems/ffi-0.5.4/lib/ffi/library.rb:8:in `block in ffi_lib'
>>       from /usr/lib/ruby19/gems/1.9.1/gems/ffi-0.5.4/lib/ffi/library.rb:7:in `each'
>>       from /usr/lib/ruby19/gems/1.9.1/gems/ffi-0.5.4/lib/ffi/library.rb:7:in `ffi_lib'
>
>
> - John
>