How can I load Windows DLL files with Ruby fiddle?

1.5k Views Asked by At

I am trying to create a GR framework binding for ruby. I use Fiddle. Fiddle is a default extension to translate a foreign function interface (FFI) with ruby. It Works well on Linux and Mac. But on Windows, I got following error.

code hoge.rb

require 'fiddle/import'

module M
   extend extend Fiddle::Importer
   dlload File.expand_path('gr/bin/libGR.dll').gsub("/", "\\")
end

error

Traceback (most recent call last):
        7: from hoge.rb:3:in `<main>'
        6: from hoge.rb:5:in `<module:M>'
        5: from C:/Ruby26-x64/lib/ruby/2.6.0/fiddle/import.rb:77:in `dlload'
        4: from C:/Ruby26-x64/lib/ruby/2.6.0/fiddle/import.rb:77:in `collect'
        3: from C:/Ruby26-x64/lib/ruby/2.6.0/fiddle/import.rb:87:in `block in dlload'
        2: from C:/Ruby26-x64/lib/ruby/2.6.0/fiddle.rb:47:in `dlopen'
        1: from C:/Ruby26-x64/lib/ruby/2.6.0/fiddle.rb:47:in `new'
C:/Ruby26-x64/lib/ruby/2.6.0/fiddle.rb:47:in `initialize': No such file or directory (Fiddle::DLError)
        5: from hoge.rb:3:in `<main>'
        4: from hoge.rb:5:in `<module:M>'
        3: from C:/Ruby26-x64/lib/ruby/2.6.0/fiddle/import.rb:77:in `dlload'
        2: from C:/Ruby26-x64/lib/ruby/2.6.0/fiddle/import.rb:77:in `collect'
        1: from C:/Ruby26-x64/lib/ruby/2.6.0/fiddle/import.rb:86:in `block in dlload'
C:/Ruby26-x64/lib/ruby/2.6.0/fiddle/import.rb:89:in `rescue in block in dlload': can't load C:\Users\kojix2\gr\bin\libgr.dll (Fiddle::DLError)
  • Windows 10
  • Ruby 2.6.5 + DevKit

ruby-ffi works well.

require 'ffi'

module M
   extend FFI::Library
   ffi_lib File.expand_path('gr/bin/libGR.dll').gsub("/", "\\")
end

But I want to use fiddle instead of ruby-ffi in this time. What should I do next?

1

There are 1 best solutions below

0
On

I answer my own questions.

1. Use RubyInstaller::Runtime.add_dll_directory

DLL loading https://github.com/oneclick/rubyinstaller2/wiki/For-gem-developers#-dll-loading

  • The PATH environment variable is ignored for all DLL searches.
  • Environment variable RUBY_DLL_PATH is interpreted at the ruby startup - later changes doesn't affect the running process.
  • Use the Ruby function add_dll_directory to do runtime changes to DLL search paths.

2. Use SetDllDirectory()

Alternatively, you can run SetDllDirectory.

require 'fiddle/import'
require 'fiddle/types'
module WinAPI
  extend Fiddle::Importer
  dlload 'kernel32.dll'
  include Fiddle::Win32Types
  extern 'int SetDllDirectory(LPCSTR)'
end
WinAPI.SetDllDirectory(File.expand_path(path))