danini-the-panini / mittsu

3D Graphics Library for Ruby.
https://github.com/danini-the-panini/mittsu
MIT License
508 stars 33 forks source link

fix: GLFW.load_lib() on Windows OS #103

Closed yusuke-ota closed 2 years ago

yusuke-ota commented 3 years ago

I'm not a native English speaker, so I apologize for any strange English.

Table of contents

Summary

On Windows PC, I cannot load glfw3.dll because the argument of GLFW.load_lib(file, path) is wrong.

This pull request adds a method for the Windows platform so that glfw3.dll can be loaded.

About Error

When I use mittsu on a windows PC, I get a type error in opengl-bindings/glfw.rb.

# main.rb
require 'mittsu'
# Powershell script to set env and run main.rb.
$ENV:MITTSU_LIBGLFW_PATH = "C:\Users\username\lib-mingw-w64"
# or $ENV:MITTSU_LIBGLFW_PATH = "C:\Users\username\lib-mingw-w64\glfw3.dll"
bundle exec ruby main.rb
# Error log
C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/opengl-bindings-1.6.11/lib/glfw.rb:505:in `+': no implicit conversion of nil into String (TypeError)
        from C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/opengl-bindings-1.6.11/lib/glfw.rb:505:in `load_lib'
        from C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/mittsu-0.3.3/lib/mittsu/renderers/glfw_window.rb:8:in `<top (required)>'
        from C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/mittsu-0.3.3/lib/mittsu/renderers/opengl_renderer.rb:9:in `require'
        from C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/mittsu-0.3.3/lib/mittsu/renderers/opengl_renderer.rb:9:in `<top (required)>'
        from C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/mittsu-0.3.3/lib/mittsu/renderers.rb:1:in `require'
        from C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/mittsu-0.3.3/lib/mittsu/renderers.rb:1:in `<top (required)>'
        from C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/mittsu-0.3.3/lib/mittsu.rb:11:in `require'
        from C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/mittsu-0.3.3/lib/mittsu.rb:11:in `<top (required)>'
        from main.rb:1:in `require'
        from main.rb:1:in `<main>'

On Windows OS, this error occurs when calling GLFW.load_lib(nil, ENV["MITTSU_LIBGLFW_PATH"]) because it is not the expected argument.

mittsu glfw_window.rb

# glfw_window.rb in windows os
require 'opengl'
require 'glfw'

require 'mittsu/utils'
require 'mittsu/renderers/glfw_lib'
glfw_lib = Mittsu::GLFWLib.discover

GLFW.load_lib(ENV["MITTSU_LIBGLFW_FILE"] || glfw_lib.file, ENV["MITTSU_LIBGLFW_PATH"] || glfw_lib.path) unless Mittsu.test?
# => GLFW.load_lib(nil, "C:\\Users\\username\\lib-mingw-w64")
...

opengl-bindings glfw.rb

# opengl-bindings glfw.rb
# Called as GLFW.load_lib(nil, "C:\\Users\\username\\lib-mingw-w64")
...
def self.load_lib(lib = nil, path = nil, output_error = false)
  if lib == nil && path == nil
    case OpenGL.get_platform
    when :OPENGL_PLATFORM_WINDOWS
      lib, path = 'GLFW3.dll', Dir.pwd
    when :OPENGL_PLATFORM_MACOSX
      lib, path = 'libglfw.dylib', Dir.pwd
    else
      lib = 'libglfw.so'
    end
  end

  if path
    dlload (path + '/' + lib)
    # => dlload("C:\\Users\\username\\lib-mingw-w64" + '/' + nil)
    #                                                  ^^^^^^^^^
    # `+': no implicit conversion of nil into String (TypeError)
  else
    dlload (lib)
  end
  import_symbols(output_error) unless @@glfw_import_done
end
...

About Fix

I believe this problem can be solved by defining a method for windows os in "glfw_lib.rb".

# mittsu/renderer/glfw_lib.rb
...
class Windows < GenericLib::Base
+ def file
+   'glfw3.dll'
+ end
end
...

Expected Behavior

# glfw_window.rb in windows os
require 'opengl'
require 'glfw'

require 'mittsu/utils'
require 'mittsu/renderers/glfw_lib'
glfw_lib = Mittsu::GLFWLib.discover

GLFW.load_lib(ENV["MITTSU_LIBGLFW_FILE"] || glfw_lib.file, ENV["MITTSU_LIBGLFW_PATH"] || glfw_lib.path) unless Mittsu.test?
# => GLFW.load_lib('glfw3.dll', "C:\\Users\\username\\lib-mingw-w64")
...
# opengl-bindings glfw.rb
# Called as GLFW.load_lib('glfw3.dll', "C:\\Users\\username\\lib-mingw-w64")
...
def self.load_lib(lib = nil, path = nil, output_error = false)
  ...

  if path
    dlload (path + '/' + lib)
    # => dlload("C:\\Users\\username\\lib-mingw-w64" + '/' + 'glfw3.dll')
  else
    dlload (lib)
  end
  import_symbols(output_error) unless @@glfw_import_done
end
...
danini-the-panini commented 3 years ago

@yusuke-ota Thank you so much for this! I'll take a look at it when I get some time, my day job is a little hectic at the moment.