Subject: [ruby-ffi] :varargs sometimes works, sometimes don't |
From: Quintus |
Date: 4/27/10 12:19 PM |
To: ruby-ffi |
Hi there, I have two pieces of Ruby code, which do essentially the same. I created the first one during experimenting with the GTK dialog display functions, and the second was aimed on creating a Rubyish MessageBox object from it. The first works correctly and displays the message box - the second fails with a quite strange error message: -------------------------------------------------------------- /opt/rubies/ruby-1.9.1-p378/lib/ruby/gems/1.9.1/gems/ffi-0.6.3/lib/ffi/ types.rb:46:in `find_type': Unable to resolve type 'string' (TypeError) from /opt/rubies/ruby-1.9.1-p378/lib/ruby/gems/1.9.1/gems/ffi-0.6.3/ lib/ffi/variadic.rb:47:in `call' from (eval):3:in `g_object_set' from gtkbox.rb:66:in `show' from gtkbox.rb:76:in `<main>' ------------------------------------------------------------- What's the matter? As far as I know, :string as a regular type in FFI. Here's the (working) first attempt: ------------------------------------------------------------- #!/usr/bin/env ruby #Encoding: UTF-8 require "ffi" module GTK extend FFI::Library ffi_lib("gtk-x11-2.0.so") attach_function(:gtk_init, [:pointer, :pointer], :void) attach_function(:gtk_set_locale, [], :void) attach_function(:gtk_message_dialog_new, [:pointer, :int, :int, :int, :string], :pointer) attach_function(:g_object_set, [:pointer, :varargs], :void) attach_function(:gtk_dialog_run, [:pointer], :int) attach_function(:gtk_widget_destroy, [:pointer], :void) end GTK.gtk_init(nil, nil) GTK.gtk_set_locale() dialog = GTK.gtk_message_dialog_new(nil, 0, 0, 2, "title") GTK.g_object_set(dialog, :string, "secondary-text", :string, "text", :pointer, nil) GTK.gtk_dialog_run(dialog) GTK.gtk_widget_destroy(dialog) ------------------------------------------------------------- And here's the (non-working) second: ------------------------------------------------------------- #!/usr/bin/env ruby #Encoding: UTF-8 require "ffi" module MessageBox class GTKBox module Functions extend FFI::Library @init = false def self.init return false if @init begin ffi_lib("gtk-x11-2.0.so") enum :type, [ :gtk_message_info, :gtk_message_warning, :gtk_message_question, :gtk_message_error, :gtk_message_other ] enum :buttons, [:gtk_buttons_none, :gtk_button_ok, :gtk_buttons_close, :gtk_buttons_cancel, :gtk_buttons_yes_no, :gtk_buttons_ok_cancel ] attach_function(:gtk_init, [:pointer, :pointer], :void) attach_function(:gtk_set_locale, [], :void) attach_function(:gtk_message_dialog_new, [:pointer, :int, :type, :buttons, :string], :pointer) attach_function(:g_object_set, [:pointer, :varargs], :void) attach_function(:gtk_dialog_run, [:pointer], :int) attach_function(:gtk_widget_destroy, [:pointer], :void) #Initialize GTK and set it to the current locale. gtk_init(nil, nil) gtk_set_locale() @init = true rescue LoadError raise(NotImplementedError, "GTK+ >= 2.10 is not installed on your system.") end #begin end #init end #Functions attr_reader :title attr_reader :text attr_accessor :icon attr_accessor :buttons def initialize(title, text) GTKBox::Functions.init @title = title @text = text @icon = :gtk_message_info @buttons = :gtk_button_ok end def show dialog = Functions.gtk_message_dialog_new(nil, 0, @icon, @buttons, @title) Functions.g_object_set(dialog, :string, "secondary- text", :string, @text, :pointer, nil) Functions.gtk_dialog_run(dialog) Functions.gtk_widget_destroy(dialog) end end end msgbox = MessageBox::GTKBox.new("title", "text") msgbox.show ------------------------------------------------------------- In case if you wonder why I don't define the FFI methods in MessageBox::GTKBox::Functions directly, the answer is that I want to create a system-independant library of displaying message boxes. And if someone uses that library on Windows, FFI tries to load the GTK shared object file which results in a program crash since it isn't there. Now this is just the case if someone tries to display a GTK box on Windows (which would work if GTK is installed, I know, but that's for later). I also noticed that if I removed the call to the g_object_set() function, everything works fine, so I suppose there's something wrong when resolving :varargs. I'm using ruby 1.9.1p378 (2010-01-10 revision 26273) [x86_64-linux] on Ubuntu Karmic Koala. I think that code works for every Linux that has GTK+ installed, but if not, please correct me since I'm planning to make a Gem for those message dialog functions in GTK+, KDE, Windows... Any ideas? Marvin-- Subscription settings: http://groups.google.com/group/ruby-ffi/subscribe?hl=en