Here is a Ruby example using the [Fiddle Foreign Function Interface wrapper](https://github.com/ruby/fiddle), and the  [dtwainapi.rb](https://github.com/dynarithmic/twain_library/tree/master/programming_language_bindings/Ruby) interface file that defines the DTWAIN constants and functions.  

The program gives an example of selecting a TWAIN device installed on your system, displaying a list of the capabilities available to the device, and acquiring a BMP image.

```ruby
#!/usr/bin/env ruby
require_relative 'dtwainapi'

if __FILE__ == $0
  # Initialize DTWAIN

  # load the 64-bit Unicode version of DTWAIN DLL. 
  # If you are running in a 32-bit environment, then the DLL should be dtwain32.dll, dtwain32u.dll, etc.

  dtwain_dll = DTWAINAPI.new('dtwain64u.dll') # replace with the absolute path to the dll here
  if !dtwain_dll.isInitialized()
      puts "Not initialized: #{dtwain_dll.isInitialized}" 
      return
  end

  #dll found and loaded, so start the initialization
  dtwain_dll.DTWAIN_SysInitialize.call()

  # Select a TWAIN souce
  twainSource = dtwain_dll.DTWAIN_SelectSource.call()

  if twainSource.null?
      puts "No TWAIN source was selected"
      return
  end

  # Display the product name of the Source
  # Create a char buffer to allow calling DTWAIN_GetSourceProductNameA
  #
  # If instead you wanted to call DTWAIN_GetSourceProductName, you will need a Unicode
  # buffer, since Ruby loaded the Unicode version of the DTWAIN DLL
  #
  # Allocate a Fiddle::Pointer for the buffer (e.g., 256 bytes)
  buffer_size = 256
  buffer = Fiddle::Pointer.malloc(buffer_size) 
  dtwain_dll.DTWAIN_GetSourceProductNameA.call(twainSource, buffer, 256)

  # convert buffer to ruby string
  result_string = buffer.to_s
  puts "Device product name is: #{result_string}" 

  # Example usage of DTWAIN_ARRAY:
  # Get the device capabilities supported by the device
  #
  # Note: The DTWAIN_ARRAY, DTWAIN_SOURCE, DTWAIN_FRAME, and DTWAIN_RANGE are actually void pointers
  # so you have to declare them as such if a DTWAIN function requires a parameter to be of this type.
  #
  # For Ruby, it is much easier to call the DTWAIN function(s) that return DTWAIN_ARRAY's and similar 
  # instead of  the version(s) that allows passing a pointer to a DTWAIN_ARRAY.  So in this case, we call
  # DTWAIN_EnumSupportedCapsEx
  
  # get the supported caps
  dtwain_array = dtwain_dll.DTWAIN_EnumSupportedCapsEx.call(twainSource)

  # get the number of items in the array
  arrCount = dtwain_dll.DTWAIN_ArrayGetCount.call(dtwain_array)
  puts "There are #{arrCount} device capabilities"
    
  #print each capability
  long_val = Fiddle::Pointer.malloc(Fiddle::SIZEOF_INT)
  long_val[0, Fiddle::SIZEOF_INT] = [0].pack("l!")

  arrCount.times do |i| 
      dtwain_dll.DTWAIN_ArrayGetAtLong.call(dtwain_array, i, long_val)
      modified_value = long_val[0, Fiddle::SIZEOF_INT].unpack("l!").first

      dtwain_dll.DTWAIN_GetNameFromCapA.call(modified_value, buffer, 256)
      result_string = buffer.to_s
      puts "Capability #{i+1}: #{result_string}  Value: #{modified_value}"
    end

  # Now Acquire to a BMP file
  dtwain_dll.DTWAIN_AcquireFileA.call(twainSource, "TEST.BMP", DTWAINAPI::DTWAIN_BMP, DTWAINAPI::DTWAIN_USELONGNAME,
                             DTWAINAPI::DTWAIN_PT_DEFAULT, 1, 1, 1, Fiddle::Pointer.new(0))

  dtwain_dll.DTWAIN_SysDestroy.call()
end
```

