A long-lived project that still receives updates
Ruby bindings to libui
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
 Dependencies
 Project Readme

LibUI

test Gem Version glimmer-dsl-libui Pre-build Lines of Code

LibUI is a Ruby wrapper for libui family.

🚀 libui-ng - A cross-platform portable GUI library

🔧 libui-dev - Native UI library for C - with some extras

🔘 libui - Original version by andlabs.

Installation

It is recommended to use libui-ng, via the --pre commandline flag:

gem install libui --pre # libui-ng; this will fetch libui-0.1.3.pre-x86_64-linux.gem

If for some reason you would like to install the slightly older libui-0.1.2.gem release, issue:

gem install libui
  • The gem package includes the libui-ng shared library for Windows, Mac, and Linux.
    • Namely libui.dll, libui.dylib, or libui.so.
  • No dependencies required.
    • The libui gem uses the standard Ruby library Fiddle to call C functions.
Windows Mac Linux

Notes:

  • If you are using the 32-bit (x86) version of Ruby, you need to download the 32-bit (x86) native dll. See the Development section.
  • On Windows, libui may not work due to missing DLLs. In that case, you need to install Visual C++ Redistributable. See (#48)
  • Users with Raspberry Pi or other platforms will need to compile the C libui library. See the Development section.

Usage

require 'libui'

UI = LibUI

UI.init

main_window = UI.new_window('hello world', 200, 100, 1)

button = UI.new_button('Button')

UI.button_on_clicked(button) do
  UI.msg_box(main_window, 'Information', 'You clicked the button')
end

UI.window_on_closing(main_window) do
  puts 'Bye Bye'
  UI.quit
  1
end

UI.window_set_child(main_window, button)
UI.control_show(main_window)

UI.main
UI.quit

For more examples, see the examples directory.

General Rules

Compared to the original libui library written in C:

  • Method names use snake_case.
  • The last argument can be omitted if it's nil.
  • A block can be passed as a callback.
    • The block will be converted to a Proc object and added as the last argument.
    • The last argument can still be omitted when nil.

You can use the documentation for libui's Go bindings as a reference.

DSLs for LibUI

LibUI is not object-oriented because it is a thin Ruby wrapper (binding) for the procedural C libui library, mirroring its API structure.

To build actual applications, it is recommended to use a DSL for LibUI, as they enable writing object-oriented code the Ruby way (instead of procedural code the C way):

Working with fiddle pointers

require 'libui'
UI = LibUI
UI.init

To convert a pointer to a string:

label = UI.new_label("Ruby")
p pointer = UI.label_text(label) # #<Fiddle::Pointer>
p pointer.to_s # Ruby

If you need to use C structs, you can do the following:

font_button = UI.new_font_button

# Allocate memory
font_descriptor = UI::FFI::FontDescriptor.malloc
font_descriptor.to_ptr.free = Fiddle::RUBY_FREE
# font_descriptor = UI::FFI::FontDescriptor.malloc(Fiddle::RUBY_FREE) # fiddle 1.0.1 or higher

UI.font_button_on_changed(font_button) do
  UI.font_button_font(font_button, font_descriptor)
  p family:  font_descriptor.Family.to_s,
    size:    font_descriptor.Size,
    weight:  font_descriptor.Weight,
    italic:  font_descriptor.Italic,
    stretch: font_descriptor.Stretch
end
  • Callbacks
    • In Ruby/Fiddle, a C callback function is written as an object of Fiddle::Closure::BlockCaller or Fiddle::Closure. Be careful about Ruby's garbage collection - if the function object is collected, memory will be freed resulting in a segmentation violation when the callback is invoked.
# Assign to a local variable to prevent it from being collected by GC.
handler.MouseEvent   = (c1 = Fiddle::Closure::BlockCaller.new(0, [0]) {})
handler.MouseCrossed = (c2 = Fiddle::Closure::BlockCaller.new(0, [0]) {})
handler.DragBroken   = (c3 = Fiddle::Closure::BlockCaller.new(0, [0]) {})

Creating a Windows executable (.exe) with OCRA

OCRA (One-Click Ruby Application) builds Windows executables from Ruby source code.

To build an exe with Ocra, include 3 DLLs from the ruby_builtin_dlls folder:

ocra examples/control_gallery.rb        ^
  --dll ruby_builtin_dlls/libssp-0.dll  ^
  --dll ruby_builtin_dlls/libgmp-10.dll ^
  --dll ruby_builtin_dlls/libffi-7.dll  ^
  --gem-all=fiddle                      ^

Add additional options below if necessary:

  --window                              ^
  --add-all-core                        ^
  --chdir-first                         ^
  --icon assets\app.ico                 ^
  --verbose                             ^
  --output out\gallery.exe

Development

git clone https://github.com/kojix2/libui
cd libui
bundle install
bundle exec rake vendor:auto
bundle exec rake test

Pre-built shared libraries for libui-ng

Download pre-built libui-ng shared libraries (per your current platform):

bundle exec rake vendor:auto

Clean downloaded vendor files (keeps vendor/{LICENSE,README}.md):

bundle exec rake vendor:clean

Using your own libui build

If you build libui-ng yourself, set LIBUIDIR to the directory containing the compiled .so/.dylib/.dll so LibUI can load it. You may also replace files under vendor/ with your build if preferred. See #46.

Publishing gems

Automated Publishing

Push a version tag to automatically publish platform-specific gems:

git tag v0.1.3
git push origin v0.1.3

Requires RUBYGEMS_API_KEY repository secret with scoped API key.

Manual Publishing

ls vendor             # check the vendor directory
rm -rf pkg            # remove previously built gems
rake build_platform   # build gems

# Check the contents of the gem
find pkg -name *.gem -exec sh -c "echo; echo \# {}; tar -O -f {} -x data.tar.gz | tar zt" \;

rake release_platform # publish gems

Windows Ruby 2.7 (x64-mingw32)

gem install rake rubyzip
GEM_PLATFORM=x64-mingw32 rake vendor:clean
GEM_PLATFORM=x64-mingw32 rake vendor:auto
GEM_PLATFORM=x64-mingw32 gem build libui.gemspec
gem push libui-0.2.0-x64-mingw32.gem

libui or libui-ng

  • From version 0.1.X, we plan to support only libui-ng/libui-ng.
  • Version 0.0.X only supports andlabs/libui.

Contributing

Would you like to contribute to LibUI?

  • Please feel free to send us your pull requests.
    • Small corrections, such as typo fixes, are appreciated.
  • Did you find any bugs? Submit them in the issues section!

Do you need commit rights?

  • If you need commit rights to my repository or want to get admin rights and take over the project, please feel free to contact @kojix2.
  • Many OSS projects become abandoned because only the founder has commit rights to the original repository.

Support libui-ng development

  • Contributing to the development of libui-ng is a contribution to the entire libui community, including Ruby's LibUI.
  • For example, it would be easier to release LibUI in Ruby if libui-ng could be built easily and official shared libraries could be distributed.

Acknowledgements

This project is inspired by libui-ruby.

While libui-ruby uses Ruby-FFI, this gem uses Fiddle.

License

MIT License.