gir_ffi-0.16.1/0000755000004100000410000000000014524576001013240 5ustar www-datawww-datagir_ffi-0.16.1/docs/0000755000004100000410000000000014524576001014170 5ustar www-datawww-datagir_ffi-0.16.1/docs/Subclassing.md0000644000004100000410000000220714524576001016770 0ustar www-datawww-data# Subclassing Creating a Ruby subclass of one of the GObject classes requires following some rules. First of all, if you override the initializer, you **must** call `super` otherwise, the underlying GObject pointer will not be created and stored. Second, GObject objects often have several constructors. GirFFI creates a separate initializer for each constructor. This allows customization of the call to super for each initializer. This means you will have to override each initializer separately, as needed. As an example, here is a subclass of `Regress::TestSubObj`, a class from GObjectIntrospection's test suite, adding an extra argument to some of its constructors. ``` class MyObj < Regress::TestSubObj attr_reader :animal def initialize animal super() @animal = animal end def initialize_from_file animal, file super(file) @animal = animal end end o1 = MyObj.new 'dog' o1.foo # => 'dog' o2 = MyObj.constructor o2.foo # => nil o3 = MyObj.new_from_file 'cat', 'my_file.txt' o3.foo # => 'cat' ``` gir_ffi-0.16.1/docs/Documentation.md0000644000004100000410000000024414524576001017323 0ustar www-datawww-data# Documentation See [the README](../README.md) for basic usage. See [Subclassing](Subclassing.md) for details on creating your own subclasses of GObject classes. gir_ffi-0.16.1/DESIGN.md0000644000004100000410000000647414524576001014546 0ustar www-datawww-data# Design of Gir-FFI ## Basic Idea Gir-FFI uses FFI to read information from the GObject Introspection Repository. Based on that it creates bindings for the information read. ## Class and method creation GirFFI::Builder creates classes and modules at runtime and adds appropriate method_missing methods to them to generate methods and perhaps other classes when required. The following options were discarded, at least for now. * Create classes and all of their methods at runtime. This would be very similar to the method chosen, but would concentrate all the overhead at start-up, some of which would be used for creating methods that will never get called. * Allow offline creation of ruby source generated from the GIR. This is still in interesting idea, but off-line source code generation is not really the Ruby way. ## Method Naming Probably, get_x/set_x pairs should become x and x= to be more Ruby-like. This should be done either by defining them as such directly, or by aliasing. Blindly going by the name leads to weird results thoough, like having x, x= and x_full= as a set. Also, some get_ or set_ methods take extra arguments. These probably shouldn't become accessors either. Boolean-valued methods could get a ? at the end. This requires a lot more thought. For now, the full method names as defined in the GIR are used. ## Ruby-GNOME Compatibility Full Ruby-GNOME compatibility cannot be achieved automatically, since its object hierarchy differs from that of standard GObject: It puts Object in the GLib namespace, and defines signal_connect and friends as methods of GLib::Instantiable; In standard GObject they are functions. Possibly, compatibility enhancing code can be added for these specific exceptions. ## Reference Counting Because we can always make sure GObjects are unref'd when the Ruby object is GC'd, the mechanism of floating references actually gets in the way a bit. Therefore, when floating GObjects are constructed, GirFFI will sink them. All GObjects can then safely be unref'd using a Ruby finalizer. GObjects obtained through other mechanisms than with a constructor will be ref'd once when wrapping them in a ruby object. ## Bootstrapping Class Design The interface to the GObject Introspection Repository itself is also introspectable. The interface is specified in terms of structs and functions rather than objects and methods. For now, the hard-coded Ruby bindings for this don't follow the introspected specification: Gir-FFI cannot bootstrap itself. ## Object initialization Each constructor method is implemented in Ruby by a pair of new/initialize methods. For example, a constructor `new_from_file` is implemented as a combination of the singleton method `new_from_file` and the instance method `initialize_from_file`. User-created subclasses override the appropriate initializer method and must call super with the appropriate arguments. Here is an example of the generated pair of methods: ```ruby class Regress::TestObj def self.new_from_file(*args) obj = allocate obj.__send__ :initialize_from_file, *args obj end def initialize_from_file(x) _v1 = GirFFI::InPointer.from(:utf8, x) _v2 = FFI::MemoryPointer.new(:pointer).write_pointer nil _v3 = Regress::Lib.regress_test_obj_new_from_file _v1, _v2 GirFFI::ArgHelper.check_error(_v2) store_pointer(_v3) end end gir_ffi-0.16.1/README.md0000644000004100000410000000700714524576001014523 0ustar www-datawww-data# GirFFI by Matijs van Zuijlen ## Description Ruby bindings for GNOME using the GObject Introspection Repository. ## Status [![Gem Version](https://badge.fury.io/rb/gir_ffi.svg)](http://badge.fury.io/rb/gir_ffi) [![Build Status](https://github.com/mvz/gir_ffi/actions/workflows/ruby.yml/badge.svg)](https://github.com/mvz/gir_ffi/actions/workflows/ruby.yml) [![Code Climate](https://codeclimate.com/github/mvz/gir_ffi/badges/gpa.svg)](https://codeclimate.com/github/mvz/gir_ffi) [![Documentation Status](https://inch-ci.org/github/mvz/gir_ffi.svg?branch=master)](https://inch-ci.org/github/mvz/gir_ffi) ## Features * Create bindings to any GObject-based library. * Bindings are generated at runtime. * Provides overridden bindings for selected methods. * Install `gir_ffi-gtk` and require `gir_ffi-gtk2` or `gir_ffi-gtk3` to load overrides for Gtk2 or Gtk3. ## Usage ```ruby require 'gir_ffi' # Set up the namespace you wish to use GirFFI.setup :Gio # Create an object inet_address = Gio::InetAddress.new_from_string "127.0.0.1" # Call some methods on the object inet_address.is_loopback # => true inet_address.is_multicast # => false # Call a function in the namespace Gio.dbus_is_name "foo" # => false ``` See the [documentation](docs/Documentation.md) for more usage information. ## Examples Have a look in the `examples/` directory for some simple examples. More examples can be found in the repositories for [`gir_ffi-gtk`](https://github.com/mvz/gir_ffi-gtk) and [`gir_ffi-gst`](https://github.com/mvz/gir_ffi-gst/). ## Install ```bash gem install gir_ffi ``` ## Requirements GirFFI is supported on CRuby 2.7, 3.0 and 3.1. You will also need gobject-introspection installed with some introspection data. Depending on the GIR data, GirFFI needs the actual libraries to be available under the name ending in plain `.so`. If GirFFI complains that it cannot find the library, try installing development packages for those libraries. GirFFI should work with gobject-introspection 1.56.0 and up, and glib 2.56.0 and up. On Debian and Ubuntu, installing `libgirepository-1.0-1` and `gir1.2-glib-2.0` should be enough to use GirFFI in your application. To run the tests, you should additionally install `libgirepository1.0-dev`, `gobject-introspection`, `libcairo2-dev`, `gir1.2-gtop-2.0`, `gir1.2-gtk-3.0`, `gir1.2-pango-1.0`, `gir1.2-gtksource-3.0`, `gir1.2-secret-1` and `gir1.2-gstreamer-1.0`. This should be enough to get `rake test` working. GirFFI has not been tested on Mac OS X or Microsoft Windows. YMMV. Pull requests to support these platforms are welcome. ## Overrides Sometimes, the GIR data is incorrect, or not detailed enough, and a reasonable binding cannot be created automatically. For these cases, overrides can be defined. The following gems with overrides already exist: * `gir_ffi-gtk`: overrides for Gtk+ 2 and 3. * `gir_ffi-gnome_keyring`: overrides for GnomeKeyring * `gir_ffi-cairo`: overrides for Cairo * `gir_ffi-pango`: overrides for Pango * `gir_ffi-tracker`: overrides for Tracker * `gir_ffi-gst`: overrides for GStreamer ## Contributing Please see [CONTRIBUTING.md](CONTRIBUTING.md) for contribution guidelines. ## Contributors The following people have contributed to GirFFI over the years: * John Cupitt * Marius Hanne * Antonio Terceiro * Matijs van Zuijlen ## License Copyright © 2009–2022 [Matijs van Zuijlen](http://www.matijs.net) GirFFI is free software, distributed under the terms of the GNU Lesser General Public License, version 2.1 or later. See the file COPYING.LIB for more information. gir_ffi-0.16.1/TODO.md0000644000004100000410000000770514524576001014340 0ustar www-datawww-data# TODO ## Memory managment GirFFI does not ~~attempt to free any memory at the moment, or~~ lower the reference count of any objects it gets from GObject. This task therefore involves two parts: - Free non-GObject pointers as needed (at garbage-collection time) - [Done!] Lower reference count of GObjects (at garbage-collection time) **Use memory_profiler to check memory use (https://github.com/SamSaffron/memory_profiler)** ## Refactorings These in the order they occured to me, and may therefore be fixed in any order. - Create Type objects for all FFI types, including the ones currently represented by a single symbol, so we can always do stuff like > `GirFFI::Types::UInt8.get_value_from_pointer(ptr)` rather than having awkward dynamic method dispatch inside GirFFI::InOutPointer. - Move to a single Pointer class, rather than InPointer, InOutPointer and Pointer monkeypatching. ## Derived types Derived classes are now registered like so: class Derived < Base install_property GObject.param_spec_int("foo", "foo bar", "The Foo Bar Property", 10, 20, 15, 3) # assume Base defines a virtual function called 'some_vfunc' install_vfunc_implementation :some_vfunc, proc {|obj| # implementation goes here } def other_vfunc # implementation end # assume Base defines a virtual function called 'other_vfunc' install_vfunc_implementation :other_vfunc end GirFFI.define_type Derived Potential improvements: * Allow `define_type` to be called in the class definition * Perhaps auto-register types, like Gtk# does * Perhaps automagically find vfunc implementations, like PyGObject and Ruby-GNOME do * What about properties? NOTE: When adding an interface module to a derived class, its prerequisites should be checked. ## Persistent Ruby GObject identity GirFFI should make sure that if it gets a pointer to a GObject for which a Ruby object already exists, the existing object is returned. This involves the use of WeakRef, no doubt. ## Handle fundamental objects that are not GObject. This is a big one. See commit 1e9822c7817062a9b853269b9418fd78782090b5 in gobject-introspection, and TestFundamentalObject in Regress. The tests for TestFundamentalObject accidentally pass, but there may be hidden issues. ## Check binding of GObject: (11:37:03 PM) walters: the basic story is that GObject should be manually bound (11:47:02 PM) ebassi: the really necessary bits are: GObject/GInitiallyUnowned memory management; properties accessors; GSignal connection API (11:47:15 PM) ebassi: the rest is "nice to have" (11:47:37 PM) ebassi: oh, and probably GBinding - but that's just because I wrote it ;-) ## Use FFI::DataConverter to automatically convert GObject types GirFFI now generates loads of Something.wrap(ptr) calls; Perhaps these can be replace by implementing to_native and from_native in ClassBase and including FFI::DataConverter. ## Handle Variants more nicely Currently, GirFFI requires the user to create GVariant objects by hand, and retrieve values from them by hand as well. Ideally, we would have `.from_ruby` and `#to_ruby` methods or somesuch that do this for us. Some classes, like GAction, require a specifice VariantType to be used consistently. Special logic will have to be put in place for that. ## Handle ownership-transfer correctly For how to handle objects, see https://bugzilla.gnome.org/show_bug.cgi?id=657202#c1 ## Miscellaneous * Move GObjectIntrospection to GIRepository, and allow generating its own members. * Do something useful with the versioning info in the GIR ## External dependencies Things that I think GirFFI cannot fix: * gobject-introspection should correctly mark private fields as not readable. * gobject-introspection should ignore functions that are only defined but not implemented, or implement those cases in GIMarshallingTests. ## See Also dnote gir_ffi-0.16.1/examples/0000755000004100000410000000000014524576001015056 5ustar www-datawww-datagir_ffi-0.16.1/examples/main_loop.rb0000644000004100000410000000011314524576001017353 0ustar www-datawww-datarequire 'gir_ffi' main_loop = GLib::MainLoop.new nil, false main_loop.run gir_ffi-0.16.1/examples/clutter.rb0000644000004100000410000000460214524576001017067 0ustar www-datawww-data$LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib') require 'gir_ffi' GirFFI.setup :Clutter GirFFI.setup :GdkPixbuf class PhotoWall < Clutter::Stage STAGE_WIDTH = 800 STAGE_HEIGHT = 600 THUMBNAIL_SIZE = 200 ROW_COUNT = STAGE_HEIGHT / THUMBNAIL_SIZE COLUMN_COUNT = STAGE_WIDTH / THUMBNAIL_SIZE FOCUS_DEPTH = 100.0 UNFOCUS_DEPTH = 0.0 def self.create_for path stage = PhotoWall.new stage.instance_eval do @path = path @bricks = [] @images = Dir["#{@path}/**/*.{jpg,png}"] @focus = nil set_title "A PhotoWall" set_size STAGE_WIDTH, STAGE_HEIGHT ROW_COUNT.times do |row| COLUMN_COUNT.times do |column| break unless @images[row*COLUMN_COUNT + column] puts "Adding #{@images[row*COLUMN_COUNT + column]}" brick = LittleBrick.new_from_file(@images[row*COLUMN_COUNT + column], row, column) add_actor brick @bricks << brick end end show_all end GObject.signal_connect(stage, "destroy") { Clutter.main_quit } stage end class LittleBrick < Clutter::Actor attr_accessor :row, :col def self.new_from_file fname, row = 0, col = 0 brick = new image = Clutter::Image.new picture = GdkPixbuf::Pixbuf.new_from_file fname image.set_data(picture.get_pixels, picture.has_alpha ? :rgba_8888 : :rgb_888, picture.width, picture.height, picture.rowstride) brick.set_content image brick.instance_eval do @row = row @col = col set_size THUMBNAIL_SIZE, THUMBNAIL_SIZE set_position col * THUMBNAIL_SIZE, row * THUMBNAIL_SIZE set_reactive true end @@focus = nil GObject.signal_connect brick, "button-press-event" do |a_brick| if @@focus @@focus.unfocus else brick.focus end end brick end def focus @@focus = self set_position 0, 0 set_size STAGE_WIDTH, STAGE_HEIGHT raise_top end def unfocus set_position @col * THUMBNAIL_SIZE, @row * THUMBNAIL_SIZE set_size THUMBNAIL_SIZE, THUMBNAIL_SIZE @@focus = nil end end end Clutter.init [] picture_directory = GLib.get_user_special_dir :directory_pictures PhotoWall.create_for picture_directory Clutter.main gir_ffi-0.16.1/lib/0000755000004100000410000000000014524576001014006 5ustar www-datawww-datagir_ffi-0.16.1/lib/ffi-gobject.rb0000644000004100000410000000567414524576001016526 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/core" # Bypass check for existing modules GirFFI::Builders::ModuleBuilder.new("GObject").generate require "ffi-gobject/value" require "ffi-gobject/initially_unowned" require "ffi-gobject/closure" require "ffi-gobject/object" require "ffi-gobject/object_class" require "ffi-gobject/param_spec" require "ffi-gobject/ruby_closure" require "gir_ffi/signal_not_found_error" # Module representing GLib's GObject namespace. module GObject def self.type_from_instance_pointer(inst_ptr) return nil if inst_ptr.null? klsptr = inst_ptr.get_pointer 0 klsptr.get_gtype 0 end def self.type_from_instance(instance) type_from_instance_pointer instance.to_ptr end def self.type_name_from_instance(instance) type_name type_from_instance instance end def self.signal_lookup_from_instance(signal, object) signal_lookup signal, type_from_instance(object) end def self.signal_emit(object, detailed_signal, *args) signal, detail = detailed_signal.split("::") signal_id = signal_lookup_from_instance signal, object detail_quark = GLib.quark_from_string(detail) sig_info = object.class.find_signal signal argument_gvalues = sig_info.arguments_to_gvalues object, args return_gvalue = sig_info.gvalue_for_return_value signal_emitv argument_gvalues, signal_id, detail_quark, return_gvalue end def self.signal_connect(object, detailed_signal, data = nil, after = false, &block) block or raise ArgumentError, "Block needed" signal_name, = detailed_signal.split("::") sig_info = object.class.find_signal signal_name closure = sig_info.wrap_in_closure do |*args| yield(*args << data) end signal_connect_closure object, detailed_signal, closure, after end def self.signal_connect_after(object, detailed_signal, data = nil, &block) signal_connect object, detailed_signal, data, true, &block end load_class :Callback load_class :ClosureNotify load_class :ConnectFlags load_class :ClosureMarshal load_class :ParamFlags # Attach some needed functions to the GObject Lib, which was set up in # `gir_ffi-base/gobject/lib.rb`. Lib.class_eval do attach_function :g_object_ref_sink, [:pointer], :pointer attach_function :g_object_ref, [:pointer], :pointer attach_function :g_object_unref, [:pointer], :pointer attach_function :g_value_copy, [:pointer, :pointer], :void attach_function :g_value_unset, [:pointer], :pointer attach_function :g_signal_connect_data, [:pointer, :string, Callback, :pointer, ClosureNotify, ConnectFlags], :ulong attach_function :g_closure_ref, [:pointer], :pointer attach_function :g_closure_sink, [:pointer], :pointer attach_function :g_closure_set_marshal, [:pointer, ClosureMarshal], :void attach_function :g_param_spec_ref, [:pointer], :pointer attach_function :g_param_spec_sink, [:pointer], :pointer end end gir_ffi-0.16.1/lib/gir_ffi.rb0000644000004100000410000000014014524576001015733 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/core" require "ffi-glib" require "ffi-gobject" gir_ffi-0.16.1/lib/ffi-gobject/0000755000004100000410000000000014524576001016165 5ustar www-datawww-datagir_ffi-0.16.1/lib/ffi-gobject/value.rb0000644000004100000410000001221714524576001017631 0ustar www-datawww-data# frozen_string_literal: true GObject.load_class :Value module GObject # Overrides for GValue, GObject's generic value container structure. class Value setup_instance_method! :init METHOD_MAP = { TYPE_INVALID => [:get_none, :set_none], # TYPE_NONE is skipped TYPE_INTERFACE => [:get_object, :set_instance_enhanced], TYPE_CHAR => [:get_schar, :set_schar], TYPE_UCHAR => [:get_uchar, :set_uchar], TYPE_BOOLEAN => [:get_boolean, :set_boolean], TYPE_INT => [:get_int, :set_int], TYPE_UINT => [:get_uint, :set_uint], TYPE_LONG => [:get_long, :set_long], TYPE_ULONG => [:get_ulong, :set_ulong], TYPE_INT64 => [:get_int64, :set_int64], TYPE_UINT64 => [:get_uint64, :set_uint64], TYPE_ENUM => [:get_enum_enhanced, :set_enum_enhanced], TYPE_FLAGS => [:get_flags_enhanced, :set_flags_enhanced], TYPE_FLOAT => [:get_float, :set_float], TYPE_DOUBLE => [:get_double, :set_double], TYPE_STRING => [:get_string, :set_string], TYPE_POINTER => [:get_pointer, :set_pointer], TYPE_BOXED => [:get_boxed, :set_boxed], TYPE_PARAM => [:get_param, :set_param], TYPE_OBJECT => [:get_object, :set_instance_enhanced], TYPE_GTYPE => [:get_gtype, :set_gtype], TYPE_VARIANT => [:get_variant, :set_variant] }.freeze # TODO: Give more generic name def self.wrap_ruby_value(val) new.tap { |gv| gv.__send__ :set_ruby_value, val } end def self.from(val) case val when self val else wrap_ruby_value val end end def self.for_gtype(gtype) new.tap do |it| it.init gtype end end # TODO: Combine with wrap_ruby_value def self.wrap_instance(instance) new.tap do |it| it.init GObject.type_from_instance instance it.set_instance instance end end def self.copy_value_to_pointer(value, pointer, offset = 0) target = wrap(pointer + offset) target.init(value.current_gtype) Lib.g_value_copy value, target unless value.uninitialized? end CLASS_TO_GTYPE_MAP = { NilClass => TYPE_INVALID, TrueClass => TYPE_BOOLEAN, FalseClass => TYPE_BOOLEAN, Integer => TYPE_INT, String => TYPE_STRING }.freeze # Overrides for existing Value methods module Overrides def set_value(val) send set_method, val end alias_method :value=, :set_value def current_gtype struct[:g_type] end def current_fundamental_type GObject.type_fundamental current_gtype end def current_gtype_name GObject.type_name current_gtype end def get_value value = get_value_plain if current_fundamental_type == TYPE_BOXED wrap_boxed value else value end end def get_value_plain send get_method end def uninitialized? current_gtype == TYPE_INVALID end def init(type) Lib.g_value_init self, type unless [TYPE_NONE, TYPE_INVALID].include? type self end private def set_ruby_value(val) init_for_ruby_value val if uninitialized? set_value val end def init_for_ruby_value(val) return init val.class.gtype if val.class.respond_to? :gtype CLASS_TO_GTYPE_MAP.each do |klass, type| return init type if val.is_a? klass end raise "Can't handle #{val.class}" end def set_none(_val); end def get_none; end def set_instance_enhanced(val) check_type_compatibility val if val set_instance val end def set_enum_enhanced(val) val = current_gtype_class.to_native(val, nil) set_enum val end def get_enum_enhanced current_gtype_class.wrap(get_enum) end def set_flags_enhanced(val) val = current_gtype_class.to_native(val, nil) set_flags val end def get_flags_enhanced current_gtype_class.wrap(get_flags) end def current_gtype_class GirFFI::Builder.build_by_gtype(current_gtype) end def check_type_compatibility(val) if GObject::Value.type_compatible(GObject.type_from_instance(val), current_gtype) return end raise ArgumentError, "#{val.class} is incompatible with #{current_gtype_name}" end def wrap_boxed(boxed) case current_gtype when TYPE_STRV GLib::Strv.wrap boxed when TYPE_HASH_TABLE GLib::HashTable.wrap [:gpointer, :gpointer], boxed when TYPE_ARRAY GLib::Array.wrap nil, boxed else current_gtype_class.wrap(boxed) unless boxed.null? end end def get_method method_map_entry.first end def set_method method_map_entry.last end def method_map_entry METHOD_MAP[current_gtype] || METHOD_MAP[current_fundamental_type] || raise("No method map entry for '#{current_gtype_name}'") end end prepend Overrides end end gir_ffi-0.16.1/lib/ffi-gobject/ruby_closure.rb0000644000004100000410000000267614524576001021242 0ustar www-datawww-data# frozen_string_literal: true require "ffi-gobject/closure" module GObject # Encapsulates Ruby blocks as GObject Closures. class RubyClosure < Closure # @api private BLOCK_STORE = {} # Extend the standard +GObject::Closure+ layout with a field block_id to store # the object_id of the associated block. # # @api private class Struct < GirFFI::Struct layout :parent, Closure::Struct, 0, :block_id, :int64 end def initialize(&block) block or raise ArgumentError, "Block needed" initialize_simple(self.class::Struct.size, nil) self.block = block set_marshal proc { |*args| self.class.marshaller(*args) } end # @api private def self.marshaller(closure, return_value, param_values, _invocation_hint, _marshal_data) # TODO: Improve by registering RubyClosure as a GObject type rclosure = wrap(closure.to_ptr) param_values ||= [] args = param_values.map(&:get_value) result = rclosure.invoke_block(*args) return_value&.set_value(result) end # @api private # TODO: Re-structure so invoke_block can become a private method def invoke_block(*args) block.call(*args) end private # @api private def block=(block) id = block.object_id BLOCK_STORE[id] = block struct[:block_id] = id end def block BLOCK_STORE[struct[:block_id]] end end end gir_ffi-0.16.1/lib/ffi-gobject/param_spec.rb0000644000004100000410000000107114524576001020623 0ustar www-datawww-data# frozen_string_literal: true GObject.load_class :ParamSpec module GObject # Overrides for GParamSpec, GObject's base class for parameter specifications. class ParamSpec VALUE_TYPE_OFFSET = Struct.offset_of :value_type FLAGS_OFFSET = Struct.offset_of :flags def ref Lib.g_param_spec_ref self self end def accessor_name get_name.tr("-", "_") end def value_type to_ptr.get_gtype(VALUE_TYPE_OFFSET) end def flags GObject::ParamFlags.get_value_from_pointer(to_ptr, FLAGS_OFFSET) end end end gir_ffi-0.16.1/lib/ffi-gobject/initially_unowned.rb0000644000004100000410000000072114524576001022247 0ustar www-datawww-data# frozen_string_literal: true GObject.load_class :InitiallyUnowned module GObject # Overrides for GInitiallyUnowned, GObject's base class for objects that # start with a floating reference. class InitiallyUnowned # Initializing method used in constructors. For InitiallyUnowned and # descendants, this needs to sink the object's floating reference. def store_pointer(ptr) super ::GObject::Lib.g_object_ref_sink ptr end end end gir_ffi-0.16.1/lib/ffi-gobject/object_class.rb0000644000004100000410000000033614524576001021147 0ustar www-datawww-data# frozen_string_literal: true GObject::Object.class_struct module GObject # Overrides for GObjectClass, the class struct for GObject::Object class ObjectClass def gtype to_ptr.get_gtype 0 end end end gir_ffi-0.16.1/lib/ffi-gobject/object.rb0000644000004100000410000001213514524576001017762 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/property_not_found_error" GObject.load_class :Object module GObject # Overrides for GObject, GObject's generic base class. class Object GObject::Lib.attach_function(:g_object_new_with_properties, [:size_t, :uint32, :pointer, :pointer], :pointer) def self.new_with_properties(*args, &block) obj = allocate obj.__send__ :initialize_with_properties, *args, &block obj end # Starting with GLib 2.54.0, use g_object_new_with_properties, which # takes an array of names and an array of values. def initialize_with_properties(properties = {}) names, gvalues = names_and_gvalues_for_properties(properties) n_properties = names.length names_arr = GirFFI::SizedArray.from(:utf8, -1, names) gvalues_arr = GirFFI::SizedArray.from(GObject::Value, -1, gvalues) ptr = GObject::Lib.g_object_new_with_properties(self.class.gtype, n_properties, names_arr, gvalues_arr) store_pointer ptr end alias_method :old_initialze, :initialize alias_method :initialize, :initialize_with_properties remove_method :old_initialze def self.new(*args, &block) obj = allocate obj.__send__ :initialize, *args, &block obj end alias_method :base_initialize, :initialize private :base_initialize remove_method :ref def ref Lib.g_object_ref self self end def self.make_finalizer(ptr) proc { finalize ptr } end class << self protected def finalize(ptr) rc = GObject::Object::Struct.new(ptr)[:ref_count] if rc == 0 warn "not unreffing #{name}:#{ptr} (#{rc})" else GObject::Lib.g_object_unref ptr end end end def signal_connect(event, data = nil, &block) GObject.signal_connect(self, event, data, &block) end def signal_connect_after(event, data = nil, &block) GObject.signal_connect_after(self, event, data, &block) end setup_instance_method! "get_property" setup_instance_method! "set_property" setup_instance_method! "is_floating" alias_method :floating?, :is_floating private def store_pointer(ptr) super make_finalizer end def make_finalizer ObjectSpace.define_finalizer self, self.class.make_finalizer(struct.to_ptr) end def names_and_gvalues_for_properties(properties) return [], [] unless properties.any? properties.map do |name, value| name = name.to_s gvalue = gvalue_for_property(name) gvalue.set_value value [name, gvalue] end.transpose end def gvalue_for_property(property_name) gtype = property_gtype property_name GObject::Value.for_gtype gtype end def property_gtype(property_name) property_param_spec(property_name).value_type end def property_param_spec(property_name) class_struct.find_property property_name or raise GirFFI::PropertyNotFoundError.new(property_name, self.class) end # Overrides for GObject, GObject's generic base class. module Overrides def get_property(property_name) gvalue = gvalue_for_property property_name super property_name, gvalue value = gvalue.get_value type_info = get_property_type property_name value = property_value_post_conversion(value, type_info) if type_info value end def set_property(property_name, value) type_info = get_property_type property_name value = property_value_pre_conversion(value, type_info) if type_info gvalue = gvalue_for_property(property_name) gvalue.set_value value super property_name, gvalue end private def get_property_type(property_name) self.class.find_property(property_name)&.property_type end # TODO: Move to ITypeInfo and unify with ArgHelper.cast_from_pointer def property_value_post_conversion(val, type_info) case type_info.flattened_tag when :ghash GLib::HashTable.from type_info.element_type, val when :glist GLib::List.from type_info.element_type, val when :callback GirFFI::Builder.build_class(type_info.interface).wrap val else val end end # TODO: Move to ITypeInfo and unify with ArgHelper.cast_from_pointer def property_value_pre_conversion(val, type_info) case type_info.flattened_tag when :ghash GLib::HashTable.from type_info.element_type, val when :glist GLib::List.from type_info.element_type, val when :strv GLib::Strv.from val when :byte_array GLib::ByteArray.from val when :callback GirFFI::Builder.build_class(type_info.interface).from val else val end end end prepend Overrides end end gir_ffi-0.16.1/lib/ffi-gobject/closure.rb0000644000004100000410000000261214524576001020167 0ustar www-datawww-data# frozen_string_literal: true GObject.load_class :Closure module GObject # Overrides for GClosure, GObject's base class for closure objects. # # To create Closure objects wrapping Ruby code, use {RubyClosure}. class Closure setup_method! :new_simple setup_instance_method! :invoke remove_method :invoke # @override # # @param [Proc] marshal The marshaller to use for this closure object def set_marshal(marshal) callback = ClosureMarshal.from marshal Lib.g_closure_set_marshal self, callback end # @override # # This override of invoke ensures the return value location can be passed # in as the first argument, which is needed to ensure the GValue is # initialized with the proper type. # # @param [GObject::Value] return_value The GValue to store the return # value, or nil if no return value is expected. # @param [Array] param_values the closure parameters. def invoke(return_value, param_values) rval = Value.from(return_value) n_params = param_values.length params = GirFFI::SizedArray.from(Value, -1, param_values) Lib.g_closure_invoke self, rval, n_params, params, nil rval.get_value end def store_pointer(ptr) # NOTE: Call C functions directly to avoid extra argument conversion Lib.g_closure_ref ptr Lib.g_closure_sink ptr super end end end gir_ffi-0.16.1/lib/ffi-glib/0000755000004100000410000000000014524576001015465 5ustar www-datawww-datagir_ffi-0.16.1/lib/ffi-glib/list.rb0000644000004100000410000000100014524576001016754 0ustar www-datawww-data# frozen_string_literal: true require "ffi-glib/list_methods" GLib.load_class :List module GLib # Overrides for GList, GLib's doubly linked list implementation. class List include ListMethods def append(data) store_pointer Lib.g_list_append(self, element_ptr_for(data)) self end def prepend(data) store_pointer Lib.g_list_prepend(self, element_ptr_for(data)) self end def reverse store_pointer Lib.g_list_reverse(self) self end end end gir_ffi-0.16.1/lib/ffi-glib/container_class_methods.rb0000644000004100000410000000152314524576001022705 0ustar www-datawww-data# frozen_string_literal: true module GLib # Common methods for container classes: Array, PtrArray, List, SList and # HashTable. module ContainerClassMethods def wrap(typespec, ptr) # HACK: wrap and from are almost the same! ptr = case ptr when nil nil when FFI::Pointer ptr when self, GirFFI::BoxedBase ptr.to_ptr end super(ptr).tap do |container| container&.reset_typespec typespec end end def from(typespec = :void, obj) case obj when nil nil when FFI::Pointer wrap typespec, obj when self obj.reset_typespec typespec when GirFFI::BoxedBase wrap typespec, obj.to_ptr else from_enumerable typespec, obj end end end end gir_ffi-0.16.1/lib/ffi-glib/destroy_notify.rb0000644000004100000410000000070314524576001021073 0ustar www-datawww-data# frozen_string_literal: true GLib.load_class :DestroyNotify module GLib # Overrides for DestroyNotify, the callback type for destroy notifications. # It should not be necessary to create objects of this class from Ruby # directly. class DestroyNotify def self.default @default ||= from proc { |user_data| callback = GirFFI::ArgHelper::OBJECT_STORE.fetch(user_data) drop_callback callback } end end end gir_ffi-0.16.1/lib/ffi-glib/ptr_array.rb0000644000004100000410000000373014524576001020020 0ustar www-datawww-data# frozen_string_literal: true require "ffi-glib/container_class_methods" require "gir_ffi/array_element_convertor" GLib.load_class :PtrArray module GLib # Overrides for GPtrArray, GLib's automatically growing array of # pointers. class PtrArray include Enumerable extend ContainerClassMethods attr_reader :element_type POINTER_SIZE = FFI.type_size(:pointer) class << self # Remove stub generated by builder. remove_method :add if method_defined? :add end def initialize(type) @element_type = type store_pointer Lib.g_ptr_array_new end def self.from_enumerable(type, arr) new(type).tap { |it| it.add_array arr } end def self.add(array, data) array.add data end def reset_typespec(typespec) @element_type = typespec self end def add(data) ptr = GirFFI::InPointer.from element_type, data Lib.g_ptr_array_add self, ptr end def add_array(ary) ary.each { |item| add item } end # Re-implementation of the g_ptrarray_index macro def index(idx) item_ptr = item_pointer(idx) convertor = GirFFI::ArrayElementConvertor.new convert_element_type, item_ptr convertor.to_ruby_value end def each length.times do |idx| yield index(idx) end end def length struct[:len] end def ==(other) to_a == other.to_a end private def item_pointer(idx) check_bounds(idx) data_ptr + idx * element_size end def check_bounds(idx) unless (0...length).cover? idx raise IndexError, "Index #{idx} outside of bounds 0..#{length - 1}" end end def convert_element_type case element_type when :utf8 :utf8 when GirFFI::ObjectBase element_type else [:pointer, element_type] end end def element_size POINTER_SIZE end def data_ptr struct[:pdata] end end end gir_ffi-0.16.1/lib/ffi-glib/array.rb0000644000004100000410000000453114524576001017133 0ustar www-datawww-data# frozen_string_literal: true require "ffi-glib/container_class_methods" require "gir_ffi/array_element_convertor" GLib.load_class :Array module GLib # Overrides for GArray, GLib's automatically growing array. It should not # be necessary to create objects of this class from Ruby directly. class Array include Enumerable extend ContainerClassMethods attr_reader :element_type def initialize(type) @element_type = type ptr = Lib.g_array_new(0, 0, calculated_element_size) store_pointer(ptr) end # @api private def self.from_enumerable(elmtype, arr) new(elmtype).tap { |it| it.append_vals arr } end # @api private def self.calculated_element_size(type) ffi_type = GirFFI::TypeMap.type_specification_to_ffi_type(type) FFI.type_size(ffi_type) end # @override def append_vals(ary) bytes = GirFFI::InPointer.from_array element_type, ary Lib.g_array_append_vals(self, bytes, ary.length) self end def each length.times do |idx| yield index(idx) end end def length struct[:len] end def get_element_size Lib.g_array_get_element_size self end alias_method :element_size, :get_element_size def ==(other) to_a == other.to_a end # @api private def reset_typespec(typespec = nil) if typespec @element_type = typespec check_element_size_match else @element_type = guess_element_type end self end # Re-implementation of the g_array_index macro def index(idx) unless (0...length).cover? idx raise IndexError, "Index #{idx} outside of bounds 0..#{length - 1}" end item_ptr = data_ptr + idx * element_size convertor = GirFFI::ArrayElementConvertor.new element_type, item_ptr convertor.to_ruby_value end private def data_ptr struct[:data] end def calculated_element_size self.class.calculated_element_size element_type end def check_element_size_match return if calculated_element_size == get_element_size warn "WARNING: Element sizes do not match" end def guess_element_type case get_element_size when 1 then :uint8 when 2 then :uint16 when 4 then :uint32 when 8 then :uint64 end end end end gir_ffi-0.16.1/lib/ffi-glib/byte_array.rb0000644000004100000410000000100314524576001020145 0ustar www-datawww-data# frozen_string_literal: true GLib.load_class :ByteArray module GLib # Overrides for GByteArray, GLib's automatically growing array of bytes. class ByteArray def to_string data.read_string len end def append(data) bytes = GirFFI::InPointer.from_utf8 data len = data.bytesize Lib.g_byte_array_append(to_ptr, bytes, len) self end def self.from(data) case data when self data else new.append(data) end end end end gir_ffi-0.16.1/lib/ffi-glib/main_loop.rb0000644000004100000410000000264714524576001020000 0ustar www-datawww-data# frozen_string_literal: true require "singleton" GLib.load_class :MainLoop module GLib # Overrides for GMainLoop, GLib's event loop class MainLoop # Class encapsulationg logic for running an idle handler to make Ruby code # run during GLib's event loop. class ThreadEnabler include Singleton FRAMERATE = 25 DEFAULT_TIMEOUT = 1000 / FRAMERATE def initialize(timeout = DEFAULT_TIMEOUT) @timeout = timeout end def setup_idle_handler @handler_id ||= GLib.timeout_add(GLib::PRIORITY_DEFAULT, @timeout, &handler_proc) end private def handler_proc proc do ::Thread.pass true end end end EXCEPTIONS = [] RUNNING_LOOPS = [] setup_instance_method! :run def run_with_thread_enabler ThreadEnabler.instance.setup_idle_handler RUNNING_LOOPS << self result = run_without_thread_enabler exception = EXCEPTIONS.shift RUNNING_LOOPS.pop raise exception if exception result end def self.handle_exception(exception) current_loop = RUNNING_LOOPS.last raise exception unless current_loop EXCEPTIONS << exception current_loop.quit end alias_method :run_without_thread_enabler, :run alias_method :run, :run_with_thread_enabler end end Signal.trap "INT" do GLib::MainLoop.handle_exception(Interrupt.new) end gir_ffi-0.16.1/lib/ffi-glib/error.rb0000644000004100000410000000057014524576001017145 0ustar www-datawww-data# frozen_string_literal: true GLib.load_class :Error module GLib # Overrides for GError, used by GLib for handling non-fatal errors. class Error GIR_FFI_DOMAIN = GLib.quark_from_string("gir_ffi") def self.from_exception(exception) new_literal GIR_FFI_DOMAIN, 0, exception.message end def self.from(obj) from_exception obj end end end gir_ffi-0.16.1/lib/ffi-glib/hash_table.rb0000644000004100000410000000374014524576001020110 0ustar www-datawww-data# frozen_string_literal: true require "ffi-glib/container_class_methods" GLib.load_class :HashTable module GLib # Overrides for GHashTable, GLib's hash table implementation. class HashTable include Enumerable extend ContainerClassMethods attr_reader :key_type, :value_type def initialize(key_type, value_type) @key_type = key_type @value_type = value_type store_pointer Lib.g_hash_table_new( hash_function_for_key_type, equality_function_for_key_type) end # @api private def self.from_enumerable(typespec, hash) ghash = new(*typespec) hash.each do |key, val| ghash.insert key, val end ghash end def each prc = proc do |keyptr, valptr, _userdata| key = GirFFI::ArgHelper.cast_from_pointer key_type, keyptr val = GirFFI::ArgHelper.cast_from_pointer value_type, valptr yield key, val end callback = GLib::HFunc.from prc ::GLib::Lib.g_hash_table_foreach to_ptr, callback, nil end def to_hash to_a.to_h end # @override def insert(key, value) keyptr = GirFFI::InPointer.from key_type, key valptr = GirFFI::InPointer.from value_type, value ::GLib::Lib.g_hash_table_insert to_ptr, keyptr, valptr end # @api private def reset_typespec(typespec) @key_type, @value_type = *typespec self end private def hash_function_for_key_type case @key_type when :utf8 FFI::Function.new(:uint, [:pointer], find_support_function("g_str_hash")) end end def equality_function_for_key_type case @key_type when :utf8 FFI::Function.new(:int, [:pointer, :pointer], find_support_function("g_str_equal")) end end def find_support_function(name) lib = ::GLib::Lib.ffi_libraries.first lib.find_function(name) end end end gir_ffi-0.16.1/lib/ffi-glib/bytes.rb0000644000004100000410000000112014524576001017132 0ustar www-datawww-data# frozen_string_literal: true GLib.load_class :Bytes module GLib # Overrides for GBytes, GLib's immutable array of bytes. class Bytes include Enumerable def each(&block) data.each(&block) end def self.from(obj) case obj when self obj when FFI::Pointer wrap obj else new obj end end def initialize(arr) data = GirFFI::SizedArray.from :guint8, arr.size, arr store_pointer Lib.g_bytes_new data.to_ptr, data.size end private def data @data ||= get_data end end end gir_ffi-0.16.1/lib/ffi-glib/list_methods.rb0000644000004100000410000000316014524576001020510 0ustar www-datawww-data# frozen_string_literal: true require "ffi-glib/container_class_methods" module GLib # Common methods for List and SList. module ListMethods include Enumerable attr_reader :element_type def self.included(base) # Override default field accessors. replace_method base, :next, :tail replace_method base, :data, :head base.extend ContainerClassMethods base.extend ClassMethods end def self.replace_method(base, old, new) base.class_eval do remove_method old alias_method old, new end end def initialize(type) store_pointer(FFI::Pointer.new(0)) @element_type = type end def each reset_iterator while (elem = next_element) yield elem end end def tail return nil if struct.null? self.class.wrap(element_type, struct[:next]) end def head return nil if struct.null? GirFFI::ArgHelper.cast_from_pointer(element_type, struct[:data]) end def reset_typespec(typespec) @element_type = typespec self end def ==(other) to_a == other.to_a end private def reset_iterator @current = self end def next_element return unless @current element = @current.head @current = @current.tail element end def element_ptr_for(data) GirFFI::InPointer.from(element_type, data) end # Common class methods for List and SList module ClassMethods def from_enumerable(type, arr) arr.reduce(new(type)) { |lst, val| lst.prepend val }.reverse end end end end gir_ffi-0.16.1/lib/ffi-glib/variant.rb0000644000004100000410000000145214524576001017460 0ustar www-datawww-data# frozen_string_literal: true GLib.load_class :Variant module GLib # Overrides for GVariant, GLib's variant data type. class Variant setup_instance_method! "get_string" def get_string_with_override get_string_without_override.first end alias_method :get_string_without_override, :get_string alias_method :get_string, :get_string_with_override # Initializing method used in constructors. For Variant the constructing # functions all return floating references, so this is need to take full # ownership. # # Also see the documentation for g_variant_ref_sink. def store_pointer(ptr) Lib.g_variant_ref_sink ptr super end # For variants, wrap_copy does not do any copying. def self.wrap_copy(val) wrap(val) end end end gir_ffi-0.16.1/lib/ffi-glib/strv.rb0000644000004100000410000000122014524576001017003 0ustar www-datawww-data# frozen_string_literal: true module GLib # Represents a null-terminated array of strings. GLib uses this construction, # but does not provide any actual functions for this class. # # The implementation is mainly inherited from GObjectIntrospection::Strv. class Strv < GObjectIntrospection::Strv def ==(other) to_a == other.to_a end def self.from(obj) case obj when nil nil when FFI::Pointer wrap obj when self obj else from_enumerable obj end end def self.from_enumerable(enum) wrap GirFFI::InPointer.from_array :utf8, enum end end end gir_ffi-0.16.1/lib/ffi-glib/s_list.rb0000644000004100000410000000100614524576001017304 0ustar www-datawww-data# frozen_string_literal: true require "ffi-glib/list_methods" GLib.load_class :SList module GLib # Overrides for GSList, GLib's singly-linked list implementation. class SList include ListMethods def append(data) store_pointer Lib.g_slist_append(self, element_ptr_for(data)) self end def prepend(data) store_pointer Lib.g_slist_prepend(self, element_ptr_for(data)) self end def reverse store_pointer Lib.g_slist_reverse(self) self end end end gir_ffi-0.16.1/lib/gir_ffi-base.rb0000644000004100000410000000041714524576001016652 0ustar www-datawww-data# frozen_string_literal: true # # This section contains code that is needed by GirFFI, but belongs in modules # that can only be created fully once GirFFI is fully loaded. # Some base GObject functions and constants are needed by GirFFI. require "gir_ffi-base/gobject" gir_ffi-0.16.1/lib/ffi-gobject_introspection.rb0000644000004100000410000000337414524576001021501 0ustar www-datawww-data# frozen_string_literal: true require "ffi-gobject_introspection/gobject_type_init" GObjectIntrospection::GObjectTypeInit.type_init require "ffi-gobject_introspection/i_base_info" require "ffi-gobject_introspection/i_callable_info" require "ffi-gobject_introspection/i_callback_info" require "ffi-gobject_introspection/i_function_info" require "ffi-gobject_introspection/i_constant_info" require "ffi-gobject_introspection/i_field_info" require "ffi-gobject_introspection/i_registered_type_info" require "ffi-gobject_introspection/i_interface_info" require "ffi-gobject_introspection/i_property_info" require "ffi-gobject_introspection/i_vfunc_info" require "ffi-gobject_introspection/i_signal_info" require "ffi-gobject_introspection/i_object_info" require "ffi-gobject_introspection/i_struct_info" require "ffi-gobject_introspection/i_value_info" require "ffi-gobject_introspection/i_union_info" require "ffi-gobject_introspection/i_enum_info" require "ffi-gobject_introspection/i_flags_info" require "ffi-gobject_introspection/i_unresolved_info" module GObjectIntrospection # Map info type to class. Default is IBaseInfo. TYPEMAP = { invalid: IBaseInfo, function: IFunctionInfo, callback: ICallbackInfo, struct: IStructInfo, # TODO: There's no GIBoxedInfo, so what does :boxed mean? boxed: IBaseInfo, enum: IEnumInfo, flags: IFlagsInfo, object: IObjectInfo, interface: IInterfaceInfo, constant: IConstantInfo, invalid_was_error_domain: IBaseInfo, union: IUnionInfo, value: IValueInfo, signal: ISignalInfo, vfunc: IVFuncInfo, property: IPropertyInfo, field: IFieldInfo, arg: IArgInfo, type: ITypeInfo, unresolved: IUnresolvedInfo }.freeze end require "ffi-gobject_introspection/i_repository" gir_ffi-0.16.1/lib/ffi-gobject_introspection/0000755000004100000410000000000014524576001021145 5ustar www-datawww-datagir_ffi-0.16.1/lib/ffi-gobject_introspection/i_repository.rb0000644000004100000410000000453214524576001024225 0ustar www-datawww-data# frozen_string_literal: true require "singleton" require "ffi-gobject_introspection/lib" require "ffi-gobject_introspection/strv" require "ffi-gobject_introspection/g_error" module GObjectIntrospection # The Gobject Introspection Repository. This class is the point of # access to the introspection typelibs. # This class wraps the GIRepository struct. class IRepository def initialize @pointer = Lib.g_irepository_get_default end def to_ptr @pointer end include Singleton def self.default instance end def self.prepend_search_path(path) Lib.g_irepository_prepend_search_path path end def self.type_tag_to_string(type) Lib.g_type_tag_to_string type end def require(namespace, version = nil, flags = 0) errpp = FFI::MemoryPointer.new(:pointer).write_pointer nil Lib.g_irepository_require self, namespace, version, flags, errpp errp = errpp.read_pointer raise GError.new(errp).message unless errp.null? end def n_infos(namespace) Lib.g_irepository_get_n_infos self, namespace end def info(namespace, index) wrap_info Lib.g_irepository_get_info(self, namespace, index) end # Utility method def infos(namespace) (0..(n_infos(namespace) - 1)).map do |idx| info namespace, idx end end def find_by_name(namespace, name) @name_cache ||= {} @name_cache[[namespace, name]] ||= wrap_info Lib.g_irepository_find_by_name(self, namespace, name) end def find_by_gtype(gtype) raise ArgumentError, "Type #{gtype} is not a valid type" if gtype == 0 @gtype_cache ||= {} @gtype_cache[gtype] ||= wrap_info Lib.g_irepository_find_by_gtype(self, gtype) end def dependencies(namespace) strv_p = Lib.g_irepository_get_dependencies(self, namespace) strv = Strv.new strv_p strv.to_a end def shared_library(namespace) Lib.g_irepository_get_shared_library self, namespace end def version(namespace) Lib.g_irepository_get_version self, namespace end def self.wrap_ibaseinfo_pointer(ptr) return nil if ptr.null? type = Lib.g_base_info_get_type ptr klass = TYPEMAP[type] klass.wrap ptr end private def wrap_info(ptr) self.class.wrap_ibaseinfo_pointer ptr end end end gir_ffi-0.16.1/lib/ffi-gobject_introspection/i_interface_info.rb0000644000004100000410000000362314524576001024761 0ustar www-datawww-data# frozen_string_literal: true module GObjectIntrospection # Wraps a IInterfaceInfo struct. # Represents an interface. class IInterfaceInfo < IRegisteredTypeInfo def n_prerequisites Lib.g_interface_info_get_n_prerequisites self end def prerequisite(index) IBaseInfo.wrap Lib.g_interface_info_get_prerequisite(self, index) end ## build_array_method :prerequisites def n_properties Lib.g_interface_info_get_n_properties self end def property(index) IPropertyInfo.wrap Lib.g_interface_info_get_property(self, index) end ## build_array_method :properties, :property build_finder_method :find_property, :n_properties def get_n_methods Lib.g_interface_info_get_n_methods self end def get_method(index) IFunctionInfo.wrap Lib.g_interface_info_get_method(self, index) end ## build_array_method :get_methods def find_method(name) IFunctionInfo.wrap Lib.g_interface_info_find_method(self, name.to_s) end def n_signals Lib.g_interface_info_get_n_signals self end def signal(index) ISignalInfo.wrap Lib.g_interface_info_get_signal(self, index) end ## build_array_method :signals build_finder_method :find_signal def n_vfuncs Lib.g_interface_info_get_n_vfuncs self end def vfunc(index) IVFuncInfo.wrap Lib.g_interface_info_get_vfunc(self, index) end ## build_array_method :vfuncs def find_vfunc(name) IVFuncInfo.wrap Lib.g_interface_info_find_vfunc(self, name) end def n_constants Lib.g_interface_info_get_n_constants self end def constant(index) IConstantInfo.wrap Lib.g_interface_info_get_constant(self, index) end ## build_array_method :constants def iface_struct @iface_struct ||= IStructInfo.wrap Lib.g_interface_info_get_iface_struct(self) end end end gir_ffi-0.16.1/lib/ffi-gobject_introspection/i_field_info.rb0000644000004100000410000000107214524576001024100 0ustar www-datawww-data# frozen_string_literal: true module GObjectIntrospection # Wraps a GIFieldInfo struct. # Represents a field of an IStructInfo or an IUnionInfo. class IFieldInfo < IBaseInfo def flags Lib.g_field_info_get_flags self end def size Lib.g_field_info_get_size self end def offset Lib.g_field_info_get_offset self end def field_type @field_type ||= ITypeInfo.wrap Lib.g_field_info_get_type(self) end def readable? flags[:readable] end def writable? flags[:writable] end end end gir_ffi-0.16.1/lib/ffi-gobject_introspection/i_base_info.rb0000644000004100000410000001053114524576001023727 0ustar www-datawww-data# frozen_string_literal: true module GObjectIntrospection # Wraps GIBaseInfo struct, the base \type for all info types. # Decendant types will be implemented as needed. class IBaseInfo def initialize(ptr) raise ArgumentError, "ptr must not be null" if ptr.null? ObjectSpace.define_finalizer self, self.class.make_finalizer(ptr) @pointer = ptr end attr_reader :pointer def self.make_finalizer(ptr) proc { finalize ptr } end class << self protected def finalize(ptr) Lib.g_base_info_unref ptr end end def to_ptr @pointer end # This is a helper method to construct a method returning an array, out # of the methods returning their number and the individual elements. # # For example, given the methods +n_foos+ and +foo+(+i+), this method # will create an additional method +foos+ returning all foos. # # Provide the second parameter if the plural is not trivially # constructed by adding +s+ to the singular. # # Examples: # # build_array_method :fields # build_array_method :properties, :property # build_array_method :get_methods # def self.build_array_method(method, single = nil) method = method.to_s cache_ivar = "@#{method}_cache" single ||= method[0..-2] count = method.sub(/^(get_)?/, "\\1n_") class_eval <<-CODE, __FILE__, __LINE__ + 1 def #{method} # def fields #{cache_ivar} ||= # @fields_cache ||= (0..(#{count} - 1)).map do |i| # (0..(n_fields - 1)).map do |i| #{single} i # field i end # end end # end CODE end # This is a helper method to construct a method for finding an element, out # of the methods returning their number and the individual elements. # # For example, given the methods +n_foos+ and +foo+(+i+), this method will # create an additional method +find_foo+ returning the foo with the # matching name. # # Optionally provide counter and fetcher methods if they cannot be # trivially derived from the finder method. # # Examples: # # build_finder_method :find_field # build_finder_method :find_property, :n_properties # build_finder_method :find_method, :get_n_methods, :get_method # def self.build_finder_method(method, counter = nil, fetcher = nil) method = method.to_s cache_ivar = "@#{method}_cache" single = method.sub(/^find_/, "") counter ||= "n_#{single}s" fetcher ||= single class_eval <<-CODE, __FILE__, __LINE__ + 1 def #{method}(name) # def find_field(name) #{cache_ivar} ||= begin # @find_field_cache ||= begin hash = {} # hash = {} #{counter}.times do |i| # n_fields.times do |i| it = #{fetcher}(i) # it = field(i) hash[it.name] = it # hash[it.name] = it end # end hash # hash end # end name = name.to_s # name = name.to_s #{cache_ivar}[name] # @find_field_cache[name] end # end CODE end def name @name ||= Lib.g_base_info_get_name self end def info_type @info_type ||= Lib.g_base_info_get_type self end def namespace @namespace ||= Lib.g_base_info_get_namespace self end def safe_namespace namespace.sub(/^[a-z]/, &:upcase) end def container @container ||= begin ptr = Lib.g_base_info_get_container self unless ptr.null? Lib.g_base_info_ref ptr IRepository.wrap_ibaseinfo_pointer ptr end end end def deprecated? Lib.g_base_info_is_deprecated self end def attribute(name) Lib.g_base_info_get_attribute self, name end def self.wrap(ptr) new ptr unless ptr.null? end def ==(other) other.is_a?(IBaseInfo) && Lib.g_base_info_equal(self, other) end end end gir_ffi-0.16.1/lib/ffi-gobject_introspection/i_flags_info.rb0000644000004100000410000000024114524576001024106 0ustar www-datawww-data# frozen_string_literal: true module GObjectIntrospection # Wraps a GIEnumInfo struct, if it represents a flag type. class IFlagsInfo < IEnumInfo end end gir_ffi-0.16.1/lib/ffi-gobject_introspection/i_function_info.rb0000644000004100000410000000116314524576001024643 0ustar www-datawww-data# frozen_string_literal: true module GObjectIntrospection # Wraps a GIFunctionInfo struct. # Represents a function or method. class IFunctionInfo < ICallableInfo def symbol Lib.g_function_info_get_symbol self end def flags @flags ||= Lib.g_function_info_get_flags self end def method? flags[:is_method] end def constructor? flags[:is_constructor] end def getter? flags[:is_getter] end def setter? flags[:is_setter] end def wraps_vfunc? flags[:wraps_vfunc] end def throws? flags[:throws] end end end gir_ffi-0.16.1/lib/ffi-gobject_introspection/i_callable_info.rb0000644000004100000410000000207014524576001024553 0ustar www-datawww-data# frozen_string_literal: true require "ffi-gobject_introspection/i_base_info" require "ffi-gobject_introspection/i_type_info" require "ffi-gobject_introspection/i_arg_info" module GObjectIntrospection # Wraps a GICallableInfo struct; represents a callable, either # IFunctionInfo, ICallbackInfo or IVFuncInfo. class ICallableInfo < IBaseInfo def return_type @return_type ||= ITypeInfo.wrap Lib.g_callable_info_get_return_type(self) end def caller_owns Lib.g_callable_info_get_caller_owns self end def may_return_null? Lib.g_callable_info_may_return_null self end def can_throw_gerror? Lib.g_callable_info_can_throw_gerror self end def n_args Lib.g_callable_info_get_n_args self end def arg(index) IArgInfo.wrap Lib.g_callable_info_get_arg(self, index) end ## build_array_method :args def skip_return? Lib.g_callable_info_skip_return self end def instance_ownership_transfer Lib.g_callable_info_get_instance_ownership_transfer self end end end gir_ffi-0.16.1/lib/ffi-gobject_introspection/i_callback_info.rb0000644000004100000410000000032714524576001024553 0ustar www-datawww-data# frozen_string_literal: true module GObjectIntrospection # Wraps a GICallbackInfo struct. Has no methods in addition to the ones # inherited from ICallableInfo. class ICallbackInfo < ICallableInfo end end gir_ffi-0.16.1/lib/ffi-gobject_introspection/i_type_info.rb0000644000004100000410000000217414524576001024002 0ustar www-datawww-data# frozen_string_literal: true module GObjectIntrospection # Wraps a GITypeInfo struct. # Represents type information, direction, transfer etc. class ITypeInfo < IBaseInfo def pointer? return @pointer_eh if defined? @pointer_eh @pointer_eh = Lib.g_type_info_is_pointer self end def tag @tag ||= Lib.g_type_info_get_tag self end def param_type(index) @param_type_cache ||= [] @param_type_cache[index] ||= ITypeInfo.wrap Lib.g_type_info_get_param_type(self, index) end def interface @interface ||= begin ptr = Lib.g_type_info_get_interface self IRepository.wrap_ibaseinfo_pointer ptr end end def array_length @array_length ||= Lib.g_type_info_get_array_length self end def array_fixed_size Lib.g_type_info_get_array_fixed_size self end def array_type Lib.g_type_info_get_array_type self end def zero_terminated? Lib.g_type_info_is_zero_terminated self end def name raise "Should not call this for ITypeInfo" end end end gir_ffi-0.16.1/lib/ffi-gobject_introspection/i_registered_type_info.rb0000644000004100000410000000070014524576001026210 0ustar www-datawww-data# frozen_string_literal: true module GObjectIntrospection # Wraps a GIRegisteredTypeInfo struct. # Represents a registered type. class IRegisteredTypeInfo < IBaseInfo def type_name Lib.g_registered_type_info_get_type_name self end def type_init Lib.g_registered_type_info_get_type_init self end def g_type Lib.g_registered_type_info_get_g_type self end alias_method :gtype, :g_type end end gir_ffi-0.16.1/lib/ffi-gobject_introspection/i_signal_info.rb0000644000004100000410000000027414524576001024275 0ustar www-datawww-data# frozen_string_literal: true module GObjectIntrospection # Wraps a GISignalInfo struct. # Represents a signal. # Not implemented yet. class ISignalInfo < ICallableInfo end end gir_ffi-0.16.1/lib/ffi-gobject_introspection/i_arg_info.rb0000644000004100000410000000173114524576001023570 0ustar www-datawww-data# frozen_string_literal: true require "ffi-gobject_introspection/i_base_info" module GObjectIntrospection # Wraps a GIArgInfo struct. # Represents an argument. class IArgInfo < IBaseInfo def direction Lib.g_arg_info_get_direction self end def return_value? Lib.g_arg_info_is_return_value self end def optional? Lib.g_arg_info_is_optional self end def caller_allocates? Lib.g_arg_info_is_caller_allocates self end def may_be_null? Lib.g_arg_info_may_be_null self end def skip? Lib.g_arg_info_is_skip self end def ownership_transfer Lib.g_arg_info_get_ownership_transfer self end def scope Lib.g_arg_info_get_scope self end def closure Lib.g_arg_info_get_closure self end def destroy Lib.g_arg_info_get_destroy self end def argument_type @argument_type ||= ITypeInfo.wrap Lib.g_arg_info_get_type(self) end end end gir_ffi-0.16.1/lib/ffi-gobject_introspection/i_unresolved_info.rb0000644000004100000410000000035014524576001025201 0ustar www-datawww-data# frozen_string_literal: true require "ffi-gobject_introspection/i_base_info" module GObjectIntrospection # Wraps a GIBaseInfo struct in the case where the info type is :unresolved. class IUnresolvedInfo < IBaseInfo end end gir_ffi-0.16.1/lib/ffi-gobject_introspection/i_struct_info.rb0000644000004100000410000000205314524576001024341 0ustar www-datawww-data# frozen_string_literal: true module GObjectIntrospection # Wraps a GIStructInfo struct. # Represents a struct. class IStructInfo < IRegisteredTypeInfo def n_fields Lib.g_struct_info_get_n_fields self end def field(index) IFieldInfo.wrap Lib.g_struct_info_get_field(self, index) end ## build_array_method :fields build_finder_method :find_field def get_n_methods Lib.g_struct_info_get_n_methods self end def get_method(index) @method_cache ||= [] @method_cache[index] ||= IFunctionInfo.wrap Lib.g_struct_info_get_method(self, index) end ## build_array_method :get_methods # There is a function g_struct_info_find_method but it causes a core dump. build_finder_method :find_method, :get_n_methods, :get_method def size Lib.g_struct_info_get_size self end def empty? size == 0 end def alignment Lib.g_struct_info_get_alignment self end def gtype_struct? Lib.g_struct_info_is_gtype_struct self end end end gir_ffi-0.16.1/lib/ffi-gobject_introspection/g_error.rb0000644000004100000410000000061514524576001023133 0ustar www-datawww-data# frozen_string_literal: true module GObjectIntrospection # Wraps GLib's GError struct. class GError # GLib's GError struct. class Struct < FFI::Struct layout :domain, :uint32, :code, :int, :message, :string end def initialize(ptr) @struct = self.class::Struct.new(ptr) end def message @struct[:message] end end end gir_ffi-0.16.1/lib/ffi-gobject_introspection/i_property_info.rb0000644000004100000410000000112714524576001024702 0ustar www-datawww-data# frozen_string_literal: true module GObjectIntrospection # Wraps a GIPropertyInfo struct. # Represents a property of an IObjectInfo or an IInterfaceInfo. class IPropertyInfo < IBaseInfo def property_type @property_type ||= ITypeInfo.wrap Lib.g_property_info_get_type(self) end def flags @flags ||= Lib.g_property_info_get_flags self end def readable? flags[:readable] end def writeable? flags[:writable] end def construct? flags[:construct] end def construct_only? flags[:construct_only] end end end gir_ffi-0.16.1/lib/ffi-gobject_introspection/i_object_info.rb0000644000004100000410000000477114524576001024274 0ustar www-datawww-data# frozen_string_literal: true module GObjectIntrospection # Wraps a GIObjectInfo struct. # Represents an object. class IObjectInfo < IRegisteredTypeInfo def type_name Lib.g_object_info_get_type_name self end def type_init Lib.g_object_info_get_type_init self end def abstract? Lib.g_object_info_get_abstract self end def fundamental? Lib.g_object_info_get_fundamental self end def parent @parent ||= IObjectInfo.wrap Lib.g_object_info_get_parent(self) end def n_interfaces Lib.g_object_info_get_n_interfaces self end def interface(index) IInterfaceInfo.wrap Lib.g_object_info_get_interface(self, index) end ## build_array_method :interfaces def n_fields Lib.g_object_info_get_n_fields self end def field(index) IFieldInfo.wrap Lib.g_object_info_get_field(self, index) end ## build_array_method :fields def n_properties Lib.g_object_info_get_n_properties self end def property(index) IPropertyInfo.wrap Lib.g_object_info_get_property(self, index) end def properties @properties ||= Array.new(n_properties) { |idx| property(idx) } end def find_property(name) name = name.to_s.tr("_", "-") properties.find { |prop| prop.name == name } end def get_n_methods Lib.g_object_info_get_n_methods self end def get_method(index) IFunctionInfo.wrap Lib.g_object_info_get_method(self, index) end ## build_array_method :get_methods def find_method(name) IFunctionInfo.wrap Lib.g_object_info_find_method(self, name.to_s) end def n_signals Lib.g_object_info_get_n_signals self end def signal(index) ISignalInfo.wrap Lib.g_object_info_get_signal(self, index) end ## build_array_method :signals build_finder_method :find_signal def n_vfuncs Lib.g_object_info_get_n_vfuncs self end def vfunc(index) IVFuncInfo.wrap Lib.g_object_info_get_vfunc(self, index) end def find_vfunc(name) IVFuncInfo.wrap Lib.g_object_info_find_vfunc(self, name.to_s) end ## build_array_method :vfuncs def n_constants Lib.g_object_info_get_n_constants self end def constant(index) IConstantInfo.wrap Lib.g_object_info_get_constant(self, index) end ## build_array_method :constants def class_struct IStructInfo.wrap Lib.g_object_info_get_class_struct(self) end end end gir_ffi-0.16.1/lib/ffi-gobject_introspection/i_constant_info.rb0000644000004100000410000000211114524576001024641 0ustar www-datawww-data# frozen_string_literal: true module GObjectIntrospection # Wraps a GIConstantInfo struct; represents a constant. class IConstantInfo < IBaseInfo TYPE_TAG_TO_UNION_MEMBER = { gboolean: :v_boolean, gint8: :v_int8, gint16: :v_int16, gint32: :v_int32, gint64: :v_int64, guint8: :v_uint8, guint16: :v_uint16, guint32: :v_uint32, guint64: :v_uint64, gdouble: :v_double, utf8: :v_string }.freeze def value case type_tag when :utf8 raw_value.force_encoding("utf-8") when :gboolean raw_value.nonzero? ? true : false else raw_value end end def constant_type @constant_type ||= ITypeInfo.wrap Lib.g_constant_info_get_type self end private def type_tag @type_tag ||= constant_type.tag end def raw_value value_union = Lib::GIArgument.new Lib.g_constant_info_get_value self, value_union value_union[union_member_key] end def union_member_key TYPE_TAG_TO_UNION_MEMBER[type_tag] end end end gir_ffi-0.16.1/lib/ffi-gobject_introspection/strv.rb0000644000004100000410000000132714524576001022473 0ustar www-datawww-data# frozen_string_literal: true require "ffi" module GObjectIntrospection # Represents a null-terminated array of strings. # GLib uses this # construction, but does not provide any actual functions for this class. class Strv include Enumerable POINTER_SIZE = FFI.type_size(:pointer) def initialize(ptr) @ptr = ptr end def to_ptr @ptr end def each offset = 0 while (ptr = fetch_ptr offset) offset += POINTER_SIZE yield ptr.read_string end end def self.wrap(ptr) new ptr end private def fetch_ptr(offset) return if @ptr.null? ptr = @ptr.get_pointer offset ptr unless ptr.null? end end end gir_ffi-0.16.1/lib/ffi-gobject_introspection/i_value_info.rb0000644000004100000410000000036714524576001024137 0ustar www-datawww-data# frozen_string_literal: true module GObjectIntrospection # Wraps a GIValueInfo struct. # Represents one of the enum values of an IEnumInfo. class IValueInfo < IBaseInfo def value Lib.g_value_info_get_value self end end end gir_ffi-0.16.1/lib/ffi-gobject_introspection/lib.rb0000644000004100000410000002726314524576001022252 0ustar www-datawww-data# frozen_string_literal: true require "ffi" require "ffi/bit_masks" module GObjectIntrospection # Module for attaching functions from the girepository library module Lib extend FFI::Library extend FFI::BitMasks ffi_lib "girepository-1.0.so.1" # IRepository enum :IRepositoryLoadFlags, [:LAZY, (1 << 0)] attach_function :g_irepository_get_default, [], :pointer attach_function :g_irepository_prepend_search_path, [:string], :void attach_function :g_irepository_require, [:pointer, :string, :string, :IRepositoryLoadFlags, :pointer], :pointer attach_function :g_irepository_get_version, [:pointer, :string], :string attach_function :g_irepository_get_n_infos, [:pointer, :string], :int attach_function :g_irepository_get_info, [:pointer, :string, :int], :pointer attach_function :g_irepository_find_by_name, [:pointer, :string, :string], :pointer attach_function :g_irepository_find_by_gtype, [:pointer, :size_t], :pointer attach_function :g_irepository_get_dependencies, [:pointer, :string], :pointer attach_function :g_irepository_get_shared_library, [:pointer, :string], :string # IBaseInfo enum :IInfoType, [ :invalid, :function, :callback, :struct, :boxed, :enum, :flags, :object, :interface, :constant, :invalid_was_error_domain, # deprecated in GI 1.29.17 :union, :value, :signal, :vfunc, :property, :field, :arg, :type, :unresolved ] attach_function :g_base_info_ref, [:pointer], :void attach_function :g_base_info_unref, [:pointer], :void attach_function :g_base_info_get_attribute, [:pointer, :string], :string attach_function :g_base_info_get_type, [:pointer], :IInfoType attach_function :g_base_info_get_name, [:pointer], :string attach_function :g_base_info_get_namespace, [:pointer], :string attach_function :g_base_info_get_container, [:pointer], :pointer attach_function :g_base_info_is_deprecated, [:pointer], :bool attach_function :g_base_info_equal, [:pointer, :pointer], :bool # IFunctionInfo bit_mask :IFunctionInfoFlags, is_method: (1 << 0), is_constructor: (1 << 1), is_getter: (1 << 2), is_setter: (1 << 3), wraps_vfunc: (1 << 4), throws: (1 << 5) attach_function :g_function_info_get_symbol, [:pointer], :string attach_function :g_function_info_get_flags, [:pointer], :IFunctionInfoFlags # ICallableInfo enum :ITransfer, [ :nothing, :container, :everything ] attach_function :g_callable_info_get_return_type, [:pointer], :pointer attach_function :g_callable_info_get_caller_owns, [:pointer], :ITransfer attach_function :g_callable_info_may_return_null, [:pointer], :bool attach_function :g_callable_info_can_throw_gerror, [:pointer], :bool attach_function :g_callable_info_get_instance_ownership_transfer, [:pointer], :ITransfer attach_function :g_callable_info_get_n_args, [:pointer], :int attach_function :g_callable_info_get_arg, [:pointer, :int], :pointer attach_function :g_callable_info_skip_return, [:pointer], :bool # IArgInfo enum :IDirection, [ :in, :out, :inout ] enum :IScopeType, [ :invalid, :call, :async, :notified ] attach_function :g_arg_info_get_direction, [:pointer], :IDirection attach_function :g_arg_info_is_return_value, [:pointer], :bool attach_function :g_arg_info_is_optional, [:pointer], :bool attach_function :g_arg_info_is_caller_allocates, [:pointer], :bool attach_function :g_arg_info_is_skip, [:pointer], :bool attach_function :g_arg_info_may_be_null, [:pointer], :bool attach_function :g_arg_info_get_ownership_transfer, [:pointer], :ITransfer attach_function :g_arg_info_get_scope, [:pointer], :IScopeType attach_function :g_arg_info_get_closure, [:pointer], :int attach_function :g_arg_info_get_destroy, [:pointer], :int attach_function :g_arg_info_get_type, [:pointer], :pointer # ITypeTag enum :ITypeTag, [ :void, :gboolean, :gint8, :guint8, :gint16, :guint16, :gint32, :guint32, :gint64, :guint64, :gfloat, :gdouble, :GType, :utf8, :filename, :array, :interface, :glist, :gslist, :ghash, :error, :gunichar ] attach_function :g_type_tag_to_string, [:ITypeTag], :string # ITypeInfo enum :IArrayType, [ :c, :array, :ptr_array, :byte_array ] attach_function :g_type_info_is_pointer, [:pointer], :bool attach_function :g_type_info_get_tag, [:pointer], :ITypeTag attach_function :g_type_info_get_param_type, [:pointer, :int], :pointer attach_function :g_type_info_get_interface, [:pointer], :pointer attach_function :g_type_info_get_array_length, [:pointer], :int attach_function :g_type_info_get_array_fixed_size, [:pointer], :int attach_function :g_type_info_get_array_type, [:pointer], :IArrayType attach_function :g_type_info_is_zero_terminated, [:pointer], :bool # IStructInfo attach_function :g_struct_info_get_n_fields, [:pointer], :int attach_function :g_struct_info_get_field, [:pointer, :int], :pointer attach_function :g_struct_info_get_n_methods, [:pointer], :int attach_function :g_struct_info_get_method, [:pointer, :int], :pointer attach_function :g_struct_info_find_method, [:pointer, :string], :pointer attach_function :g_struct_info_get_size, [:pointer], :int attach_function :g_struct_info_get_alignment, [:pointer], :int attach_function :g_struct_info_is_gtype_struct, [:pointer], :bool # IValueInfo attach_function :g_value_info_get_value, [:pointer], :long # IFieldInfo bit_mask :IFieldInfoFlags, readable: (1 << 0), writable: (1 << 1) attach_function :g_field_info_get_flags, [:pointer], :IFieldInfoFlags attach_function :g_field_info_get_size, [:pointer], :int attach_function :g_field_info_get_offset, [:pointer], :int attach_function :g_field_info_get_type, [:pointer], :pointer # IUnionInfo attach_function :g_union_info_get_n_fields, [:pointer], :int attach_function :g_union_info_get_field, [:pointer, :int], :pointer attach_function :g_union_info_get_n_methods, [:pointer], :int attach_function :g_union_info_get_method, [:pointer, :int], :pointer attach_function :g_union_info_find_method, [:pointer, :string], :pointer attach_function :g_union_info_get_size, [:pointer], :int attach_function :g_union_info_get_alignment, [:pointer], :int # IRegisteredTypeInfo attach_function :g_registered_type_info_get_type_name, [:pointer], :string attach_function :g_registered_type_info_get_type_init, [:pointer], :string attach_function :g_registered_type_info_get_g_type, [:pointer], :size_t # IEnumInfo attach_function :g_enum_info_get_storage_type, [:pointer], :ITypeTag attach_function :g_enum_info_get_n_values, [:pointer], :int attach_function :g_enum_info_get_value, [:pointer, :int], :pointer attach_function :g_enum_info_get_n_methods, [:pointer], :int attach_function :g_enum_info_get_method, [:pointer, :int], :pointer # IObjectInfo attach_function :g_object_info_get_type_name, [:pointer], :string attach_function :g_object_info_get_type_init, [:pointer], :string attach_function :g_object_info_get_abstract, [:pointer], :bool attach_function :g_object_info_get_parent, [:pointer], :pointer attach_function :g_object_info_get_n_interfaces, [:pointer], :int attach_function :g_object_info_get_interface, [:pointer, :int], :pointer attach_function :g_object_info_get_n_fields, [:pointer], :int attach_function :g_object_info_get_field, [:pointer, :int], :pointer attach_function :g_object_info_get_n_properties, [:pointer], :int attach_function :g_object_info_get_property, [:pointer, :int], :pointer attach_function :g_object_info_get_n_methods, [:pointer], :int attach_function :g_object_info_get_method, [:pointer, :int], :pointer attach_function :g_object_info_find_method, [:pointer, :string], :pointer attach_function :g_object_info_get_n_signals, [:pointer], :int attach_function :g_object_info_get_signal, [:pointer, :int], :pointer attach_function :g_object_info_get_n_vfuncs, [:pointer], :int attach_function :g_object_info_get_vfunc, [:pointer, :int], :pointer attach_function :g_object_info_find_vfunc, [:pointer, :string], :pointer attach_function :g_object_info_get_n_constants, [:pointer], :int attach_function :g_object_info_get_constant, [:pointer, :int], :pointer attach_function :g_object_info_get_class_struct, [:pointer], :pointer attach_function :g_object_info_get_fundamental, [:pointer], :bool # IVFuncInfo bit_mask :IVFuncInfoFlags, must_chain_up: (1 << 0), must_override: (1 << 1), must_not_override: (1 << 2), throws: (1 << 3) attach_function :g_vfunc_info_get_flags, [:pointer], :IVFuncInfoFlags attach_function :g_vfunc_info_get_invoker, [:pointer], :pointer # IInterfaceInfo attach_function :g_interface_info_get_n_prerequisites, [:pointer], :int attach_function :g_interface_info_get_prerequisite, [:pointer, :int], :pointer attach_function :g_interface_info_get_n_properties, [:pointer], :int attach_function :g_interface_info_get_property, [:pointer, :int], :pointer attach_function :g_interface_info_get_n_methods, [:pointer], :int attach_function :g_interface_info_get_method, [:pointer, :int], :pointer attach_function :g_interface_info_find_method, [:pointer, :string], :pointer attach_function :g_interface_info_get_n_signals, [:pointer], :int attach_function :g_interface_info_get_signal, [:pointer, :int], :pointer attach_function :g_interface_info_get_n_vfuncs, [:pointer], :int attach_function :g_interface_info_get_vfunc, [:pointer, :int], :pointer attach_function :g_interface_info_find_vfunc, [:pointer, :string], :pointer attach_function :g_interface_info_get_n_constants, [:pointer], :int attach_function :g_interface_info_get_constant, [:pointer, :int], :pointer attach_function :g_interface_info_get_iface_struct, [:pointer], :pointer # Union type representing an argument value class GIArgument < FFI::Union signed_size_t = "int#{FFI.type_size(:size_t) * 8}".to_sym layout :v_boolean, :int, :v_int8, :int8, :v_uint8, :uint8, :v_int16, :int16, :v_uint16, :uint16, :v_int32, :int32, :v_uint32, :uint32, :v_int64, :int64, :v_uint64, :uint64, :v_float, :float, :v_double, :double, :v_short, :short, :v_ushort, :ushort, :v_int, :int, :v_uint, :uint, :v_long, :long, :v_ulong, :ulong, :v_ssize, signed_size_t, :v_size, :size_t, :v_string, :string, :v_pointer, :pointer end # IConstInfo # attach_function :g_constant_info_get_type, [:pointer], :pointer attach_function :g_constant_info_get_value, [:pointer, :pointer], :int # IPropertyInfo # attach_function :g_property_info_get_type, [:pointer], :pointer # NOTE: This type has more values, but these are the ones used bit_mask :ParamFlags, readable: (1 << 0), writable: (1 << 1), construct: (1 << 2), construct_only: (1 << 3) attach_function :g_property_info_get_flags, [:pointer], :ParamFlags end end gir_ffi-0.16.1/lib/ffi-gobject_introspection/i_union_info.rb0000644000004100000410000000145714524576001024154 0ustar www-datawww-data# frozen_string_literal: true module GObjectIntrospection # Wraps a GIUnionInfo struct. # Represents a union. class IUnionInfo < IRegisteredTypeInfo def n_fields Lib.g_union_info_get_n_fields self end def field(index) IFieldInfo.wrap Lib.g_union_info_get_field(self, index) end ## build_array_method :fields def get_n_methods Lib.g_union_info_get_n_methods self end def get_method(index) IFunctionInfo.wrap Lib.g_union_info_get_method(self, index) end ## build_array_method :get_methods def find_method(name) IFunctionInfo.wrap Lib.g_union_info_find_method(self, name.to_s) end def size Lib.g_union_info_get_size self end def alignment Lib.g_union_info_get_alignment self end end end gir_ffi-0.16.1/lib/ffi-gobject_introspection/i_enum_info.rb0000644000004100000410000000150514524576001023762 0ustar www-datawww-data# frozen_string_literal: true module GObjectIntrospection # Wraps a GIEnumInfo struct if it represents an enum. # If it represents a flag, an IFlagsInfo object is used instead. class IEnumInfo < IRegisteredTypeInfo def n_values Lib.g_enum_info_get_n_values self end def value(index) IValueInfo.wrap Lib.g_enum_info_get_value(self, index) end ## build_array_method :values build_finder_method :find_value, :n_values, :value def get_n_methods Lib.g_enum_info_get_n_methods self end def get_method(index) IFunctionInfo.wrap Lib.g_enum_info_get_method(self, index) end ## build_array_method :get_methods build_finder_method :find_method, :get_n_methods, :get_method def storage_type Lib.g_enum_info_get_storage_type self end end end gir_ffi-0.16.1/lib/ffi-gobject_introspection/i_vfunc_info.rb0000644000004100000410000000057314524576001024143 0ustar www-datawww-data# frozen_string_literal: true module GObjectIntrospection # Wraps a GIVFuncInfo struct. # Represents a virtual function. class IVFuncInfo < ICallableInfo def flags Lib.g_vfunc_info_get_flags self end def throws? flags.fetch :throws end def invoker @invoker ||= IFunctionInfo.wrap Lib.g_vfunc_info_get_invoker self end end end gir_ffi-0.16.1/lib/ffi-gobject_introspection/gobject_type_init.rb0000644000004100000410000000062014524576001025171 0ustar www-datawww-data# frozen_string_literal: true require "ffi" module GObjectIntrospection # Provides access to the g_type_init function. module GObjectTypeInit def self.type_init Lib.g_type_init end # Module for attaching g_type_init from the gobject library. module Lib extend FFI::Library ffi_lib "gobject-2.0" attach_function :g_type_init, [], :void end end end gir_ffi-0.16.1/lib/gir_ffi/0000755000004100000410000000000014524576001015413 5ustar www-datawww-datagir_ffi-0.16.1/lib/gir_ffi/method_stubber.rb0000644000004100000410000000067014524576001020751 0ustar www-datawww-data# frozen_string_literal: true module GirFFI # Generates method stubs that will replace themselves with the real # method upon being called. class MethodStubber def initialize(method_info) @info = method_info end def method_stub <<~STUB def #{@info.method? ? "" : "self."}#{@info.safe_name} *args, &block setup_and_call "#{@info.name}", args, &block end STUB end end end gir_ffi-0.16.1/lib/gir_ffi/arg_helper.rb0000644000004100000410000000375214524576001020057 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/allocation_helper" require "gir_ffi/builder" require "gir_ffi/glib_error" require "gir_ffi/object_store" module GirFFI # Helper module containing methods used during argument conversion in # generated methods. module ArgHelper OBJECT_STORE = ObjectStore.new def self.check_error(errpp) err = GLib::Error.wrap(errpp.read_pointer) raise GLibError, err if err end def self.check_fixed_array_size(size, arr, name) raise ArgumentError, "#{name} should have size #{size}" unless arr.size.equal? size end # NOTE: Only used in List, SList and HashTable classes. # TODO: Stop using basic types and instead cast type to an ITypeInfo # look-alike. def self.cast_from_pointer(type, ptr) case type when Symbol cast_from_simple_type_pointer(type, ptr) when Class type.wrap ptr when Array cast_from_complex_type_pointer(type, ptr) end end def self.cast_uint32_to_int32(val) if val >= 0x80000000 -(0x100000000 - val) else val end end def self.cast_pointer_to_int32(ptr) cast_uint32_to_int32(ptr.address & 0xffffffff) end def self.store(obj) OBJECT_STORE.store(obj) end def self.cast_from_simple_type_pointer(type, ptr) case type when :utf8, :filename ptr.to_utf8 when :gint32, :gint8 cast_pointer_to_int32 ptr when :guint32 ptr.address else raise "Don't know how to cast #{type}" end end def self.cast_from_complex_type_pointer(type, ptr) main_type, (container_type, *element_type) = *type case main_type when :pointer case container_type when :ghash return GLib::HashTable.wrap(element_type, ptr) end end raise "Don't know how to cast #{type}" end private_class_method :cast_from_complex_type_pointer, :cast_from_simple_type_pointer end end gir_ffi-0.16.1/lib/gir_ffi/class_base.rb0000644000004100000410000000532714524576001020046 0ustar www-datawww-data# frozen_string_literal: true require "forwardable" require "gir_ffi/registered_type_base" require "gir_ffi/builders/null_class_builder" require "gir_ffi/method_setup" require "gir_ffi/instance_method_setup" module GirFFI # Base class for all generated classes and structs. Contains code for dealing # with the generated nested Struct classes. class ClassBase extend RegisteredTypeBase extend Forwardable extend MethodSetup extend InstanceMethodSetup GIR_FFI_BUILDER = Builders::NullClassBuilder.new attr_reader :struct def_delegators :@struct, :to_ptr def setup_and_call(method, arguments, &block) method_name = self.class.try_in_ancestors(:setup_instance_method, method.to_s) raise NoMethodError, "undefined method `#{method}' for #{self}" unless method_name send method_name, *arguments, &block end def ==(other) other.class == self.class && to_ptr == other.to_ptr end def self.setup_and_call(method, arguments, &block) method_name = try_in_ancestors(:setup_method, method.to_s) raise NoMethodError, "undefined method `#{method}' for #{self}" unless method_name send method_name, *arguments, &block end def self.try_in_ancestors(method, *arguments) ancestors.each do |klass| if klass.respond_to?(method) result = klass.send(method, *arguments) return result if result end end nil end def self.to_ffi_type self::Struct end def self.to_callback_ffi_type :pointer end # Wrap the passed pointer in an instance of the current class, or a # descendant type if applicable. def self.wrap(ptr) direct_wrap ptr end # Wrap the passed pointer in an instance of the current class. Will not # do any casting to subtypes or additional processing. def self.direct_wrap(ptr) return nil if !ptr || ptr.null? obj = allocate obj.__send__ :assign_pointer, ptr obj end # Pass-through casting method. This may become a type checking # method. It is overridden by GValue to implement wrapping of plain # Ruby objects. def self.from(val) val end private # Stores a pointer created by a constructor function. Derived classes may # perform additional processing. For example, InitiallyUnowned overrides it # to sink the floating object. # # This method assumes the pointer will always be of the type corresponding # to the current class, and never of a subtype. # # @param ptr Pointer to the object's C structure def store_pointer(ptr) assign_pointer ptr end def assign_pointer(ptr) @struct = self.class::Struct.new(ptr) end end end gir_ffi-0.16.1/lib/gir_ffi/version.rb0000644000004100000410000000013714524576001017426 0ustar www-datawww-data# frozen_string_literal: true # Current GirFFI version module GirFFI VERSION = "0.16.1" end gir_ffi-0.16.1/lib/gir_ffi/info_ext/0000755000004100000410000000000014524576001017226 5ustar www-datawww-datagir_ffi-0.16.1/lib/gir_ffi/info_ext/i_field_info.rb0000644000004100000410000000073014524576001022161 0ustar www-datawww-data# frozen_string_literal: true module GirFFI module InfoExt # Extensions for GObjectIntrospection::IFieldInfo needed by GirFFI module IFieldInfo def layout_specification [name.to_sym, field_type.to_ffi_type, offset] end def related_array_length_field index = field_type.array_length container.fields[index] if index > -1 end end end end GObjectIntrospection::IFieldInfo.include GirFFI::InfoExt::IFieldInfo gir_ffi-0.16.1/lib/gir_ffi/info_ext/i_function_info.rb0000644000004100000410000000132514524576001022724 0ustar www-datawww-data# frozen_string_literal: true module GirFFI module InfoExt # Extensions for GObjectIntrospection::IFunctionInfo needed by GirFFI module IFunctionInfo def argument_ffi_types super.tap do |types| types.unshift :pointer if method? types << :pointer if throws? end end def return_ffi_type return_type.to_ffi_type end def full_name if method? "#{container.full_name}##{safe_name}" elsif container "#{container.full_name}.#{safe_name}" else "#{safe_namespace}.#{safe_name}" end end end end end GObjectIntrospection::IFunctionInfo.include GirFFI::InfoExt::IFunctionInfo gir_ffi-0.16.1/lib/gir_ffi/info_ext/i_callable_info.rb0000644000004100000410000000050614524576001022636 0ustar www-datawww-data# frozen_string_literal: true module GirFFI module InfoExt # Extensions for GObjectIntrospection::ICallableInfo needed by GirFFI module ICallableInfo def argument_ffi_types args.map(&:to_ffi_type) end end end end GObjectIntrospection::ICallableInfo.include GirFFI::InfoExt::ICallableInfo gir_ffi-0.16.1/lib/gir_ffi/info_ext/i_callback_info.rb0000644000004100000410000000103314524576001022627 0ustar www-datawww-data# frozen_string_literal: true module GirFFI module InfoExt # Extensions for GObjectIntrospection::ICallbackInfo needed by GirFFI module ICallbackInfo def to_ffi_type Builder.build_class(self) end def to_callback_ffi_type :pointer end def argument_ffi_types args.map(&:to_callback_ffi_type) end def return_ffi_type return_type.to_callback_ffi_type end end end end GObjectIntrospection::ICallbackInfo.include GirFFI::InfoExt::ICallbackInfo gir_ffi-0.16.1/lib/gir_ffi/info_ext/i_type_info.rb0000644000004100000410000001403114524576001022056 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/builder_helper" module GirFFI module InfoExt # Extensions for GObjectIntrospection::ITypeInfo needed by GirFFI module ITypeInfo FLATTENED_TAG_TO_GTYPE_MAP = { gboolean: GObject::TYPE_BOOLEAN, gint32: GObject::TYPE_INT, gint64: GObject::TYPE_INT64, guint64: GObject::TYPE_UINT64, void: GObject::TYPE_NONE }.freeze FLATTENED_TAG_POINTER_TO_GTYPE_MAP = { array: GObject::TYPE_ARRAY, ghash: GObject::TYPE_HASH_TABLE, strv: GObject::TYPE_STRV, utf8: GObject::TYPE_STRING }.freeze def gtype return interface.gtype if tag == :interface if pointer? FLATTENED_TAG_POINTER_TO_GTYPE_MAP.fetch(flattened_tag, GObject::TYPE_POINTER) else FLATTENED_TAG_TO_GTYPE_MAP.fetch(flattened_tag) end end def make_g_value GObject::Value.for_gtype gtype end def element_type case tag when :glist, :gslist, :array, :c enumerable_element_type when :ghash dictionary_element_type end end def flattened_tag @flattened_tag ||= case tag when :interface interface_type when :array flattened_array_type else tag end end def interface_type tag == :interface && interface.info_type end def hidden_struct_type? flattened_tag == :struct && interface.empty? end def tag_or_class base = case tag when :interface interface_class when :ghash [tag, *element_type] else flattened_tag end if pointer? && tag != :utf8 && tag != :filename [:pointer, base] else base end end def interface_class @interface_class ||= Builder.build_class interface if tag == :interface end TAG_TO_WRAPPER_CLASS_MAP = { array: "GLib::Array", byte_array: "GLib::ByteArray", c: "GirFFI::SizedArray", error: "GLib::Error", ghash: "GLib::HashTable", glist: "GLib::List", gslist: "GLib::SList", ptr_array: "GLib::PtrArray", strv: "GLib::Strv", utf8: "GirFFI::InPointer", # TODO: Create a string-like class void: "GirFFI::InPointer", # TODO: Create a void-pointer class zero_terminated: "GirFFI::ZeroTerminated" }.freeze # TODO: Use class rather than class name def argument_class_name interface_class_name || TAG_TO_WRAPPER_CLASS_MAP[flattened_tag] end def interface_class_name interface.full_name if tag == :interface end def to_ffi_type return :pointer if pointer? case tag when :interface interface.to_ffi_type when :array [subtype_ffi_type(0), array_fixed_size] else TypeMap.map_basic_type tag end end def to_callback_ffi_type return :pointer if pointer? case tag when :interface interface.to_callback_ffi_type when :gboolean # TODO: Move this logic into TypeMap :bool else TypeMap.map_basic_type tag end end TAGS_NEEDING_RUBY_TO_C_CONVERSION = [ :array, :c, :callback, :error, :ghash, :glist, :gslist, :object, :ptr_array, :struct, :strv, :utf8, :zero_terminated ].freeze TAGS_NEEDING_C_TO_RUBY_CONVERSION = [ :array, :byte_array, :c, :error, :filename, :ghash, :glist, :gslist, :interface, :object, :ptr_array, :struct, :strv, :union, :utf8, :zero_terminated ].freeze def needs_ruby_to_c_conversion_for_functions? TAGS_NEEDING_RUBY_TO_C_CONVERSION.include?(flattened_tag) end def needs_c_to_ruby_conversion_for_functions? TAGS_NEEDING_C_TO_RUBY_CONVERSION.include?(flattened_tag) end def needs_ruby_to_c_conversion_for_callbacks? [:enum].include?(flattened_tag) || needs_ruby_to_c_conversion_for_functions? end def needs_c_to_ruby_conversion_for_callbacks? [:callback, :enum].include?(flattened_tag) || needs_c_to_ruby_conversion_for_functions? end def needs_c_to_ruby_conversion_for_closures? [:array, :c, :error, :ghash, :glist, :ptr_array, :struct, :strv] .include?(flattened_tag) end def needs_ruby_to_c_conversion_for_closures? [:array].include?(flattened_tag) end def needs_ruby_to_c_conversion_for_properties? [:glist, :ghash, :strv, :callback].include?(flattened_tag) end def needs_c_to_ruby_conversion_for_properties? [:glist, :ghash, :callback].include?(flattened_tag) end def extra_conversion_arguments case flattened_tag when :c [element_type, array_fixed_size] when :array, :ghash, :glist, :gslist, :ptr_array, :zero_terminated [element_type] else [] end end GOBJECT_VALUE_NAME = "GObject::Value" def gvalue? argument_class_name == GOBJECT_VALUE_NAME end private def subtype_tag_or_class(index) param_type(index).tag_or_class end def dictionary_element_type [subtype_tag_or_class(0), subtype_tag_or_class(1)] end def enumerable_element_type subtype_tag_or_class 0 end def subtype_ffi_type(index) param_type(index).to_ffi_type end def flattened_array_type if zero_terminated? zero_terminated_array_type else array_type end end def zero_terminated_array_type case element_type when :utf8, :filename :strv else :zero_terminated end end end end end GObjectIntrospection::ITypeInfo.include GirFFI::InfoExt::ITypeInfo gir_ffi-0.16.1/lib/gir_ffi/info_ext/i_registered_type_info.rb0000644000004100000410000000131514524576001024274 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/builder_helper" module GirFFI module InfoExt # Extensions for GObjectIntrospection::IRegisteredTypeInfo needed by GirFFI module IRegisteredTypeInfo def to_ffi_type to_type.to_ffi_type end def to_callback_ffi_type to_type.to_callback_ffi_type end def to_type Builder.build_class self end def find_instance_method(method) info = find_method method info if info&.method? end def find_method(_method) raise "Must be overridden in subclass" end end end end GObjectIntrospection::IRegisteredTypeInfo.include GirFFI::InfoExt::IRegisteredTypeInfo gir_ffi-0.16.1/lib/gir_ffi/info_ext/i_signal_info.rb0000644000004100000410000000236014524576001022354 0ustar www-datawww-data# frozen_string_literal: true module GirFFI module InfoExt # Extensions for GObjectIntrospection::ISignalInfo needed by GirFFI module ISignalInfo # Create a signal hander closure. Wraps the given block in a custom # descendent of RubyClosure with a marshaller tailored for this signal. # # @param block The body of the signal handler # # @return [GObject::RubyClosure] The signal handler closure, ready to be # passed as a GClosure to C. def wrap_in_closure(&block) bldr = Builders::SignalClosureBuilder.new(self) bldr.build_class.new(&block) end def arguments_to_gvalues(instance, arguments) arg_g_values = args.zip(arguments).map do |arg_info, arg| case arg_info.direction when :in type = arg_info.argument_type type.make_g_value.tap { |it| it.set_value arg } else raise NotImplementedError end end arg_g_values.unshift GObject::Value.wrap_instance(instance) end def gvalue_for_return_value return_type.make_g_value end end end end GObjectIntrospection::ISignalInfo.include GirFFI::InfoExt::ISignalInfo gir_ffi-0.16.1/lib/gir_ffi/info_ext/i_arg_info.rb0000644000004100000410000000073414524576001021653 0ustar www-datawww-data# frozen_string_literal: true module GirFFI module InfoExt # Extensions for GObjectIntrospection::IArgInfo needed by GirFFI module IArgInfo def to_ffi_type return :pointer if direction != :in argument_type.to_ffi_type end def to_callback_ffi_type return :pointer if direction != :in argument_type.to_callback_ffi_type end end end end GObjectIntrospection::IArgInfo.include GirFFI::InfoExt::IArgInfo gir_ffi-0.16.1/lib/gir_ffi/info_ext/i_unresolved_info.rb0000644000004100000410000000047014524576001023265 0ustar www-datawww-data# frozen_string_literal: true module GirFFI module InfoExt # Extensions for GObjectIntrospection::IUnresolvedInfo needed by GirFFI module IUnresolvedInfo def to_ffi_type :pointer end end end end GObjectIntrospection::IUnresolvedInfo.include GirFFI::InfoExt::IUnresolvedInfo gir_ffi-0.16.1/lib/gir_ffi/info_ext/safe_constant_name.rb0000644000004100000410000000142014524576001023377 0ustar www-datawww-data# frozen_string_literal: true module GirFFI module InfoExt # Extension module provinding a #safe_name method suitable for types. module SafeConstantName def safe_name name.tr("-", "_").sub(/^[_a-z]/) do |char| case char when "_" "Private___" else char.upcase end end end end end end GObjectIntrospection::ICallbackInfo.include GirFFI::InfoExt::SafeConstantName GObjectIntrospection::IConstantInfo.include GirFFI::InfoExt::SafeConstantName GObjectIntrospection::IRegisteredTypeInfo.include GirFFI::InfoExt::SafeConstantName GObjectIntrospection::ISignalInfo.include GirFFI::InfoExt::SafeConstantName GObjectIntrospection::IVFuncInfo.include GirFFI::InfoExt::SafeConstantName gir_ffi-0.16.1/lib/gir_ffi/info_ext/full_type_name.rb0000644000004100000410000000111114524576001022550 0ustar www-datawww-data# frozen_string_literal: true module GirFFI module InfoExt # Extension module provinding a #full_name method suitable for # callbacks, constants and registered types. Signals and vfuncs need a # different implementation. # module FullTypeName def full_name "#{safe_namespace}::#{safe_name}" end end end end GObjectIntrospection::ICallbackInfo.include GirFFI::InfoExt::FullTypeName GObjectIntrospection::IConstantInfo.include GirFFI::InfoExt::FullTypeName GObjectIntrospection::IRegisteredTypeInfo.include GirFFI::InfoExt::FullTypeName gir_ffi-0.16.1/lib/gir_ffi/info_ext/i_property_info.rb0000644000004100000410000000056414524576001022767 0ustar www-datawww-data# frozen_string_literal: true module GirFFI module InfoExt # Extensions for GObjectIntrospection::IPropertyInfo needed by GirFFI module IPropertyInfo def getter_name name.tr("-", "_") end def setter_name "#{getter_name}=" end end end end GObjectIntrospection::IPropertyInfo.include GirFFI::InfoExt::IPropertyInfo gir_ffi-0.16.1/lib/gir_ffi/info_ext/safe_function_name.rb0000644000004100000410000000056014524576001023377 0ustar www-datawww-data# frozen_string_literal: true module GirFFI module InfoExt # Extension module provinding a #safe_name method suitable for functions. module SafeFunctionName def safe_name name = self.name return "_" if name.empty? name end end end end GObjectIntrospection::IFunctionInfo.include GirFFI::InfoExt::SafeFunctionName gir_ffi-0.16.1/lib/gir_ffi/info_ext/i_value_info.rb0000644000004100000410000000106514524576001022214 0ustar www-datawww-data# frozen_string_literal: true module GirFFI module InfoExt # Extensions for GObjectIntrospection::IValueInfo needed by GirFFI module IValueInfo def constant_name upcased_name = name.upcase if /^[0-9]/.match?(upcased_name) "VALUE_#{upcased_name}" else upcased_name end end def to_callback_ffi_type return :pointer if direction != :in argument_type.to_callback_ffi_type end end end end GObjectIntrospection::IValueInfo.include GirFFI::InfoExt::IValueInfo gir_ffi-0.16.1/lib/gir_ffi/info_ext/i_vfunc_info.rb0000644000004100000410000000133314524576001022217 0ustar www-datawww-data# frozen_string_literal: true module GirFFI module InfoExt # Extensions for GObjectIntrospection::IVFuncInfo needed by GirFFI # TODO: Merge implementation with ICallbackInfo and ISignalInfo extensions. module IVFuncInfo def argument_ffi_types args.map(&:to_callback_ffi_type).tap do |types| types << :pointer if throws? end end def return_ffi_type return_type.to_callback_ffi_type end def invoker_name invoker&.name end def has_invoker? invoker end def full_name "#{container.full_name}::#{safe_name}" end end end end GObjectIntrospection::IVFuncInfo.include GirFFI::InfoExt::IVFuncInfo gir_ffi-0.16.1/lib/gir_ffi/user_defined_property_info.rb0000644000004100000410000000667414524576001023370 0ustar www-datawww-data# frozen_string_literal: true module GirFFI # Represents a property of a user defined type. Wraps a GParamSpec with # useful helper methods for building property accessors etc. class UserDefinedPropertyInfo # Type info for user-defined property class UserDefinedTypeInfo include InfoExt::ITypeInfo def initialize(param_spec) @param_spec = param_spec end # TODO: Unify with InfoExt::ITypeInfo.flattened_tag_to_gtype_map G_TYPE_TAG_MAP = { GObject::TYPE_BOOLEAN => :gboolean, GObject::TYPE_CHAR => :gint8, GObject::TYPE_UCHAR => :guint8, GObject::TYPE_FLOAT => :gfloat, GObject::TYPE_DOUBLE => :gdouble, GObject::TYPE_INT => :gint, GObject::TYPE_UINT => :guint, GObject::TYPE_LONG => :glong, GObject::TYPE_ULONG => :gulong, GObject::TYPE_INT64 => :gint64, GObject::TYPE_UINT64 => :guint64, GObject::TYPE_ENUM => :interface, GObject::TYPE_FLAGS => :interface, GObject::TYPE_STRING => :utf8, GObject::TYPE_BOXED => :interface, GObject::TYPE_OBJECT => :interface }.freeze def tag @tag ||= G_TYPE_TAG_MAP.fetch(fundamental_value_type) end # TODO: Unify with InfoExt::ITypeInfo.flattened_tag_to_gtype_map G_TYPE_POINTER_MAP = { GObject::TYPE_BOOLEAN => false, GObject::TYPE_CHAR => false, GObject::TYPE_UCHAR => false, GObject::TYPE_FLOAT => false, GObject::TYPE_DOUBLE => false, GObject::TYPE_INT => false, GObject::TYPE_UINT => false, GObject::TYPE_LONG => false, GObject::TYPE_ULONG => false, GObject::TYPE_INT64 => false, GObject::TYPE_UINT64 => false, GObject::TYPE_ENUM => false, GObject::TYPE_FLAGS => false, GObject::TYPE_STRING => true, GObject::TYPE_BOXED => true, GObject::TYPE_OBJECT => true }.freeze def pointer? G_TYPE_POINTER_MAP.fetch(fundamental_value_type) end G_TYPE_INTERFACE_TAG_MAP = { GObject::TYPE_ENUM => :enum, GObject::TYPE_FLAGS => :flags, GObject::TYPE_BOXED => :struct, GObject::TYPE_OBJECT => :object }.freeze def interface_type G_TYPE_INTERFACE_TAG_MAP.fetch(fundamental_value_type) if interface? end def hidden_struct_type? false end def interface_class @interface_class ||= Builder.build_by_gtype(value_type) if interface? end def interface_class_name interface_class.name if interface? end def ffi_type GirFFI::TypeMap.map_basic_type(tag) end private def value_type @param_spec.value_type end def fundamental_value_type @fundamental_value_type ||= GObject.type_fundamental value_type end def interface? tag == :interface end end def initialize(param_spec, container, offset) @param_spec = param_spec @container = container @offset = offset end attr_reader :container, :offset, :param_spec def name @param_spec.accessor_name end def field_type @field_type ||= UserDefinedTypeInfo.new @param_spec end def related_array_length_field nil end def writable? param_spec.flags[:writable] end def ffi_type field_type.ffi_type end def field_symbol name.to_sym end end end gir_ffi-0.16.1/lib/gir_ffi/callback_base.rb0000644000004100000410000000413614524576001020472 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/type_base" require "set" module GirFFI # Base module for callbacks and vfuncs. # NOTE: Another option would be to derive this class from FFI::Function, # allowing a more natural implementation of from_native, to_native and wrap. class CallbackBase < Proc extend TypeBase extend FFI::DataConverter def self.native_type FFI::Type::POINTER end # TODO: Return instance of this class def self.from_native(value, _context) return nil if !value || value.null? FFI::Function.new(gir_ffi_builder.return_ffi_type, gir_ffi_builder.argument_ffi_types, value) end def self.to_native(value, _context) case value when CallbackBase value.to_native when FFI::Function value end end def self.wrap(ptr) from_native ptr, nil end CALLBACKS = Set.new def self.store_callback(prc) CALLBACKS.add prc end def self.drop_callback(prc) CALLBACKS.delete prc end # Create Callback from a Proc. Makes sure arguments are properly wrapped, # and the callback is stored to prevent garbage collection. def self.from(prc) wrap_proc(prc).tap do |cb| store_callback cb end end def self.wrap_proc(prc) return unless prc new do |*args| call_with_argument_mapping(prc, *args) rescue StandardError => e GLib::MainLoop.handle_exception e end end def self.to_ffi_type self end def to_native @to_native ||= begin builder = self.class.gir_ffi_builder FFI::Function.new(builder.return_ffi_type, builder.argument_ffi_types, self) end end def to_ptr to_native.to_ptr end def self.copy_value_to_pointer(value, pointer, offset = 0) pointer.put_pointer offset, to_native(value, nil) end def self.get_value_from_pointer(pointer, offset) from_native pointer.get_pointer(offset), nil end end end gir_ffi-0.16.1/lib/gir_ffi/union_base.rb0000644000004100000410000000026714524576001020067 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/boxed_base" module GirFFI # Base class for generated classes representing GLib unions. class UnionBase < StructLikeBase end end gir_ffi-0.16.1/lib/gir_ffi/signal_not_found_error.rb0000644000004100000410000000053614524576001022505 0ustar www-datawww-data# frozen_string_literal: true module GirFFI # Exception class to be raised when a signal is not found. class SignalNotFoundError < RuntimeError attr_reader :signal_name def initialize(signal_name, klass) @signal_name = signal_name @klass = klass super "Signal '#{signal_name}' not found in #{klass}" end end end gir_ffi-0.16.1/lib/gir_ffi/lib_c.rb0000644000004100000410000000041114524576001017004 0ustar www-datawww-data# frozen_string_literal: true require "ffi" module GirFFI # Library of libc functions. module LibC extend FFI::Library ffi_lib FFI::Library::LIBC attach_function :malloc, [:size_t], :pointer attach_function :free, [:pointer], :void end end gir_ffi-0.16.1/lib/gir_ffi/boxed_base.rb0000644000004100000410000000132614524576001020035 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/class_base" module GirFFI # Base class for generated classes representing boxed types. class BoxedBase < StructLikeBase def self.make_finalizer(struct) proc { finalize(struct) } end def self.copy(val) ptr = GObject.boxed_copy(gtype, val) wrap(ptr) end class << self protected def finalize(struct) struct.owned? or return struct.owned = nil GObject.boxed_free gtype, struct.to_ptr end end private def store_pointer(*) super make_finalizer end def make_finalizer ObjectSpace.define_finalizer self, self.class.make_finalizer(struct) end end end gir_ffi-0.16.1/lib/gir_ffi/builders/0000755000004100000410000000000014524576001017224 5ustar www-datawww-datagir_ffi-0.16.1/lib/gir_ffi/builders/base_method_builder.rb0000644000004100000410000000555214524576001023540 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/builders/argument_builder" require "gir_ffi/builders/argument_builder_collection" require "gir_ffi/builders/method_template" require "gir_ffi/builders/null_argument_builder" require "gir_ffi/error_argument_info" require "gir_ffi/return_value_info" require "gir_ffi/variable_name_generator" module GirFFI module Builders # Base class for method definition builders. class BaseMethodBuilder def initialize(info, return_value_builder_class, receiver_info: nil, argument_builder_class: ArgumentBuilder) @info = info @return_value_builder_class = return_value_builder_class @argument_builder_class = argument_builder_class @receiver_info = receiver_info end def method_definition template.method_definition end # Methods used by MethodTemplate def invocation "#{lib_name}.#{@info.symbol} #{function_call_arguments.join(", ")}".strip end def method_arguments argument_builder_collection.method_argument_names end def preparation [] end private def variable_generator @variable_generator ||= VariableNameGenerator.new end def template @template ||= MethodTemplate.new(self, argument_builder_collection) end # Methods used for setting up the builders def argument_builders @argument_builders ||= @info.args.map { |arg| make_argument_builder arg } end def return_value_info @return_value_info ||= ReturnValueInfo.new(@info.return_type, @info.caller_owns, @info.skip_return?) end def return_value_builder @return_value_builder ||= @return_value_builder_class.new(variable_generator, return_value_info) end def receiver_builder @receiver_builder ||= @receiver_info ? make_argument_builder(@receiver_info) : nil end def argument_builder_collection @argument_builder_collection ||= ArgumentBuilderCollection.new(return_value_builder, argument_builders, error_argument_builder: error_argument, receiver_builder: receiver_builder) end def error_argument @error_argument ||= if @info.can_throw_gerror? make_argument_builder ErrorArgumentInfo.new else NullArgumentBuilder.new end end def lib_name "#{@info.safe_namespace}::Lib" end def make_argument_builder(argument_info) @argument_builder_class.new variable_generator, argument_info end end end end gir_ffi-0.16.1/lib/gir_ffi/builders/vfunc_argument_builder.rb0000644000004100000410000000164014524576001024303 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/builders/callback_argument_builder" module GirFFI module Builders # Convertor for arguments for vfuncs. Used when building the # argument mapper for vfuncs. class VFuncArgumentBuilder < CallbackArgumentBuilder def pre_conversion if ingoing_ref_needed? super + ["#{pre_converted_name}&.ref"] else super end end def post_conversion if outgoing_ref_needed? ["#{result_name}.ref"] + super else super end end private def ingoing_ref_needed? direction == :in && ownership_transfer == :nothing && specialized_type_tag == :object end def outgoing_ref_needed? direction == :out && ownership_transfer == :everything && specialized_type_tag == :object end end end end gir_ffi-0.16.1/lib/gir_ffi/builders/argument_builder.rb0000644000004100000410000001525514524576001023111 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/builders/base_argument_builder" require "gir_ffi/builders/closure_to_pointer_convertor" require "gir_ffi/builders/full_c_to_ruby_convertor" require "gir_ffi/builders/ruby_to_c_convertor" require "gir_ffi/builders/pointer_value_convertor" require "gir_ffi/builders/null_convertor" module GirFFI module Builders # Implements building pre- and post-processing statements for arguments. class ArgumentBuilder < BaseArgumentBuilder def method_argument_name name if has_input_value? && !helper_argument? end def block_argument? specialized_type_tag == :callback end def allow_none? arginfo.may_be_null? end def post_converted_name @post_converted_name ||= if has_post_conversion? new_variable else call_argument_name end end def return_value_name post_converted_name if has_output_value? && !array_length_parameter? end def capture_variable_name nil end def pre_conversion case direction when :in pre_conversion_in when :inout pre_conversion_inout when :out pre_conversion_out when :error pre_conversion_error end end def post_conversion if direction == :error ["GirFFI::ArgHelper.check_error(#{call_argument_name})"] elsif has_post_conversion? value = output_value ["#{post_converted_name} = #{value}"] else [] end end private def pre_conversion_in pr = [] pr << fixed_array_size_check if needs_size_check? pr << array_length_assignment if array_length_parameter? pr << "#{call_argument_name} = #{ingoing_convertor.conversion}" pr end def pre_conversion_inout pr = [] pr << fixed_array_size_check if needs_size_check? pr << array_length_assignment if array_length_parameter? pr << out_parameter_preparation pr << ingoing_value_storage pr end def pre_conversion_out [out_parameter_preparation] end def pre_conversion_error ["#{call_argument_name} = FFI::MemoryPointer.new(:pointer).write_pointer nil"] end def ingoing_value_storage PointerValueConvertor.new(type_spec) .value_to_pointer(call_argument_name, ingoing_convertor.conversion) end def has_post_conversion? has_output_value? && (!caller_allocated_object? || gvalue?) end def output_value return "#{call_argument_name}.get_value" if caller_allocated_object? && gvalue? base = pointer_to_value_method_call call_argument_name, type_spec if needs_out_conversion? outgoing_convertor(base).conversion elsif allocated_by_them? && specialized_type_tag != :void pointer_to_value_method_call base, sub_type_spec else base end end def outgoing_convertor(base) FullCToRubyConvertor.new(type_info, base, length_argument_name, ownership_transfer: arginfo.ownership_transfer) end def sub_type_spec type_spec[1] end def pointer_to_value_method_call(ptr_exp, spec) PointerValueConvertor.new(spec).pointer_to_value(ptr_exp) end def needs_out_conversion? type_info.needs_c_to_ruby_conversion_for_functions? end def gvalue? type_info.gvalue? end # Check if an out argument needs to be allocated by them, the callee. Since # caller_allocates is false by default, we must also check that the type # is a pointer. For example, an out parameter of type gint8* will always # be allocated by the caller (that's us). def allocated_by_them? !arginfo.caller_allocates? && type_info.pointer? end def length_argument_name length_arg&.post_converted_name end def needs_size_check? specialized_type_tag == :c && type_info.array_fixed_size > -1 end def fixed_array_size_check size = type_info.array_fixed_size "GirFFI::ArgHelper.check_fixed_array_size #{size}, #{name}, \"#{name}\"" end def skipped_in? arginfo.skip? end def skipped_out? arginfo.skip? || array_arg && array_arg.specialized_type_tag == :strv end def has_output_value? (direction == :inout || direction == :out) && !skipped_out? end def has_input_value? has_ingoing_component? && !skipped_in? end def has_ingoing_component? (direction == :inout || direction == :in) end def array_length_assignment arrname = array_arg.name "#{name} = #{arrname}.nil? ? 0 : #{arrname}.length" end def out_parameter_preparation value = if caller_allocated_object? if specialized_type_tag == :array "#{argument_class_name}.new #{type_info.element_type.inspect}" else "#{argument_class_name}.new" end else ffi_type_spec = TypeMap.type_specification_to_ffi_type type_spec "FFI::MemoryPointer.new #{ffi_type_spec.inspect}" end "#{call_argument_name} = #{value}" end def type_spec type_info.tag_or_class end def caller_allocated_object? [:struct, :array].include?(specialized_type_tag) && arginfo.caller_allocates? end DESTROY_NOTIFIER = "GLib::DestroyNotify.default" def ingoing_convertor if skipped_in? NullConvertor.new("0") elsif destroy_notifier? NullConvertor.new(DESTROY_NOTIFIER) elsif user_data? ClosureToPointerConvertor.new(callback_argument_name) elsif needs_ruby_to_c_conversion? RubyToCConvertor.new(type_info, pre_convertor_argument, ownership_transfer: ownership_transfer) else NullConvertor.new(pre_convertor_argument) end end def pre_convertor_argument if ownership_transfer == :everything && specialized_type_tag == :object "#{name} && #{name}.ref" else name end end def needs_ruby_to_c_conversion? type_info.needs_ruby_to_c_conversion_for_functions? end def callback_argument_name related_callback_builder.call_argument_name end end end end gir_ffi-0.16.1/lib/gir_ffi/builders/flags_builder.rb0000644000004100000410000000135614524576001022360 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/builders/enum_builder" require "gir_ffi/flags_base" module GirFFI module Builders # Implements the creation of a flags type. The type will be # attached to the appropriate namespace module, and will be defined # as a bit_mask for FFI. class FlagsBuilder < EnumBuilder def setup_ffi_type optionally_define_constant klass, :BitMask do lib.bit_mask(enum_sym, value_spec) end end def value_spec info.values.map do |vinfo| val = GirFFI::ArgHelper.cast_uint32_to_int32(vinfo.value) { vinfo.name.to_sym => val } end.reduce(:merge) end def superclass FlagsBase end end end end gir_ffi-0.16.1/lib/gir_ffi/builders/closure_return_value_builder.rb0000644000004100000410000000062114524576001025525 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/builders/callback_return_value_builder" module GirFFI module Builders # Implements building post-processing statements for return values of # closures. class ClosureReturnValueBuilder < CallbackReturnValueBuilder def needs_ruby_to_c_conversion? type_info.needs_ruby_to_c_conversion_for_closures? end end end end gir_ffi-0.16.1/lib/gir_ffi/builders/closure_argument_builder.rb0000644000004100000410000000065114524576001024637 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/builders/callback_argument_builder" module GirFFI module Builders # Convertor for arguments for RubyClosure objects. Used when building the # marshaller for signal handler closures. class ClosureArgumentBuilder < CallbackArgumentBuilder def needs_c_to_ruby_conversion? type_info.needs_c_to_ruby_conversion_for_closures? end end end end gir_ffi-0.16.1/lib/gir_ffi/builders/registered_type_builder.rb0000644000004100000410000000611314524576001024456 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/builders/base_type_builder" require "gir_ffi/method_stubber" require "gir_ffi/builders/function_builder" require "gir_ffi/builders/constructor_builder" require "gir_ffi/builders/initializer_builder" module GirFFI module Builders # Base class for type builders building types specified by subtypes # of IRegisteredTypeInfo. These are types whose C representation is # complex, i.e., a struct or a union. class RegisteredTypeBuilder < BaseTypeBuilder def setup_method(method) method_info = info.find_method method return unless method_info remove_old_method method_info, meta_class attach_and_define_method method_info end def setup_instance_method(method) method_info = info.find_instance_method method return unless method_info remove_old_method method_info, build_class attach_and_define_method method_info end def target_gtype info.g_type end private def meta_class (class << build_class; self; end) end def attach_and_define_method(method_info) attach_method method_info if method_info.constructor? define_construction_methods method_info else define_method method_info end method_info.safe_name end def define_method(method_info) method_definition = FunctionBuilder.new(method_info).method_definition build_class.class_eval(method_definition, __FILE__, __LINE__) end def define_construction_methods(method_info) initializer_builder = InitializerBuilder.new(method_info) initializer_name = initializer_builder.method_name.to_sym unless build_class.private_instance_methods(false).include? initializer_name build_class.class_eval initializer_builder.method_definition, __FILE__, __LINE__ end constructor_definition = ConstructorBuilder.new(method_info).method_definition build_class.class_eval(constructor_definition, __FILE__, __LINE__) end def remove_old_method(method_info, modul) method = method_info.safe_name modul.class_eval do remove_method method if method_defined? method end end def attach_method(method_info) Builder.attach_ffi_function lib, method_info end def stub_methods info.get_methods.each do |minfo| klass.class_eval MethodStubber.new(minfo).method_stub, __FILE__, __LINE__ alias_accessors(minfo) if minfo.method? end end def setup_constants klass.const_set :G_TYPE, target_gtype super end def parent_info nil end def fields info.fields end def alias_accessors(minfo) if minfo.name =~ /^get_(.*)/ klass.send :alias_method, Regexp.last_match(1), minfo.name elsif minfo.n_args == 1 && minfo.name =~ /^set_(.*)/ klass.send :alias_method, "#{Regexp.last_match(1)}=", minfo.name end end end end end gir_ffi-0.16.1/lib/gir_ffi/builders/user_defined_builder.rb0000644000004100000410000001336614524576001023724 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/builders/object_builder" require "gir_ffi/g_type" module GirFFI module Builders # Implements the creation of GObject subclasses from Ruby. class UserDefinedBuilder < ObjectBuilder def initialize(info) @info = info end def setup_class check_ancestry setup_layout register_type setup_constants setup_property_accessors setup_initializer TypeBuilder::CACHE[@gtype] = klass end def target_gtype @gtype ||= klass.gtype end private def check_ancestry unless klass < GirFFI::ObjectBase raise ArgumentError, "#{klass} is not a GObject class" end end def register_type @gtype = GObject.type_register_static(parent_gtype.to_i, info.g_name, gobject_type_info, 0) included_interfaces.each do |interface| ifinfo = gobject_interface_info interface GObject.type_add_interface_static @gtype, interface.gtype, ifinfo end end def parent_info @info.parent end def parent_gtype @info.parent_gtype end def interface_gtypes included_interfaces.map { |interface| GType.new(interface.gtype) } end def included_interfaces klass.included_interfaces end def klass @klass ||= @info.described_class end def gobject_type_info GObject::TypeInfo.new.tap do |type_info| type_info.class_size = class_size type_info.instance_size = instance_size type_info.class_init = class_init_proc end end def gobject_interface_info(interface) GObject::InterfaceInfo.new.tap do |interface_info| interface_info.interface_init = interface_init_proc(interface) end end def class_init_proc proc do |type_class, _data| class_struct_ptr = type_class.to_ptr setup_properties class_struct_ptr setup_vfuncs class_struct_ptr end end def interface_init_proc(interface) proc do |type_interface, _data| interface_struct_ptr = type_interface.to_ptr setup_interface_vfuncs interface, interface_struct_ptr end end def instance_size if property_fields.any? last_property = property_fields.last size = last_property.offset type_size = FFI.type_size(last_property.ffi_type) size += [type_size, field_alignment].max else size = parent_gtype.instance_size end size end def class_size parent_gtype.class_size + interface_gtypes.sum(&:class_size) end def setup_properties(class_struct_ptr) class_struct = GObject::ObjectClass.wrap class_struct_ptr class_struct.struct[:get_property] = property_getter_func class_struct.struct[:set_property] = property_setter_func property_fields.each_with_index do |property, index| class_struct.install_property index + 1, property.param_spec end end def property_getter_func getter = proc do |object, _property_id, value, pspec| value.set_value object.send(pspec.accessor_name) end GObject::ObjectGetPropertyFunc.from getter end def property_setter_func setter = proc do |object, _property_id, value, pspec| object.send("#{pspec.accessor_name}=", value.get_value) end GObject::ObjectSetPropertyFunc.from setter end def setup_vfuncs(class_struct_ptr) super_class_struct = superclass.gir_ffi_builder.class_struct_class.wrap(class_struct_ptr) info.vfunc_implementations.each do |impl| setup_vfunc parent_info, super_class_struct, impl end end def setup_interface_vfuncs(interface, interface_struct_ptr) interface_builder = interface.gir_ffi_builder interface_struct = interface_builder.interface_struct.wrap(interface_struct_ptr) interface_info = interface_builder.info info.vfunc_implementations.each do |impl| setup_vfunc interface_info, interface_struct, impl end end def setup_vfunc(ancestor_info, ancestor_struct, impl) vfunc_name = impl.name vfunc_info = ancestor_info.find_vfunc vfunc_name.to_s return unless vfunc_info vfunc_class = VFuncBuilder.new(vfunc_info).build_class ancestor_struct.struct[vfunc_name] = vfunc_class.from(impl.implementation) end def properties @properties ||= info.properties end def layout_specification parent_spec = [:parent, superclass::Struct] fields_spec = property_fields.flat_map do |property_info| [property_info.field_symbol, property_info.ffi_type, property_info.offset] end parent_spec + fields_spec end def field_alignment @field_alignment ||= superclass::Struct.alignment end def setup_property_accessors property_fields.each do |field_info| FieldBuilder.new(field_info, klass).build end end def property_fields @property_fields ||= begin offset = parent_gtype.instance_size properties.map do |param_spec| field_info = UserDefinedPropertyInfo.new(param_spec, info, offset) type_size = FFI.type_size(field_info.ffi_type) offset += [type_size, field_alignment].max field_info end end end def method_introspection_data(_method) nil end end end end gir_ffi-0.16.1/lib/gir_ffi/builders/object_builder.rb0000644000004100000410000001043614524576001022531 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/builders/registered_type_builder" require "gir_ffi/builders/with_layout" require "gir_ffi/builders/property_builder" require "gir_ffi/object_base" require "gir_ffi/struct" module GirFFI module Builders # Implements the creation of a class representing a GObject Object. class ObjectBuilder < RegisteredTypeBuilder include WithLayout # Dummy builder for the ObjectBase class class ObjectBaseBuilder def build_class ObjectBase end def class_struct_class GObject::TypeClass end def ancestor_infos [] end end def find_signal(signal_name) seek_in_ancestor_infos { |info| info.find_signal signal_name } end def find_property(property_name) seek_in_ancestor_infos { |info| info.find_property property_name } end def class_struct_class @class_struct_class ||= begin parent_struct = parent_builder.class_struct_class if class_struct_info StructBuilder.new(class_struct_info, superclass: parent_struct).build_class else parent_struct end end end def ancestor_infos @ancestor_infos ||= [info] + info.interfaces + parent_ancestor_infos end def eligible_properties info.properties.reject do |pinfo| info.find_instance_method("get_#{pinfo.name}") end end private def setup_class setup_layout setup_constants stub_methods setup_property_accessors setup_vfunc_invokers setup_interfaces setup_initializer end def class_struct_info @class_struct_info ||= info.class_struct end # FIXME: Private method only used in subclass def layout_superclass GirFFI::Struct end def parent_info info.parent end def superclass @superclass ||= parent_builder.build_class end def parent_builder @parent_builder ||= if parent_info Builders::TypeBuilder.builder_for(parent_info) else ObjectBaseBuilder.new end end def parent_ancestor_infos @parent_ancestor_infos ||= parent_builder.ancestor_infos end def setup_property_accessors eligible_properties.each do |prop| PropertyBuilder.new(prop).build end end # TODO: Guard agains accidental invocation of undefined vfuncs. # TODO: Create object responsible for creating these invokers def setup_vfunc_invokers info.vfuncs.each do |vfinfo| define_vfunc_invoker vfinfo.name, vfinfo.invoker_name if vfinfo.has_invoker? end end def define_vfunc_invoker(vfunc_name, invoker_name) return if vfunc_name == invoker_name klass.class_eval <<-DEF, __FILE__, __LINE__ + 1 def #{vfunc_name} *args, &block # def foo *args, &block #{invoker_name}(*args, &block) # foo_invoker *args, &block end # end DEF end def setup_initializer return if info.find_method "new" if info.abstract? define_abstract_initializer else define_default_initializer end end def define_abstract_initializer klass.class_eval <<-RUBY, __FILE__, __LINE__ + 1 def initialize(*) raise NoMethodError end RUBY end def define_default_initializer klass.class_eval <<-RUBY, __FILE__, __LINE__ + 1 def initialize(properties = {}) base_initialize(properties) end RUBY end def setup_interfaces interfaces.each do |iface| klass.send :include, iface end end def interfaces info.interfaces.map do |ifinfo| GirFFI::Builder.build_class ifinfo end end def seek_in_ancestor_infos ancestor_infos.each do |info| item = yield info return item if item end nil end end end end gir_ffi-0.16.1/lib/gir_ffi/builders/method_template.rb0000644000004100000410000000426214524576001022730 0ustar www-datawww-data# frozen_string_literal: true module GirFFI module Builders # Encapsulates the general structure of generated methods, consisting of a # preparation phase where arguments are converted to the form needed by the # main call of the method, the main call itself, a post-processing phase # where the return values and any 'out' arguments of the main call are # converted into a form suitable for returning, and finally the returning # of said values to the caller. # # The different method builders collaborate with MethodTemplate to build # the desired method. class MethodTemplate def initialize(builder, argument_builder_collection) @builder = builder @argument_builder_collection = argument_builder_collection end def method_definition code = +"def #{qualified_method_name}" code << "(#{method_arguments.join(", ")})" if method_arguments.any? method_lines.each { |line| code << "\n #{line}" } code << "\nend\n" end private def qualified_method_name "#{@builder.singleton_method? ? "self." : ""}#{@builder.method_name}" end def method_arguments @builder.method_arguments end def method_lines method_preparation + parameter_preparation + invocation + return_value_conversion + result end def method_preparation @builder.preparation end def parameter_preparation @argument_builder_collection.parameter_preparation end def invocation if result_name_list.empty? plain_invocation else capturing_invocation end end def return_value_conversion @argument_builder_collection.return_value_conversion end def result @builder.result end def result_name_list @result_name_list ||= @argument_builder_collection.capture_variable_names.join(", ") end def capturing_invocation ["#{result_name_list} = #{@builder.invocation}"] end def plain_invocation [@builder.invocation].compact end end end end gir_ffi-0.16.1/lib/gir_ffi/builders/interface_builder.rb0000644000004100000410000000151314524576001023217 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/builders/registered_type_builder" require "gir_ffi/interface_base" module GirFFI module Builders # Implements the creation of a module representing an Interface. class InterfaceBuilder < RegisteredTypeBuilder def interface_struct @interface_struct ||= StructBuilder.new(iface_struct_info, superclass: GObject::TypeInterface).build_class end private def klass @klass ||= get_or_define_module namespace_module, @classname end # FIXME: The word 'class' is not really correct. def setup_class klass.extend InterfaceBase setup_constants stub_methods end def iface_struct_info @iface_struct_info ||= info.iface_struct end end end end gir_ffi-0.16.1/lib/gir_ffi/builders/null_convertor.rb0000644000004100000410000000044014524576001022622 0ustar www-datawww-data# frozen_string_literal: true module GirFFI module Builders # Argument convertor that does nothing class NullConvertor def initialize(argument_name) @argument_name = argument_name end def conversion @argument_name end end end end gir_ffi-0.16.1/lib/gir_ffi/builders/mapping_method_builder.rb0000644000004100000410000000323314524576001024253 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/variable_name_generator" require "gir_ffi/builders/callback_argument_builder" require "gir_ffi/builders/vfunc_argument_builder" require "gir_ffi/builders/callback_return_value_builder" require "gir_ffi/builders/argument_builder_collection" require "gir_ffi/builders/base_method_builder" module GirFFI module Builders # Implements the creation mapping method for a callback or vfunc # handler. This method converts arguments from C to Ruby, and the # result from Ruby to C. class MappingMethodBuilder < BaseMethodBuilder def self.for_callback(info) new nil, info, CallbackArgumentBuilder end def self.for_vfunc(receiver_info, info) new receiver_info, info, VFuncArgumentBuilder end def initialize(receiver_info, info, builder_class) super(info, CallbackReturnValueBuilder, receiver_info: receiver_info, argument_builder_class: builder_class) end ## Methods used by MethodTemplate def method_name "call_with_argument_mapping" end def method_arguments @method_arguments ||= argument_builder_collection.method_argument_names.dup.unshift("_proc") end def invocation "_proc.call(#{call_argument_list})" end def result if (name = argument_builder_collection.return_value_name) ["return #{name}"] else [] end end def singleton_method? true end private def call_argument_list argument_builder_collection.call_argument_names.join(", ") end end end end gir_ffi-0.16.1/lib/gir_ffi/builders/constant_builder.rb0000644000004100000410000000111714524576001023110 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/builders/base_type_builder" module GirFFI module Builders # Implements the creation of a constant. Though semantically not a # type, its build method is like that of the types, in that it is # triggered by a missing constant in the parent namespace. The # constant will be attached to the appropriate namespace module. class ConstantBuilder < BaseTypeBuilder def build_class @klass ||= optionally_define_constant namespace_module, @classname do info.value end end end end end gir_ffi-0.16.1/lib/gir_ffi/builders/closure_convertor.rb0000644000004100000410000000064214524576001023330 0ustar www-datawww-data# frozen_string_literal: true module GirFFI module Builders # Builder that generates code to convert closure arguments ('user data') # from C to Ruby. Used by argument builders. class ClosureConvertor def initialize(argument_name) @argument_name = argument_name end def conversion "GirFFI::ArgHelper::OBJECT_STORE.fetch(#{@argument_name})" end end end end gir_ffi-0.16.1/lib/gir_ffi/builders/full_c_to_ruby_convertor.rb0000644000004100000410000000072214524576001024662 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/builders/c_to_ruby_convertor" module GirFFI module Builders # Builder that generates code to convert values from C to Ruby, including # GValue unpacking. Used by argument builders. class FullCToRubyConvertor < CToRubyConvertor def conversion if @type_info.gvalue? "GObject::Value.wrap(#{@argument}).get_value" else super end end end end end gir_ffi-0.16.1/lib/gir_ffi/builders/enum_builder.rb0000644000004100000410000000327414524576001022231 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/builders/registered_type_builder" require "gir_ffi/enum_base" module GirFFI module Builders # Implements the creation of an enum or flags type. The type will be # attached to the appropriate namespace module, and will be defined # as an enum for FFI. class EnumBuilder < RegisteredTypeBuilder private def enum_sym @classname.to_sym end def value_spec value_infos.map do |vinfo| val = GirFFI::ArgHelper.cast_uint32_to_int32(vinfo.value) [vinfo.name.to_sym, val] end.flatten end def setup_class setup_ffi_type klass.extend superclass setup_constants setup_value_constants stub_methods setup_inspect end def klass @klass ||= get_or_define_module namespace_module, @classname end def setup_ffi_type optionally_define_constant klass, :Enum do lib.enum(enum_sym, value_spec) end end def setup_value_constants value_infos.each do |vinfo| optionally_define_constant klass, vinfo.constant_name do vinfo.value end end end def setup_inspect klass.instance_eval <<-RUBY, __FILE__, __LINE__ + 1 def self.inspect # def self.inspect "#{@namespace}::#{@classname}" # "GFoo::Bar" end # end RUBY end def already_set_up klass.respond_to? :gtype end def superclass EnumBase end def value_infos @value_infos ||= info.values end end end end gir_ffi-0.16.1/lib/gir_ffi/builders/union_builder.rb0000644000004100000410000000107214524576001022407 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/builders/registered_type_builder" require "gir_ffi/builders/struct_like" require "gir_ffi/union_base" require "gir_ffi/union" module GirFFI module Builders # Implements the creation of a class representing union type. The # class will have a nested GirFFI::Union class to represent its C union. class UnionBuilder < RegisteredTypeBuilder include StructLike def layout_superclass GirFFI::Union end private def superclass UnionBase end end end end gir_ffi-0.16.1/lib/gir_ffi/builders/field_builder.rb0000644000004100000410000001707314524576001022352 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/builders/argument_builder" require "gir_ffi/builders/base_argument_builder" require "gir_ffi/builders/null_argument_builder" require "gir_ffi/builders/pointer_value_convertor" require "gir_ffi/variable_name_generator" require "gir_ffi/field_argument_info" module GirFFI module Builders # Creates field getter and setter code for a given IFieldInfo. class FieldBuilder # Convertor for fields for field getters. Used when building getter # methods. class GetterArgumentBuilder < BaseArgumentBuilder attr_reader :array_length_idx def initialize(var_gen, field_argument_info, field_info, array_length_idx: -1) super(var_gen, field_argument_info) @field_info = field_info @length_arg = NullArgumentBuilder.new @array_length_idx = array_length_idx end def pre_conversion [ "#{field_ptr} = @struct.to_ptr", "#{bare_value} = #{pointer_to_value_conversion}" ] end def capture_variable_name nil end def post_converted_name @post_converted_name ||= if has_post_conversion? new_variable else bare_value end end def return_value_name post_converted_name end def post_conversion if has_post_conversion? ["#{post_converted_name} = #{post_convertor.conversion}"] else [] end end private def pointer_to_value_conversion PointerValueConvertor.new(field_type_tag) .pointer_to_value(field_ptr, field_offset) end def field_offset @field_info.offset end def field_ptr @field_ptr ||= @var_gen.new_var end def typed_ptr @typed_ptr ||= @var_gen.new_var end def bare_value @bare_value ||= @var_gen.new_var end def field_type_tag @field_type_tag ||= field_type.tag_or_class end def field_type @field_type ||= @field_info.field_type end def has_post_conversion? type_info.needs_c_to_ruby_conversion_for_functions? end def post_convertor @post_convertor ||= CToRubyConvertor.new(type_info, bare_value, length_arg.post_converted_name) end end # Class to represent argument info for the argument of a getter method. # Implements the necessary parts of IArgInfo's interface. class GetterArgumentInfo attr_reader :name, :argument_type def initialize(name, type) @name = name @argument_type = type end def closure -1 end def destroy -1 end def direction :out end def ownership_transfer :nothing end def caller_allocates? false end def skip? false end end # Builder for field getters # TODO: Derive from BaseMethodBuilder class GetterBuilder def initialize(info) @info = info end def method_definition template.method_definition end def singleton_method? false end def method_name @info.name end def method_arguments [] end def preparation [] end def invocation nil end def result [getter_argument_builder.return_value_name] end private def var_gen @var_gen ||= VariableNameGenerator.new end def template @template ||= MethodTemplate.new(self, argument_builders) end def argument_builders @argument_builders ||= ArgumentBuilderCollection.new( NullReturnValueBuilder.new, base_argument_builders) end def base_argument_builders if array_length_field [getter_argument_builder, length_argument_builder] else [getter_argument_builder] end end def getter_argument_builder @getter_argument_builder ||= GetterArgumentBuilder.new(var_gen, field_argument_info, @info, array_length_idx: array_length_field ? 1 : -1) end def length_argument_builder @length_argument_builder ||= GetterArgumentBuilder.new(var_gen, length_argument_info, array_length_field) end def array_length_field @info.related_array_length_field end def length_argument_info @length_argument_info ||= GetterArgumentInfo.new "length", array_length_field.field_type end def field_offset @info.offset end def field_type_tag @field_type_tag ||= field_type.tag_or_class.inspect end def field_type @field_type ||= @info.field_type end def field_argument_info @field_argument_info ||= GetterArgumentInfo.new "value", field_type end end attr_reader :info def initialize(field_info, container_class) @info = field_info @container_class = container_class end def build setup_getter setup_setter end def setup_getter return if container_defines_getter_method? return if hidden_struct_type? container_class.class_eval getter_def, __FILE__, __LINE__ end def container_defines_getter_method? container_info.find_instance_method info.name end def setup_setter return unless info.writable? return if hidden_struct_type? container_class.class_eval setter_def, __FILE__, __LINE__ end def getter_def getter_builder = GetterBuilder.new(info) getter_builder.method_definition end # TODO: Use MethodTemplate def setter_def builder = setter_builder field_ptr = builder.new_variable <<~CODE def #{info.name}= #{builder.method_argument_name} #{field_ptr} = @struct.to_ptr #{builder.pre_conversion.join("\n ")} #{value_storage(field_ptr, builder)} end CODE end private def value_storage(typed_ptr, builder) PointerValueConvertor.new(field_type_tag) .value_to_pointer(typed_ptr, builder.call_argument_name, info.offset) end def field_type_tag @field_type_tag ||= field_type.tag_or_class end attr_reader :container_class # TODO: Inject container_info on initialization def container_info @container_info ||= info.container end def field_type @field_type ||= @info.field_type end def field_argument_info @field_argument_info ||= FieldArgumentInfo.new "value", field_type end def setter_builder @setter_builder ||= ArgumentBuilder.new(VariableNameGenerator.new, field_argument_info) end def hidden_struct_type? field_type.hidden_struct_type? end end end end gir_ffi-0.16.1/lib/gir_ffi/builders/unintrospectable_builder.rb0000644000004100000410000000167514524576001024651 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/builders/object_builder" require "gir_ffi/unintrospectable_signal_info" module GirFFI module Builders # Implements the creation of a class representing an object type for # which no data is found in the GIR. Typically, these are created to # cast objects returned by a function that returns an interface. class UnintrospectableBuilder < ObjectBuilder def klass @klass ||= TypeBuilder::CACHE[target_gtype] ||= Class.new(superclass) end def setup_class setup_constants setup_layout setup_interfaces end def setup_instance_method(_method) false end def find_signal(signal_name) info = super return info if info signal_id = GObject.signal_lookup signal_name, target_gtype return if signal_id == 0 UnintrospectableSignalInfo.new(signal_id) end end end end gir_ffi-0.16.1/lib/gir_ffi/builders/c_to_ruby_convertor.rb0000644000004100000410000000353114524576001023641 0ustar www-datawww-data# frozen_string_literal: true module GirFFI module Builders # Builder that generates code to convert values from C to Ruby. Used by # argument builders. class CToRubyConvertor def initialize(type_info, argument, length_arg, ownership_transfer: nil) @type_info = type_info @argument = argument @length_arg = length_arg @ownership_transfer = ownership_transfer end def conversion case @type_info.flattened_tag when :utf8, :filename if @ownership_transfer == :everything "GirFFI::AllocationHelper.free_after #{@argument}, &:to_utf8" else "#{@argument}.to_utf8" end when :object base = "#{@type_info.argument_class_name}.wrap(#{conversion_argument_list})" @ownership_transfer == :nothing ? "#{base}.tap { |it| it && it.ref }" : base else "#{argument_class}.#{conversion_method}(#{conversion_argument_list})" end end private def conversion_method case @type_info.flattened_tag when :struct, :union case @ownership_transfer when :everything "wrap_own" when :nothing "wrap_copy" else "wrap" end else "wrap" end end def conversion_argument_list conversion_arguments.join(", ") end def conversion_arguments case @type_info.flattened_tag when :c [@type_info.element_type.inspect, array_size, @argument] else @type_info.extra_conversion_arguments.map(&:inspect).push(@argument) end end def array_size @length_arg || @type_info.array_fixed_size end def argument_class @type_info.argument_class_name end end end end gir_ffi-0.16.1/lib/gir_ffi/builders/initializer_return_value_builder.rb0000644000004100000410000000072214524576001026376 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/builders/base_return_value_builder" module GirFFI module Builders # Implements post-conversion for initializer functions class InitializerReturnValueBuilder < BaseReturnValueBuilder def post_conversion result = [] result << "store_pointer(#{capture_variable_name})" result << "@struct.owned = true" if specialized_type_tag == :struct result end end end end gir_ffi-0.16.1/lib/gir_ffi/builders/marshalling_method_builder.rb0000644000004100000410000000373314524576001025126 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/variable_name_generator" require "gir_ffi/builders/closure_argument_builder" require "gir_ffi/builders/closure_return_value_builder" require "gir_ffi/builders/argument_builder_collection" require "gir_ffi/builders/method_template" module GirFFI module Builders # Implements the creation mapping method for a signal # handler. This method converts arguments from C to Ruby, and the # result from Ruby to C. class MarshallingMethodBuilder < BaseMethodBuilder def self.for_signal(info) container_info = info.container container_type_info = ReceiverTypeInfo.new(container_info) receiver_info = ReceiverArgumentInfo.new(container_type_info) new receiver_info, info end def initialize(receiver_info, info) super(info, ClosureReturnValueBuilder, receiver_info: receiver_info, argument_builder_class: ClosureArgumentBuilder) end ## Methods used by MethodTemplate def method_name "marshaller" end def method_arguments %w[closure return_value param_values _invocation_hint _marshal_data] end def preparation if param_names.size == 1 ["#{param_names.first} = param_values.first.get_value_plain"] else ["#{param_names.join(", ")} = param_values.map(&:get_value_plain)"] end end def invocation "wrap(closure.to_ptr).invoke_block(#{call_argument_list})" end def result if (name = @argument_builder_collection.return_value_name) ["return_value.set_value #{name}"] else [] end end def singleton_method? true end private def call_argument_list @argument_builder_collection.call_argument_names.join(", ") end def param_names @param_names ||= @argument_builder_collection.method_argument_names end end end end gir_ffi-0.16.1/lib/gir_ffi/builders/function_builder.rb0000644000004100000410000000240714524576001023107 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/builders/return_value_builder" require "gir_ffi/builders/base_method_builder" module GirFFI module Builders # Implements the creation of a Ruby function definition out of a GIR # IFunctionInfo. class FunctionBuilder < BaseMethodBuilder def initialize(info) super(info, ReturnValueBuilder) end def method_name @info.safe_name end def result if argument_builder_collection.has_return_values? ["return #{argument_builder_collection.return_value_names.join(", ")}"] else [] end end def singleton_method? !@info.method? end def function_call_arguments ca = argument_builder_collection.call_argument_names.dup ca.unshift receiver_call_argument if @info.method? ca end private def receiver_call_argument container_type_info = ReceiverTypeInfo.new(container_info) if @info.instance_ownership_transfer == :everything && container_type_info.flattened_tag == :object "self.ref" else "self" end end def container_info @container_info ||= @info.container end end end end gir_ffi-0.16.1/lib/gir_ffi/builders/ruby_to_c_convertor.rb0000644000004100000410000000205614524576001023642 0ustar www-datawww-data# frozen_string_literal: true module GirFFI module Builders # Builder that generates code to convert values from Ruby to C. Used by # argument builders. class RubyToCConvertor def initialize(type_info, argument_name, ownership_transfer: nil) @type_info = type_info @argument_name = argument_name @ownership_transfer = ownership_transfer end def conversion args = conversion_arguments @argument_name "#{@type_info.argument_class_name}.#{conversion_method}(#{args})" end def conversion_arguments(name) @type_info.extra_conversion_arguments.map(&:inspect).push(name).join(", ") end private def conversion_method case @type_info.flattened_tag when :utf8 "from_utf8" when :struct, :c case @ownership_transfer when :everything "copy_from" else "from" end when :enum "to_int" else "from" end end end end end gir_ffi-0.16.1/lib/gir_ffi/builders/struct_like.rb0000644000004100000410000000075614524576001022111 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/builders/with_layout" module GirFFI module Builders # Implements base methods used by struct and union builders module StructLike include WithLayout def setup_class setup_layout setup_constants stub_methods setup_field_accessors end def setup_field_accessors fields.each do |finfo| FieldBuilder.new(finfo, klass).build end end end end end gir_ffi-0.16.1/lib/gir_ffi/builders/null_argument_builder.rb0000644000004100000410000000100714524576001024131 0ustar www-datawww-data# frozen_string_literal: true module GirFFI # Argument builder that does nothing. Implements the Null Object pattern. class NullArgumentBuilder def pre_conversion [] end def post_conversion [] end def array_length_idx -1 end def method_argument_name nil end def return_value_name nil end def call_argument_name nil end def capture_variable_name nil end def post_converted_name nil end end end gir_ffi-0.16.1/lib/gir_ffi/builders/unintrospectable_boxed_builder.rb0000644000004100000410000000123314524576001026020 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/builders/registered_type_builder" require "gir_ffi/builders/struct_like" module GirFFI module Builders # Implements the creation of a class representing a boxed type for # which no data is found in the GIR. class UnintrospectableBoxedBuilder < RegisteredTypeBuilder include StructLike def klass @klass ||= TypeBuilder::CACHE[target_gtype] ||= Class.new(superclass) end def setup_class setup_layout setup_constants end def superclass BoxedBase end def layout_superclass GirFFI::Struct end end end end gir_ffi-0.16.1/lib/gir_ffi/builders/return_value_builder.rb0000644000004100000410000000237014524576001023774 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/builders/base_return_value_builder" require "gir_ffi/builders/full_c_to_ruby_convertor" require "gir_ffi/builders/closure_convertor" module GirFFI module Builders # Implements building post-processing statements for return values. class ReturnValueBuilder < BaseReturnValueBuilder def post_conversion result = [] if has_post_conversion? result << "#{post_converted_name} = #{post_convertor.conversion}" end result end def has_post_conversion? user_data? || needs_c_to_ruby_conversion? end def needs_c_to_ruby_conversion? type_info.needs_c_to_ruby_conversion_for_functions? end private def post_convertor @post_convertor ||= if user_data? ClosureConvertor.new(capture_variable_name) else FullCToRubyConvertor.new(type_info, capture_variable_name, length_argument_name, ownership_transfer: arginfo.ownership_transfer) end end def length_argument_name length_arg&.post_converted_name end end end end gir_ffi-0.16.1/lib/gir_ffi/builders/argument_builder_collection.rb0000644000004100000410000001211014524576001025307 0ustar www-datawww-data# frozen_string_literal: true module GirFFI module Builders # Class representing the argument and return value builders for a method, # callback mapping function or marshaller. Implements collecting the # conversion code and parameter and variable names for use by function # builders. class ArgumentBuilderCollection attr_reader :return_value_builder def initialize(return_value_builder, argument_builders, receiver_builder: nil, error_argument_builder: nil) @receiver_builder = receiver_builder @error_argument_builder = error_argument_builder @base_argument_builders = argument_builders @return_value_builder = return_value_builder set_up_argument_relations end def parameter_preparation builders_for_pre_conversion.map(&:pre_conversion).flatten end def return_value_conversion builders_for_post_conversion.map(&:post_conversion).flatten end def capture_variable_names @capture_variable_names ||= all_builders.filter_map(&:capture_variable_name) end def call_argument_names @call_argument_names ||= argument_builders.filter_map(&:call_argument_name) end def method_argument_names @method_argument_names ||= begin base, block = split_off_block_argument args = base_argument_names(base) args << "&#{block.method_argument_name}" if block args end end def return_value_name return_value_builder.return_value_name end def return_value_names @return_value_names ||= all_builders.filter_map(&:return_value_name) end def has_return_values? return_value_names.any? end private def argument_builders @argument_builders ||= @base_argument_builders.dup.tap do |builders| builders.unshift @receiver_builder if @receiver_builder builders.push @error_argument_builder if @error_argument_builder end end def set_up_argument_relations set_up_user_data_relations set_up_destroy_notifier_relations set_up_length_argument_relations end def set_up_user_data_relations @base_argument_builders.each do |bldr| if (idx = bldr.closure_idx) >= 0 target_bldr = @base_argument_builders[idx] unless target_bldr.specialized_type_tag == :void target_bldr, bldr = bldr, target_bldr end target_bldr.mark_as_user_data bldr end end end def set_up_destroy_notifier_relations @base_argument_builders.each do |bldr| if (idx = bldr.destroy_idx) >= 0 target = @base_argument_builders[idx] if target.specialized_type_tag == :callback && bldr.specialized_type_tag == :callback target.mark_as_destroy_notifier bldr else warn "Not marking #{target.name} (#{target.specialized_type_tag})" \ " as destroy notifier for #{bldr.name} (#{bldr.specialized_type_tag})" end end end end def set_up_length_argument_relations all_builders.each do |bldr| idx = bldr.array_length_idx next if idx < 0 other = @base_argument_builders[idx] bldr.length_arg = other other.array_arg = bldr end end def all_builders @all_builders ||= [return_value_builder] + argument_builders end def builders_for_pre_conversion @builders_for_pre_conversion ||= sorted_base_argument_builders.dup.tap do |builders| builders.unshift @receiver_builder if @receiver_builder builders.push @error_argument_builder if @error_argument_builder end end def builders_for_post_conversion @builders_for_post_conversion ||= sorted_base_argument_builders.dup.tap do |builders| builders.unshift @receiver_builder if @receiver_builder builders.unshift @error_argument_builder if @error_argument_builder builders.push return_value_builder end end def sorted_base_argument_builders @sorted_base_argument_builders ||= @base_argument_builders .sort_by.with_index { |arg, i| [arg.array_length_idx, i] } end def split_off_block_argument builders_with_name = argument_builders.select(&:method_argument_name) blocks, base = builders_with_name.partition(&:block_argument?) case blocks.count when 1 return base, blocks.first else return builders_with_name, nil end end def base_argument_names(arguments) required_found = false arguments.reverse.filter_map do |it| name = it.method_argument_name if it.allow_none? && !required_found "#{name} = nil" else required_found = true name end end.reverse end end end end gir_ffi-0.16.1/lib/gir_ffi/builders/callback_argument_builder.rb0000644000004100000410000001206014524576001024714 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/builders/base_argument_builder" require "gir_ffi/builders/c_to_ruby_convertor" require "gir_ffi/builders/closure_convertor" require "gir_ffi/builders/null_convertor" require "gir_ffi/builders/pointer_value_convertor" module GirFFI module Builders # Convertor for arguments for ruby callbacks. Used when building the # argument mapper for callbacks. class CallbackArgumentBuilder < BaseArgumentBuilder def method_argument_name @method_argument_name ||= name || new_variable end def block_argument? false end # All arguments to the argument mapper must always be provided. They may # be nil, though. def allow_none? false end def pre_converted_name @pre_converted_name ||= new_variable end def out_parameter_name @out_parameter_name ||= if direction == :inout new_variable else pre_converted_name end end def call_argument_name pre_converted_name if [:in, :inout].include?(direction) && !array_arg end def capture_variable_name result_name if [:out, :inout].include?(direction) && !array_arg end def pre_conversion case direction when :in [ingoing_pre_conversion] when :out [out_parameter_preparation] when :inout [out_parameter_preparation, ingoing_pre_conversion] when :error [out_parameter_preparation, "begin"] end end def post_conversion case direction when :out, :inout [value_to_pointer_conversion] when :error [ "rescue => #{result_name}", value_to_pointer_conversion, "end" ] else [] end end private def result_name @result_name ||= new_variable end def pre_convertor_argument if direction == :inout pointer_to_value_conversion else method_argument_name end end def pointer_value_convertor @pointer_value_convertor ||= if allocated_by_us? PointerValueConvertor.new(type_spec[1]) else PointerValueConvertor.new(type_spec) end end def pointer_to_value_conversion pointer_value_convertor.pointer_to_value(out_parameter_name) end def value_to_pointer_conversion pointer_value_convertor.value_to_pointer(out_parameter_name, post_convertor.conversion) end def pre_convertor @pre_convertor ||= if user_data? ClosureConvertor.new(pre_convertor_argument) elsif needs_c_to_ruby_conversion? CToRubyConvertor.new(type_info, pre_convertor_argument, length_argument_name) else NullConvertor.new(pre_convertor_argument) end end def needs_c_to_ruby_conversion? type_info.needs_c_to_ruby_conversion_for_callbacks? end def ingoing_pre_conversion "#{pre_converted_name} = #{pre_convertor.conversion}" end def post_convertor @post_convertor ||= if type_info.needs_ruby_to_c_conversion_for_callbacks? RubyToCConvertor.new(type_info, post_convertor_argument) else NullConvertor.new(post_convertor_argument) end end def post_convertor_argument if array_arg "#{array_arg.capture_variable_name}.length" else result_name end end def out_parameter_preparation value = if allocated_by_us? ffi_type = TypeMap.type_specification_to_ffi_type type_spec.last "FFI::MemoryPointer.new(#{ffi_type.inspect})" \ ".tap { |ptr| #{method_argument_name}.put_pointer 0, ptr }" else method_argument_name end "#{out_parameter_name} = #{value}" end def type_spec type_info.tag_or_class end # Check if an out argument needs to be allocated by us, the callee. Since # caller_allocates is false by default, we must also check that the type # is a pointer. For example, an out parameter of type gint8* will always # be allocate by the caller. def allocated_by_us? direction == :out && !@arginfo.caller_allocates? && type_info.pointer? && ![:object, :zero_terminated].include?(specialized_type_tag) end def length_argument_name length_arg&.pre_converted_name end end end end gir_ffi-0.16.1/lib/gir_ffi/builders/null_class_builder.rb0000644000004100000410000000041014524576001023411 0ustar www-datawww-data# frozen_string_literal: true module GirFFI module Builders # Class builder that does nothing class NullClassBuilder def setup_method(_method) nil end def setup_instance_method(_method) nil end end end end gir_ffi-0.16.1/lib/gir_ffi/builders/null_return_value_builder.rb0000644000004100000410000000053014524576001025022 0ustar www-datawww-data# frozen_string_literal: true module GirFFI module Builders # Implements a blank return value matching ReturnValueBuilder's interface. class NullReturnValueBuilder def array_length_idx -1 end def capture_variable_name nil end def post_conversion [] end end end end gir_ffi-0.16.1/lib/gir_ffi/builders/initializer_builder.rb0000644000004100000410000000130214524576001023576 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/builders/initializer_return_value_builder" require "gir_ffi/builders/base_method_builder" module GirFFI module Builders # Implements the creation of a Ruby object initializer definition out of a # GIR IFunctionInfo. class InitializerBuilder < BaseMethodBuilder def initialize(info) super(info, InitializerReturnValueBuilder) end def singleton_method? false end def method_name @info.safe_name.sub(/^new/, "initialize") end def result [] end def function_call_arguments argument_builder_collection.call_argument_names end end end end gir_ffi-0.16.1/lib/gir_ffi/builders/base_type_builder.rb0000644000004100000410000000166314524576001023240 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/builder_helper" module GirFFI # Base class for type builders. class BaseTypeBuilder include BuilderHelper def initialize(info) @info = info @namespace = @info.namespace @classname = @info.safe_name end def build_class instantiate_class unless defined? @klass @klass end def instantiate_class setup_class unless already_set_up end attr_reader :info private def namespace_module @namespace_module ||= Builder.build_module @namespace end def lib @lib ||= namespace_module::Lib end def setup_constants optionally_define_constant(klass, :GIR_INFO) { info } klass.const_set :GIR_FFI_BUILDER, self end def already_set_up klass.const_defined? :GIR_FFI_BUILDER, false end def gir @gir ||= GObjectIntrospection::IRepository.default end end end gir_ffi-0.16.1/lib/gir_ffi/builders/vfunc_builder.rb0000644000004100000410000000304714524576001022404 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/return_value_info" require "gir_ffi/builders/base_type_builder" require "gir_ffi/builders/mapping_method_builder" require "gir_ffi/receiver_type_info" require "gir_ffi/receiver_argument_info" require "gir_ffi/callback_base" module GirFFI module Builders # Implements the creation of a class representing the implementation of a # vfunc. This class will be able to turn a proc into an FFI::Function that # can serve as such an implementation in C. The class will be namespaced # inside class defining the vfunc. class VFuncBuilder < BaseTypeBuilder def setup_class setup_constants klass.class_eval mapping_method_definition, __FILE__, __LINE__ end def klass @klass ||= get_or_define_class container_class, @classname, CallbackBase end def mapping_method_definition receiver_info = ReceiverArgumentInfo.new receiver_type_info MappingMethodBuilder.for_vfunc(receiver_info, info).method_definition end def receiver_type_info ReceiverTypeInfo.new(container_info) end def container_class @container_class ||= Builder.build_class(container_info) end def container_info @container_info ||= info.container end def argument_ffi_types @argument_ffi_types ||= info.argument_ffi_types .unshift(receiver_type_info.to_callback_ffi_type) end def return_ffi_type @return_ffi_type ||= info.return_ffi_type end end end end gir_ffi-0.16.1/lib/gir_ffi/builders/pointer_value_convertor.rb0000644000004100000410000000206214524576001024526 0ustar www-datawww-data# frozen_string_literal: true module GirFFI module Builders # Encapsulates knowledge about how to store values in pointers, and how to # fetch values from pointers. class PointerValueConvertor def initialize(type_spec) @type_spec = type_spec end def pointer_to_value(ptr_exp, offset = 0) case ffi_type_spec when Module "#{ffi_type_spec}.get_value_from_pointer(#{ptr_exp}, #{offset})" when Symbol "#{ptr_exp}.get_#{ffi_type_spec}(#{offset})" end end def value_to_pointer(ptr_exp, value_exp, offset = 0) case ffi_type_spec when Module args = [value_exp, ptr_exp] args << offset unless offset == 0 "#{ffi_type_spec}.copy_value_to_pointer(#{args.join(", ")})" when Symbol "#{ptr_exp}.put_#{ffi_type_spec} #{offset}, #{value_exp}" end end private attr_reader :type_spec def ffi_type_spec TypeMap.type_specification_to_ffi_type type_spec end end end end gir_ffi-0.16.1/lib/gir_ffi/builders/property_builder.rb0000644000004100000410000000703414524576001023147 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/builders/method_template" require "gir_ffi/builders/argument_builder_collection" require "gir_ffi/builders/property_argument_builder" require "gir_ffi/builders/property_return_value_builder" require "gir_ffi/variable_name_generator" require "gir_ffi/field_argument_info" module GirFFI module Builders # Method builder used for the creation of property getter methods. class PropertyGetterBuilder attr_reader :info, :return_value_builder def initialize(info, return_value_builder) @return_value_builder = return_value_builder @info = info end def method_definition template.method_definition end def template @template ||= MethodTemplate.new(self, argument_builder_collection) end def singleton_method? false end def method_name info.getter_name end def method_arguments [] end def preparation [] end def invocation "get_property('#{info.name}')" end def result [return_value_builder.return_value_name] end private def argument_builder_collection @argument_builder_collection ||= ArgumentBuilderCollection.new(return_value_builder, []) end end # Creates property getter and setter code for a given IPropertyInfo. class PropertyBuilder def initialize(property_info) @info = property_info end def build setup_getter setup_setter if setting_allowed end def setup_getter return if container_defines_getter_method? container_class.class_eval getter_def, __FILE__, __LINE__ end def container_defines_getter_method? container_info.find_instance_method getter_name end def setup_setter container_class.class_eval setter_def, __FILE__, __LINE__ end def getter_def PropertyGetterBuilder.new(@info, getter_builder).method_definition end def setter_def converting_setter_def end private def getter_builder @getter_builder ||= PropertyReturnValueBuilder.new(VariableNameGenerator.new, argument_info) end def converting_setter_def <<~CODE def #{setter_name} value #{setter_builder.pre_conversion.join("\n")} set_property("#{property_name}", #{setter_builder.call_argument_name}) end CODE end def setter_builder @setter_builder ||= PropertyArgumentBuilder.new(VariableNameGenerator.new, argument_info) end def property_name @info.name end def getter_name @info.getter_name end def setter_name @info.setter_name end def type_info @type_info ||= @info.property_type end def argument_info @argument_info ||= FieldArgumentInfo.new("value", type_info) end def container_class @container_class ||= container_module.const_get(container_info.safe_name) end def container_module @container_module ||= Object.const_get(container_info.safe_namespace) end # TODO: Inject container_info on initialization def container_info @container_info ||= @info.container end def setting_allowed @info.writeable? && !@info.construct_only? end end end end gir_ffi-0.16.1/lib/gir_ffi/builders/module_builder.rb0000644000004100000410000000603514524576001022550 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/builder_helper" require "gir_ffi/module_base" require "gir_ffi/builders/function_builder" module GirFFI module Builders # Builds a module based on information found in the introspection # repository. class ModuleBuilder include BuilderHelper def initialize(module_name, namespace: module_name, version: nil) @namespace = namespace @version = version @safe_namespace = module_name end def generate modul end def setup_method(method) go = function_introspection_data method.to_s return false unless go Builder.attach_ffi_function lib, go modul.class_eval FunctionBuilder.new(go).method_definition, __FILE__, __LINE__ true end def method_available?(method) function_introspection_data(method.to_s) and true end def build_namespaced_class(classname) info = find_namespaced_class_info(classname) Builder.build_class info end def find_namespaced_class_info(classname) name = classname.to_s info = gir.find_by_name(@namespace, name) || gir.find_by_name(@namespace, name.sub(/^./, &:downcase)) unless info raise NameError, "Class #{classname} not found in namespace #{@namespace}" end info end private def modul unless defined? @module build_dependencies instantiate_module setup_lib_for_ffi unless lib_already_set_up setup_module unless already_set_up end @module end def build_dependencies deps = gir.dependencies @namespace deps.each do |dep| name, version = dep.split "-" Builder.build_module name, version end end def instantiate_module @module = get_or_define_module ::Object, @safe_namespace end def setup_module @module.extend ModuleBase @module.const_set :GIR_FFI_BUILDER, self end def already_set_up @module.const_defined? :GIR_FFI_BUILDER end def setup_lib_for_ffi lib.extend FFI::Library lib.extend FFI::BitMasks lib.ffi_lib_flags :global, :lazy if shared_library_specification lib.ffi_lib(*shared_library_specification.split(",")) end end def shared_library_specification @shared_library_specification ||= gir.shared_library(@namespace) end def lib_already_set_up (class << lib; self; end).include? FFI::Library end def lib @lib ||= get_or_define_module modul, :Lib end def function_introspection_data(function) info = gir.find_by_name @namespace, function.to_s return unless info info.info_type == :function ? info : nil end def gir @gir ||= GObjectIntrospection::IRepository.default.tap do |it| it.require @namespace, @version end end end end end gir_ffi-0.16.1/lib/gir_ffi/builders/type_builder.rb0000644000004100000410000000253014524576001022240 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/builders/callback_builder" require "gir_ffi/builders/constant_builder" require "gir_ffi/builders/enum_builder" require "gir_ffi/builders/flags_builder" require "gir_ffi/builders/interface_builder" require "gir_ffi/builders/object_builder" require "gir_ffi/builders/struct_builder" require "gir_ffi/builders/signal_closure_builder" require "gir_ffi/builders/unintrospectable_boxed_builder" require "gir_ffi/builders/unintrospectable_builder" require "gir_ffi/builders/union_builder" require "gir_ffi/builders/vfunc_builder" module GirFFI module Builders # Builds a class based on information found in the introspection # repository. module TypeBuilder CACHE = {} TYPE_MAP = { callback: CallbackBuilder, constant: ConstantBuilder, enum: EnumBuilder, flags: FlagsBuilder, interface: InterfaceBuilder, object: ObjectBuilder, struct: StructBuilder, union: UnionBuilder, unintrospectable_boxed: UnintrospectableBoxedBuilder, unintrospectable: UnintrospectableBuilder }.freeze def self.build(info) builder_for(info).build_class end # TODO: Pull up to include :function and :module def self.builder_for(info) TYPE_MAP[info.info_type].new(info) end end end end gir_ffi-0.16.1/lib/gir_ffi/builders/base_argument_builder.rb0000644000004100000410000000456614524576001024106 0ustar www-datawww-data# frozen_string_literal: true module GirFFI module Builders # Abstract parent class of the argument building classes. These # classes are used by FunctionBuilder to create the code that # processes each argument before and after the actual function call. class BaseArgumentBuilder KEYWORDS = %w[ alias and begin break case class def do else elsif end ensure false for if in module next nil not or redo rescue retry return self super then true undef unless until when while yield ].freeze attr_reader :arginfo, :related_callback_builder attr_accessor :length_arg, :array_arg def initialize(var_gen, arginfo) @var_gen = var_gen @arginfo = arginfo @length_arg = nil @array_arg = nil @is_user_data = false @is_destroy_notifier = false end def name @name ||= safe(arginfo.name) end def direction @direction ||= arginfo.direction end def type_info @type_info ||= arginfo.argument_type end def specialized_type_tag type_info.flattened_tag end # TODO: Use class rather than class name def argument_class_name type_info.argument_class_name end def array_length_idx type_info.array_length end def closure_idx arginfo.closure end def destroy_idx arginfo.destroy end def mark_as_user_data(callback_builder) @is_user_data = true @related_callback_builder = callback_builder end def mark_as_destroy_notifier(callback_builder) @is_destroy_notifier = true @related_callback_builder = callback_builder end def array_length_parameter? @array_arg end def user_data? @is_user_data end def destroy_notifier? @is_destroy_notifier end def helper_argument? array_length_parameter? || user_data? || destroy_notifier? end def ownership_transfer arginfo.ownership_transfer end def safe(name) if KEYWORDS.include? name "#{name}_" else name end end def call_argument_name @call_argument_name ||= new_variable end def new_variable @var_gen.new_var end end end end gir_ffi-0.16.1/lib/gir_ffi/builders/constructor_builder.rb0000644000004100000410000000262514524576001023651 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/builders/argument_builder_collection" require "gir_ffi/builders/method_template" require "gir_ffi/builders/null_return_value_builder" module GirFFI module Builders # Implements the creation of a Ruby constructor definition out of a # GIR IFunctionInfo. # TODO: Derive from BaseMethodBuilder class ConstructorBuilder def initialize(info) @info = info return_value_builder = NullReturnValueBuilder.new arg_builders = ArgumentBuilderCollection.new(return_value_builder, []) @template = MethodTemplate.new(self, arg_builders) end def method_definition @template.method_definition end def singleton_method? true end def method_name @info.safe_name end def method_arguments ["*args", "&block"] end def preparation if @info.safe_name == "new" ["obj = allocate"] else [ "raise NoMethodError unless self == #{@info.container.full_name}", "obj = allocate" ] end end def invocation "obj.__send__ #{initializer_name.to_sym.inspect}, #{method_arguments.join(", ")}" end def result ["obj"] end private def initializer_name @info.safe_name.sub(/^new/, "initialize") end end end end gir_ffi-0.16.1/lib/gir_ffi/builders/signal_closure_builder.rb0000644000004100000410000000171414524576001024273 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/builders/base_type_builder" require "gir_ffi/builders/marshalling_method_builder" module GirFFI module Builders # Implements the creation of a closure class for handling a particular # signal. The type will be attached to the appropriate class. class SignalClosureBuilder < BaseTypeBuilder def setup_class setup_constants klass.class_eval marshaller_definition, __FILE__, __LINE__ end def setup_method(_method) nil end def marshaller_definition MarshallingMethodBuilder.for_signal(info).method_definition end private def klass @klass ||= get_or_define_class container_class, @classname, GObject::RubyClosure end def container_class @container_class ||= Builder.build_class(container_info) end def container_info @container_info ||= info.container end end end end gir_ffi-0.16.1/lib/gir_ffi/builders/property_argument_builder.rb0000644000004100000410000000110714524576001025044 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/builders/base_argument_builder" module GirFFI module Builders # Convertor for arguments for property setters. class PropertyArgumentBuilder < BaseArgumentBuilder def pre_conversion pr = [] pr << "#{call_argument_name} = #{ingoing_convertor.conversion}" pr end def ingoing_convertor if type_info.needs_ruby_to_c_conversion_for_properties? RubyToCConvertor.new(type_info, name) else NullConvertor.new(name) end end end end end gir_ffi-0.16.1/lib/gir_ffi/builders/with_layout.rb0000644000004100000410000000217314524576001022124 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/builders/field_builder" module GirFFI module Builders # Implements the creation of classes representing types with layout, # i.e., :union, :struct, :object. # NOTE: This module depends on methods in RegisteredTypeBuilder. module WithLayout def layout_specification spec = base_layout_specification if spec.empty? dummy_layout_specification else spec end end private def setup_layout spec = layout_specification struct_class.class_eval do layout(*spec) end end def dummy_layout_specification if parent_info [:parent, superclass::Struct, 0] else [:dummy, :char, 0] end end def base_layout_specification fields.flat_map(&:layout_specification) end def klass @klass ||= get_or_define_class namespace_module, @classname, superclass end def struct_class @struct_class ||= get_or_define_class klass, :Struct, layout_superclass end end end end gir_ffi-0.16.1/lib/gir_ffi/builders/callback_builder.rb0000644000004100000410000000307314524576001023016 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/builders/base_type_builder" require "gir_ffi/builders/mapping_method_builder" require "gir_ffi/callback_base" module GirFFI module Builders # Implements the creation of a callback type. The type will be # attached to the appropriate namespace module, and will be defined # as a callback for FFI. class CallbackBuilder < BaseTypeBuilder def setup_class setup_callback setup_constants klass.class_eval mapping_method_definition, __FILE__, __LINE__ end def mapping_method_definition MappingMethodBuilder.for_callback(info).method_definition end def argument_ffi_types @argument_ffi_types ||= @info.argument_ffi_types end def return_ffi_type @return_ffi_type ||= @info.return_ffi_type end private def setup_callback optionally_define_constant klass, :Callback do lib.callback callback_sym, argument_ffi_types, return_ffi_type end end def klass @klass ||= get_or_define_class container_module, @classname, CallbackBase end def container_module @container_module ||= if @info.container type_info = @info.container field_info = type_info.container container_class_info = field_info.container namespace_module.const_get container_class_info.safe_name else namespace_module end end def callback_sym @classname.to_sym end end end end gir_ffi-0.16.1/lib/gir_ffi/builders/closure_to_pointer_convertor.rb0000644000004100000410000000063514524576001025574 0ustar www-datawww-data# frozen_string_literal: true module GirFFI module Builders # Builder that generates code to convert closure arguments ('user data') # from Ruby to C. Used by argument builders. class ClosureToPointerConvertor def initialize(argument_name) @argument_name = argument_name end def conversion "GirFFI::ArgHelper.store(#{@argument_name})" end end end end gir_ffi-0.16.1/lib/gir_ffi/builders/callback_return_value_builder.rb0000644000004100000410000000246714524576001025617 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/builders/base_return_value_builder" require "gir_ffi/builders/ruby_to_c_convertor" module GirFFI module Builders # Implements building post-processing statements for return values of # callbacks. class CallbackReturnValueBuilder < BaseReturnValueBuilder def post_conversion optional_outgoing_ref + base_post_conversion end private def has_post_conversion? relevant? && needs_ruby_to_c_conversion? end def needs_ruby_to_c_conversion? type_info.needs_ruby_to_c_conversion_for_callbacks? end def optional_outgoing_ref if outgoing_ref_needed? ["#{capture_variable_name}.ref"] else [] end end def base_post_conversion if !has_post_conversion? [] elsif specialized_type_tag == :object ["#{post_converted_name} = #{post_convertor.conversion}.to_ptr"] else ["#{post_converted_name} = #{post_convertor.conversion}"] end end def post_convertor @post_convertor ||= RubyToCConvertor.new(type_info, capture_variable_name) end def outgoing_ref_needed? ownership_transfer == :everything && specialized_type_tag == :object end end end end gir_ffi-0.16.1/lib/gir_ffi/builders/struct_builder.rb0000644000004100000410000000266014524576001022607 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/builders/registered_type_builder" require "gir_ffi/builders/struct_like" require "gir_ffi/struct_base" module GirFFI module Builders # Implements the creation of a class representing a Struct. class StructBuilder < RegisteredTypeBuilder include StructLike def initialize(info, superclass: nil) @superclass = superclass super info end def superclass @superclass ||= if info.gtype_struct? gtype_struct_parent elsif GObject.type_fundamental(info.gtype) == GObject::TYPE_BOXED BoxedBase else StructBase end end private def layout_superclass GirFFI::Struct end def klass @klass ||= get_or_define_class(namespace_module, @classname) { superclass } end def parent_info @parent_info ||= parent_field_type&.interface end def parent_field_type fields.first&.field_type end def gtype_struct_parent full_name = info.full_name if full_name == "GObject::InitiallyUnownedClass" GObject::ObjectClass else raise "Unable to calculate parent class for #{full_name}" unless parent_info Builder.build_class parent_info end end end end end gir_ffi-0.16.1/lib/gir_ffi/builders/property_return_value_builder.rb0000644000004100000410000000061314524576001025736 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/builders/return_value_builder" module GirFFI module Builders # Implements building post-processing statements for return values of # property getters. class PropertyReturnValueBuilder < ReturnValueBuilder def needs_c_to_ruby_conversion? type_info.needs_c_to_ruby_conversion_for_properties? end end end end gir_ffi-0.16.1/lib/gir_ffi/builders/base_return_value_builder.rb0000644000004100000410000000175514524576001024774 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/builders/base_argument_builder" module GirFFI module Builders # Implements building post-processing statements for return values of # callbacks. class BaseReturnValueBuilder < BaseArgumentBuilder def relevant? !void_return_value? && !arginfo.skip? end def capture_variable_name @capture_variable_name ||= new_variable if relevant? end def post_converted_name @post_converted_name ||= if has_post_conversion? new_variable else capture_variable_name end end def return_value_name post_converted_name if has_return_value_name? end def void_return_value? specialized_type_tag == :void && !type_info.pointer? end def has_return_value_name? relevant? && !array_arg end end end end gir_ffi-0.16.1/lib/gir_ffi/g_type.rb0000644000004100000410000000073314524576001017232 0ustar www-datawww-data# frozen_string_literal: true module GirFFI # Wrapper class providing extended functionality for a GType, which is # normally just a kind of integer class GType def initialize(gtype) @gtype = gtype end def to_i @gtype end def class_size type_query.class_size end def instance_size type_query.instance_size end private def type_query @type_query ||= GObject.type_query @gtype end end end gir_ffi-0.16.1/lib/gir_ffi/unintrospectable_signal_info.rb0000644000004100000410000000172614524576001023677 0ustar www-datawww-data# frozen_string_literal: true module GirFFI # Represents a signal not found in the GIR, conforming, as needed, to the # interface of GObjectIntrospection::ISignalInfo. class UnintrospectableSignalInfo attr_reader :signal_id def initialize(signal_id) @signal_id = signal_id end def name GObject.signal_name signal_id end def wrap_in_closure(&block) GObject::RubyClosure.new(&block) end def arguments_to_gvalues(instance, arguments) param_gtypes = signal_query.param_types || [] argument_gvalues = param_gtypes.zip(arguments).map do |gtype, arg| GObject::Value.for_gtype(gtype).tap { |it| it.set_value arg } end argument_gvalues.unshift GObject::Value.wrap_instance(instance) end def gvalue_for_return_value GObject::Value.for_gtype signal_query.return_type end private def signal_query @signal_query ||= GObject.signal_query signal_id end end end gir_ffi-0.16.1/lib/gir_ffi/glib_error.rb0000644000004100000410000000064314524576001020071 0ustar www-datawww-data# frozen_string_literal: true module GirFFI # Exception class to be raised whenever an error is signaled through # GLib::Error. class GLibError < RuntimeError attr_reader :domain_quark, :code def initialize(g_error) @domain_quark = g_error.domain @code = g_error.code super g_error.message end def domain @domain ||= GLib.quark_to_string @domain_quark end end end gir_ffi-0.16.1/lib/gir_ffi/ffi_ext.rb0000644000004100000410000000010114524576001017354 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/ffi_ext/pointer" gir_ffi-0.16.1/lib/gir_ffi/info_ext.rb0000644000004100000410000000123614524576001017555 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/info_ext/full_type_name" require "gir_ffi/info_ext/i_arg_info" require "gir_ffi/info_ext/i_callable_info" require "gir_ffi/info_ext/i_callback_info" require "gir_ffi/info_ext/i_field_info" require "gir_ffi/info_ext/i_function_info" require "gir_ffi/info_ext/i_property_info" require "gir_ffi/info_ext/i_registered_type_info" require "gir_ffi/info_ext/i_signal_info" require "gir_ffi/info_ext/i_type_info" require "gir_ffi/info_ext/i_unresolved_info" require "gir_ffi/info_ext/i_value_info" require "gir_ffi/info_ext/i_vfunc_info" require "gir_ffi/info_ext/safe_constant_name" require "gir_ffi/info_ext/safe_function_name" gir_ffi-0.16.1/lib/gir_ffi/unintrospectable_type_info.rb0000644000004100000410000000227014524576001023376 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/info_ext/full_type_name" module GirFFI # Represents a type not found in the GIR, conforming, as needed, to the # interface of GObjectIntrospection::IObjectInfo. class UnintrospectableTypeInfo attr_reader :g_type def initialize(gtype, gir = GObjectIntrospection::IRepository.default, gobject = GObject) @g_type = gtype @gir = gir @gobject = gobject end def info_type :unintrospectable end def safe_name @gobject.type_name @g_type end def parent @gir.find_by_gtype(parent_gtype) || self.class.new(parent_gtype, @gir, @gobject) end def parent_gtype @parent_gtype ||= @gobject.type_parent @g_type end def namespace parent.namespace end def interfaces @gobject.type_interfaces(@g_type).filter_map do |gtype| @gir.find_by_gtype gtype end end def fields [] end def find_property(_any) nil end def find_signal(_any) nil end # TODO: Create custom class that includes the interfaces instead def class_struct nil end end end gir_ffi-0.16.1/lib/gir_ffi/registered_type_base.rb0000644000004100000410000000041414524576001022127 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/type_base" module GirFFI # Base module for generated registered GLib types (these are types that have a # GType). module RegisteredTypeBase include TypeBase def gtype self::G_TYPE end end end gir_ffi-0.16.1/lib/gir_ffi/zero_terminated.rb0000644000004100000410000000376014524576001021141 0ustar www-datawww-data# frozen_string_literal: true module GirFFI # Represents a null-terminated array. class ZeroTerminated include Enumerable attr_reader :element_type def initialize(elm_t, ptr) @element_type = elm_t @ptr = ptr end def to_ptr @ptr end def self.from(type, arg) new type, InPointer.from_array(type, arg) end def self.wrap(type, arg) new type, arg end def each return if @ptr.null? offset = 0 while (val = read_value(offset)) offset += ffi_type_size yield wrap_value(val) end end def ==(other) to_a == other.to_a end private def read_value(offset) val = fetch_value(offset) val unless null_value? val end def getter_method @getter_method ||= "get_#{ffi_type}" end def fetch_value(offset) case ffi_type when Module ffi_type.get_value_from_pointer(@ptr, offset) when Symbol @ptr.send(getter_method, offset) else raise NotImplementedError end end def wrap_value(val) case element_type when Array element_type.last.wrap val when Class element_type.wrap val else val end end def ffi_type @ffi_type ||= TypeMap.type_specification_to_ffi_type element_type end def ffi_type_size @ffi_type_size ||= FFI.type_size(ffi_type) end def null_check_strategy @null_check_strategy ||= if ffi_type == :pointer :pointer elsif ffi_type.is_a? Symbol :numeric elsif ffi_type < GirFFI::ClassBase # rubocop:disable Lint/DuplicateBranch :pointer elsif ffi_type.singleton_class.include? GirFFI::EnumBase :enum end end def null_value?(val) case null_check_strategy when :pointer val.null? when :enum ffi_type.to_native(val, nil) == 0 else val == 0 end end end end gir_ffi-0.16.1/lib/gir_ffi/error_type_info.rb0000644000004100000410000000064314524576001021150 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/info_ext/i_type_info" module GirFFI # Represents the type of an error argument for callbacks and functions, # conforming, as needed, to the interface of GObjectIntrospection::ITypeInfo class ErrorTypeInfo include GirFFI::InfoExt::ITypeInfo def array_length -1 end def tag :error end def pointer? true end end end gir_ffi-0.16.1/lib/gir_ffi/property_not_found_error.rb0000644000004100000410000000055614524576001023116 0ustar www-datawww-data# frozen_string_literal: true module GirFFI # Exception class to be raised when a property is not found. class PropertyNotFoundError < RuntimeError attr_reader :property_name def initialize(property_name, klass) @property_name = property_name @klass = klass super "Property '#{property_name}' not found in #{klass}" end end end gir_ffi-0.16.1/lib/gir_ffi/sized_array.rb0000644000004100000410000000476514524576001020270 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/array_element_convertor" module GirFFI # Class representing an array with a determined size class SizedArray include Enumerable attr_reader :element_type, :size def initialize(element_type, size, pointer) @element_type = element_type @size = size @pointer = pointer end def to_ptr @pointer end def index(idx) convertor = ArrayElementConvertor.new element_type, @pointer + idx * element_size convertor.to_ruby_value end def each size.times do |idx| yield index(idx) end end def ==(other) to_a.eql? other.to_a end def size_in_bytes size * element_size end def self.get_value_from_pointer(pointer, offset) pointer + offset end def self.copy_value_to_pointer(value, pointer, offset = 0) size = value.size_in_bytes pointer.put_bytes(offset, value.to_ptr.read_bytes(size)) end def self.wrap(element_type, size, pointer) new element_type, size, pointer unless pointer.null? end private def element_ffi_type @element_ffi_type ||= TypeMap.type_specification_to_ffi_type element_type end def element_size @element_size ||= FFI.type_size element_ffi_type end class << self def from(element_type, size, item) return unless item case item when FFI::Pointer wrap element_type, size, item when self from_sized_array size, item else from_enumerable element_type, size, item end end def copy_from(element_type, size, enumerable) return unless enumerable arr = enumerable.to_a case element_type when Array _main_type, sub_type = *element_type arr = arr.map { |it| sub_type.copy_from it } end from_enumerable element_type, size, arr end private def from_sized_array(size, sized_array) check_size size, sized_array.size sized_array end def from_enumerable(element_type, expected_size, arr) size = arr.size check_size expected_size, size ptr = InPointer.from_array element_type, arr wrap element_type, size, ptr end def check_size(expected_size, size) return if expected_size == -1 return if size == expected_size raise ArgumentError, "Expected size #{expected_size}, got #{size}" end end end end gir_ffi-0.16.1/lib/gir_ffi/variable_name_generator.rb0000644000004100000410000000043714524576001022577 0ustar www-datawww-data# frozen_string_literal: true module GirFFI # Generates a sequence of unique variable names used in generating # function definitions. class VariableNameGenerator def initialize @varno = 0 end def new_var @varno += 1 "_v#{@varno}" end end end gir_ffi-0.16.1/lib/gir_ffi/union.rb0000644000004100000410000000023614524576001017071 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/ownable" module GirFFI # Union that can be owned. class Union < FFI::Union include Ownable end end gir_ffi-0.16.1/lib/gir_ffi/module_base.rb0000644000004100000410000000125614524576001020223 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/method_setup" module GirFFI # Base module for modules representing GLib namespaces. module ModuleBase include MethodSetup def method_missing(method, *arguments, &block) result = setup_method method.to_s return super unless result send method, *arguments, &block end def respond_to_missing?(method, *) gir_ffi_builder.method_available? method end def const_missing(classname) load_class(classname) end def load_class(classname) gir_ffi_builder.build_namespaced_class classname.to_s end def gir_ffi_builder self::GIR_FFI_BUILDER end end end gir_ffi-0.16.1/lib/gir_ffi/enum_like_base.rb0000644000004100000410000000167214524576001020710 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/registered_type_base" require "gir_ffi/method_setup" module GirFFI # Base module for enums and flags. module EnumLikeBase include FFI::DataConverter include RegisteredTypeBase include MethodSetup def wrap(arg) from_native arg, nil end def to_int(arg) to_native arg, nil end def size native_type.size end def copy_value_to_pointer(value, pointer, offset = 0) pointer.put_int32 offset, to_native(value, nil) end def get_value_from_pointer(pointer, offset) from_native pointer.get_int32(offset), nil end def setup_and_call(method, arguments, &block) result = setup_method method.to_s raise "Unable to set up method #{method} in #{self}" unless result send method, *arguments, &block end def to_ffi_type self end def to_callback_ffi_type :int32 end end end gir_ffi-0.16.1/lib/gir_ffi/allocation_helper.rb0000644000004100000410000000042114524576001021421 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/lib_c" module GirFFI # Helper module for alloction-related functionality. module AllocationHelper def self.free_after(ptr) result = yield ptr LibC.free ptr unless ptr.null? result end end end gir_ffi-0.16.1/lib/gir_ffi/interface_base.rb0000644000004100000410000000156114524576001020675 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/registered_type_base" require "gir_ffi/method_setup" require "gir_ffi/instance_method_setup" module GirFFI # Base module for modules representing GLib interfaces. module InterfaceBase include RegisteredTypeBase include MethodSetup include InstanceMethodSetup def setup_and_call(method, arguments, &block) method_name = setup_method method.to_s raise NoMethodError, "undefined method `#{method}' for #{self}" unless method_name send method_name, *arguments, &block end # TODO: Unify with implementation in ObjectBase def copy_value_to_pointer(value, pointer, offset = 0) pointer.put_pointer offset, value.to_ptr end def wrap(ptr) ptr.to_object end def to_ffi_type :pointer end def to_callback_ffi_type :pointer end end end gir_ffi-0.16.1/lib/gir_ffi/vfunc_implementation.rb0000644000004100000410000000056314524576001022172 0ustar www-datawww-data# frozen_string_literal: true module GirFFI # Simple wrapper class to represent the implementation of a VFunc. class VFuncImplementation attr_reader :name, :implementation def initialize(name, implementation) implementation ||= ->(obj, *args) { obj.public_send name, *args } @name = name @implementation = implementation end end end gir_ffi-0.16.1/lib/gir_ffi/receiver_type_info.rb0000644000004100000410000000077414524576001021630 0ustar www-datawww-data# frozen_string_literal: true module GirFFI # Represents the type of the receiver of a signal, vfunc, or method, # conforming, as needed, to the interface of GObjectIntrospection::ITypeInfo class ReceiverTypeInfo include InfoExt::ITypeInfo def initialize(interface_info) @interface_info = interface_info end def interface @interface_info end def tag :interface end def pointer? false end def array_length -1 end end end gir_ffi-0.16.1/lib/gir_ffi/struct.rb0000644000004100000410000000024114524576001017261 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/ownable" module GirFFI # Struct that can be owned. class Struct < FFI::Struct include Ownable end end gir_ffi-0.16.1/lib/gir_ffi/in_pointer.rb0000644000004100000410000000745214524576001020116 0ustar www-datawww-data# frozen_string_literal: true module GirFFI # The InPointer module handles conversion from ruby types to pointers for # arguments with direction :in. This is used for arguments that are # arrays, strings, or interfaces. module InPointer def self.from_array(type, ary) return unless ary case type when Symbol from_simple_type_array type, ary when Module from_module_type_array type, ary when Array main_type, sub_type = *type raise "Unexpected main type #{main_type}" if main_type != :pointer from_pointer_array sub_type, ary else raise NotImplementedError, type end end def self.from(type, val) return unless val case type when :utf8, :filename from_utf8 val when :gfloat, :gdouble, :gint64, :guint64 from_basic_type type, val when :gint32, :guint32, :gint8, :GType FFI::Pointer.new val when GirFFI::EnumLikeBase FFI::Pointer.new type[val] when Module, :void val.to_ptr else raise NotImplementedError, type end end def self.from_utf8(str) return unless str ptr = FFI::MemoryPointer.from_string(str) ptr.autorelease = false ptr end class << self private def from_basic_type(type, value) ffi_type = TypeMap.type_specification_to_ffi_type type FFI::MemoryPointer.new(ffi_type).tap do |block| block.autorelease = false block.send "put_#{ffi_type}", 0, value end end def from_simple_type_array(type, ary) case type when :utf8, :filename from_utf8_array ary when :gboolean from_boolean_array ary when :guint8 from_char_array ary else from_basic_type_array type, ary end end def from_module_type_array(type, ary) return from_gvalue_array(type, ary) if type == GObject::Value case type when GirFFI::EnumLikeBase from_enum_array type, ary when GirFFI::RegisteredTypeBase from_struct_array type, ary else raise NotImplementedError, type end end def from_utf8_array(ary) from_basic_type_array :pointer, ary.map { |str| from_utf8 str } end def from_boolean_array(ary) from_basic_type_array :int, ary.map { |val| val ? 1 : 0 } end def from_char_array(ary) ary = ary.bytes if ary.is_a? String from_basic_type_array :int8, ary end def from_pointer_array(type, ary) from_basic_type_array :pointer, ary.map { |elem| from type, elem } end def from_gvalue_array(type, ary) ary = ary.map do |it| if it.is_a? GObject::Value it else GObject::Value.wrap_ruby_value it end end from_struct_array type, ary end def from_struct_array(type, ary) ffi_type = TypeMap.type_specification_to_ffi_type type type_size = FFI.type_size(ffi_type) length = ary.length ptr = FFI::MemoryPointer.new type_size * (length + 1) ptr.autorelease = false ary.each_with_index do |item, idx| type.copy_value_to_pointer item, ptr, idx * type_size end ptr end def from_enum_array(type, ary) from_basic_type_array :int32, ary.map { |sym| type.to_native sym, nil } end def from_basic_type_array(type, ary) ffi_type = TypeMap.type_specification_to_ffi_type type type_size = FFI.type_size(ffi_type) FFI::MemoryPointer.new(type_size * (ary.length + 1)).tap do |block| block.autorelease = false block.send "put_array_of_#{ffi_type}", 0, ary end end end end end gir_ffi-0.16.1/lib/gir_ffi/method_setup.rb0000644000004100000410000000043714524576001020444 0ustar www-datawww-data# frozen_string_literal: true module GirFFI # Methods for setting up class methods module MethodSetup def setup_method(name) gir_ffi_builder.setup_method name end def setup_method!(name) setup_method name or raise "Unknown method #{name}" end end end gir_ffi-0.16.1/lib/gir_ffi/boolean.rb0000644000004100000410000000136514524576001017364 0ustar www-datawww-data# frozen_string_literal: true require "ffi" module GirFFI # Class representing a boolean (natively, an int). class Boolean extend FFI::DataConverter native_type FFI::Type::INT FROM_NATIVE = { 0 => false, 1 => true }.freeze TO_NATIVE = FROM_NATIVE.invert def self.from_native(value, _context) FROM_NATIVE.fetch(value) end def self.to_native(value, _context) TO_NATIVE.fetch(value ? true : false) end def self.size FFI.type_size FFI::Type::INT end def self.copy_value_to_pointer(value, pointer, offset = 0) pointer.put_int offset, to_native(value, nil) end def self.get_value_from_pointer(pointer, offset) from_native pointer.get_int(offset), nil end end end gir_ffi-0.16.1/lib/gir_ffi/flags_base.rb0000644000004100000410000000102714524576001020026 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/enum_like_base" module GirFFI # Base module for flags. module FlagsBase include EnumLikeBase def native_type self::BitMask.native_type end def to_native(value, context) case value when Symbol value = { value => true } end self::BitMask.to_native(value, context) end def from_native(*args) self::BitMask.from_native(*args).select { |_k, v| v } end def [](arg) self::BitMask[arg] end end end gir_ffi-0.16.1/lib/gir_ffi/struct_like_base.rb0000644000004100000410000000325014524576001021262 0ustar www-datawww-data# frozen_string_literal: true module GirFFI # Base class providing methods for generated classes representing GLib # structs, unions and boxed types. class StructLikeBase < ClassBase extend FFI::DataConverter def initialize store_pointer(nil) struct.owned = true struct.to_ptr.autorelease = false end # Class methods for struct-like classes. class << self def native_type FFI::Type::Struct.new(self::Struct) end def to_ffi_type self end def to_native(value, _context) value.struct end def get_value_from_pointer(pointer, offset) pointer + offset end def size self::Struct.size end def copy_value_to_pointer(value, pointer, offset = 0) bytes = value.to_ptr.read_bytes(size) pointer.put_bytes offset, bytes end # Create an unowned copy of the struct represented by val def copy_from(val) return unless val disown copy from(val) end # Wrap an owned copy of the struct represented by val def wrap_copy(val) return unless val own copy(val) end # Wrap value and take ownership of it def wrap_own(val) return unless val return if val.null? own wrap(val) end private def own(val) val.struct.owned = true val end def disown(val) val.struct.owned = nil val end # Create a copy of the struct represented by val def copy(val) new.tap do |copy| copy_value_to_pointer(val, copy.to_ptr) end end end end end gir_ffi-0.16.1/lib/gir_ffi/error_argument_info.rb0000644000004100000410000000051714524576001022011 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/error_type_info" module GirFFI # Represents an error argument with the same interface as IArgInfo class ErrorArgumentInfo def direction :error end def argument_type @argument_type ||= ErrorTypeInfo.new end def name "_error" end end end gir_ffi-0.16.1/lib/gir_ffi/return_value_info.rb0000644000004100000410000000071314524576001021467 0ustar www-datawww-data# frozen_string_literal: true module GirFFI # Represents a return value with the same interface as IArgInfo class ReturnValueInfo attr_reader :argument_type, :ownership_transfer def initialize(type, ownership_transfer, skip) @argument_type = type @ownership_transfer = ownership_transfer @skip = skip end def skip? @skip end def direction :return end def name nil end end end gir_ffi-0.16.1/lib/gir_ffi/type_map.rb0000644000004100000410000000251014524576001017554 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/boolean" require "gir_ffi/sized_array" module GirFFI # Maps GObject type tags and type specification to types FFI can handle. module TypeMap sz = FFI.type_size(:size_t) * 8 gsize_type = "uint#{sz}".to_sym TAG_TYPE_MAP = { enum: :int32, flags: :int32, ghash: :pointer, glist: :pointer, gslist: :pointer, strv: :pointer, interface: :pointer, error: :pointer, ptr_array: :pointer, array: :pointer, c: GirFFI::SizedArray, utf8: :pointer, filename: :pointer, GType: gsize_type, gboolean: GirFFI::Boolean, gunichar: :uint32, gint8: :int8, guint8: :uint8, gint16: :int16, guint16: :uint16, gint: :int, guint: :uint, gint32: :int32, guint32: :uint32, gint64: :int64, guint64: :uint64, glong: :long, gulong: :ulong, gsize: gsize_type, gfloat: :float, gdouble: :double, void: :void }.freeze def self.map_basic_type(type) sym = type.to_sym TAG_TYPE_MAP[sym] || sym end def self.type_specification_to_ffi_type(type) case type when Module type.to_ffi_type when Array type[0] else map_basic_type(type) end end end end gir_ffi-0.16.1/lib/gir_ffi/array_element_convertor.rb0000644000004100000410000000167714524576001022703 0ustar www-datawww-data# frozen_string_literal: true module GirFFI # The ArrayElementConvertor class handles conversion from C array elements to # ruby values class ArrayElementConvertor attr_reader :value_type, :pointer def initialize(type, ptr) @value_type = type @pointer = ptr end def to_ruby_value bare_value = to_value case value_type when :utf8, :filename bare_value.to_utf8 when Array value_type[1].wrap bare_value when Module value_type.wrap bare_value else bare_value end end private def to_value case value_ffi_type when Module value_ffi_type.get_value_from_pointer(pointer, 0) when Symbol pointer.send("get_#{value_ffi_type}", 0) else raise NotImplementedError end end def value_ffi_type @value_ffi_type ||= TypeMap.type_specification_to_ffi_type value_type end end end gir_ffi-0.16.1/lib/gir_ffi/object_base.rb0000644000004100000410000000525514524576001020207 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/class_base" module GirFFI # Base class for all generated classes of type :object. class ObjectBase < ClassBase extend FFI::DataConverter def class_struct self.class.class_struct end def self.native_type FFI::Type::POINTER end def self.to_ffi_type self end def self.to_native(obj, _context) obj.to_ptr end def self.get_value_from_pointer(pointer, offset = 0) pointer.get_pointer offset end def self.copy_value_to_pointer(value, pointer, offset = 0) pointer.put_pointer offset, value.to_ptr end # Wrap the passed pointer in an instance of its type's corresponding class, # generally assumed to be a descendant of the current type. def self.wrap(ptr) ptr.to_object end def self.copy_from(val) val&.ref end # # Find property info for the named property. # # @param name The property's name # # @return [GObjectIntrospection::IPropertyInfo] The property's info # def self.find_property(name) gir_ffi_builder.find_property name end # # Find signal info for the named signal. # # @param name The signal's name # # @return [GObjectIntrospection::ISignalInfo] The signal's info # def self.find_signal(name) gir_ffi_builder.find_signal name or raise GirFFI::SignalNotFoundError.new(name, self) end def self.class_struct @class_struct ||= begin ptr = GObject::Lib.g_type_class_ref(gtype) gir_ffi_builder.class_struct_class.wrap ptr end end def self.included_interfaces included_modules.select { |it| it.singleton_class.include? InterfaceBase } end def self.registered_ancestors ancestors.select do |it| it < GirFFI::ObjectBase || it.singleton_class.include?(InterfaceBase) end end def self.prepare_user_defined_class return if const_defined? :GIR_INFO, false info = UserDefinedObjectInfo.new(self) const_set :GIR_INFO, info end def self.install_property(param_spec) if const_defined? :GIR_FFI_BUILDER, false raise "Installing a property in a class that is already set up is not supported" end prepare_user_defined_class gir_info.install_property(param_spec) end def self.install_vfunc_implementation(name, implementation = nil) if const_defined? :GIR_FFI_BUILDER, false raise "Installing a property in a class that is already set up is not supported" end prepare_user_defined_class gir_info.install_vfunc_implementation(name, implementation) end end end gir_ffi-0.16.1/lib/gir_ffi/ffi_ext/0000755000004100000410000000000014524576001017037 5ustar www-datawww-datagir_ffi-0.16.1/lib/gir_ffi/ffi_ext/pointer.rb0000644000004100000410000000210014524576001021035 0ustar www-datawww-data# frozen_string_literal: true module GirFFI module FFIExt # Extensions to FFI::Pointer module Pointer def self.prepended(base) base.class_eval do size_t_getter = case (size = FFI.type_size(:size_t)) when 4 :get_uint32 when 8 :get_uint64 else raise NotImplementedError, "Don't know how to handle size_t types of size #{size}" end alias_method :get_size_t, size_t_getter alias_method :get_gtype, :get_size_t end end def to_ptr self end # FIXME: Should probably not be here. def to_object return nil if null? gtype = GObject.type_from_instance_pointer self Builder.build_by_gtype(gtype).direct_wrap self end def to_utf8 null? ? nil : read_string.force_encoding("utf-8") end end end end # @api private class FFI::Pointer # rubocop:disable Style/ClassAndModuleChildren prepend GirFFI::FFIExt::Pointer end gir_ffi-0.16.1/lib/gir_ffi/object_store.rb0000644000004100000410000000106114524576001020420 0ustar www-datawww-data# frozen_string_literal: true module GirFFI # Helper class for storing objects for later retrieval. Used to store user # data arguments. class ObjectStore def initialize @store = {} end def store(obj) return FFI::Pointer::NULL if obj.nil? # FIXME: Don't use object_id! key = obj.object_id @store[key] = obj FFI::Pointer.new(key) end def fetch(ptr) return if ptr.null? key = ptr.address if @store.key? key @store[key] else ptr end end end end gir_ffi-0.16.1/lib/gir_ffi/user_defined_object_info.rb0000644000004100000410000000300214524576001022730 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/user_defined_property_info" require "gir_ffi/vfunc_implementation" module GirFFI # Represents a user defined type, conforming, as needed, to the interface of # GObjectIntrospection::IObjectInfo. class UserDefinedObjectInfo attr_reader :properties, :vfunc_implementations def initialize(klass) @klass = klass @properties = [] @vfunc_implementations = [] end def described_class @klass end def install_property(param_spec) @properties << param_spec end def install_vfunc_implementation(name, implementation = nil) @vfunc_implementations << VFuncImplementation.new(name, implementation) end def find_method(_method) nil end def find_instance_method(_method) nil end def find_property(_property) nil end def parent_gtype @parent_gtype ||= GType.new(@klass.superclass.gtype) end def parent @parent ||= gir.find_by_gtype(parent_gtype.to_i) end # TODO: Create custom class that includes the interfaces instead def class_struct nil end def interfaces (@klass.included_modules - @klass.superclass.included_modules).map(&:gir_info) end def find_signal(_signal_name) nil end def abstract? false end attr_writer :g_name def g_name @g_name ||= @klass.name end private def gir @gir ||= GObjectIntrospection::IRepository.default end end end gir_ffi-0.16.1/lib/gir_ffi/unintrospectable_boxed_info.rb0000644000004100000410000000116114524576001023514 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/info_ext/full_type_name" module GirFFI # Represents a boxed type not found in the GIR, conforming, as needed, to the # interface of GObjectIntrospection::IUnionInfo and GObjectIntrospection::IStructInfo. class UnintrospectableBoxedInfo attr_reader :g_type def initialize(gtype) @g_type = gtype end def info_type :unintrospectable_boxed end def safe_name GObject.type_name g_type end DEFAULT_BOXED_NAMESPACE = "GLib" def namespace DEFAULT_BOXED_NAMESPACE end def fields [] end end end gir_ffi-0.16.1/lib/gir_ffi/builder.rb0000644000004100000410000000370714524576001017375 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/builders/type_builder" require "gir_ffi/builders/module_builder" require "gir_ffi/builder_helper" require "gir_ffi/unintrospectable_type_info" require "gir_ffi/unintrospectable_boxed_info" module GirFFI # Builds modules and classes based on information found in the # introspection repository. Call its build_module and build_class methods # to create the modules and classes used in your program. module Builder extend BuilderHelper def self.build_class(info) Builders::TypeBuilder.build(info) end def self.build_by_gtype(gtype) info = GObjectIntrospection::IRepository.default.find_by_gtype gtype info ||= begin fund = GObject.type_fundamental gtype if fund == GObject::TYPE_BOXED UnintrospectableBoxedInfo.new gtype elsif fund == GObject::TYPE_OBJECT || fund >= GObject::TYPE_RESERVED_USER_FIRST UnintrospectableTypeInfo.new gtype else raise "Unable to handle type #{GObject.type_name gtype}" end end build_class info end def self.build_module(namespace, version = nil) module_name = namespace.sub(/\A./, &:upcase) if const_defined? module_name modul = const_get module_name unless modul.const_defined? :GIR_FFI_BUILDER raise "The module #{module_name} was already defined elsewhere" end return modul end Builders::ModuleBuilder.new(module_name, namespace: namespace, version: version).generate end # TODO: Move elsewhere, perhaps to FunctionBuilder. def self.attach_ffi_function(lib, info) sym = info.symbol return if lib.method_defined? sym lib.attach_function sym, info.argument_ffi_types, info.return_ffi_type end end end gir_ffi-0.16.1/lib/gir_ffi/enum_base.rb0000644000004100000410000000062414524576001017700 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/enum_like_base" module GirFFI # Base module for enums. module EnumBase include EnumLikeBase def native_type self::Enum.native_type end def to_native(*args) self::Enum.to_native(*args) end def from_native(*args) self::Enum.from_native(*args) end def [](arg) self::Enum[arg] end end end gir_ffi-0.16.1/lib/gir_ffi/receiver_argument_info.rb0000644000004100000410000000103614524576001022461 0ustar www-datawww-data# frozen_string_literal: true module GirFFI # Class to represent the info for the receiver argument of a callback or # signal handler. Implements the necessary parts of IArgInfo's # interface. class ReceiverArgumentInfo attr_reader :argument_type def initialize(type) @argument_type = type end def direction :in end # Assume we don't need to increase the refcount for the receiver argument. def ownership_transfer :everything end def name "_instance" end end end gir_ffi-0.16.1/lib/gir_ffi/core.rb0000644000004100000410000000217114524576001016671 0ustar www-datawww-data# frozen_string_literal: true require "ffi" require "ffi/bit_masks" require "ffi-gobject_introspection" require "gir_ffi-base" require "gir_ffi/ffi_ext" require "gir_ffi/class_base" require "gir_ffi/type_map" require "gir_ffi/info_ext" require "gir_ffi/in_pointer" require "gir_ffi/sized_array" require "gir_ffi/zero_terminated" require "gir_ffi/arg_helper" require "gir_ffi/builder" require "gir_ffi/user_defined_object_info" require "gir_ffi/builders/user_defined_builder" require "gir_ffi/version" module GirFFI # Core GirFFI interface. module Core def setup(namespace, version = nil) namespace = namespace.to_s Builder.build_module namespace, version end def define_type(klass) unless klass < GirFFI::ObjectBase raise ArgumentError, "#{klass} is not a GObject class" end klass.prepare_user_defined_class info = klass.gir_info unless info.is_a? UserDefinedObjectInfo raise ArgumentError, "#{klass} is not a user-defined class" end Builders::UserDefinedBuilder.new(info).build_class klass.gtype end end end GirFFI.extend GirFFI::Core gir_ffi-0.16.1/lib/gir_ffi/struct_base.rb0000644000004100000410000000027714524576001020264 0ustar www-datawww-data# frozen_string_literal: true require "gir_ffi/struct_like_base" module GirFFI # Base class for generated classes representing GLib structs. class StructBase < StructLikeBase end end gir_ffi-0.16.1/lib/gir_ffi/field_argument_info.rb0000644000004100000410000000101214524576001021732 0ustar www-datawww-data# frozen_string_literal: true module GirFFI # Class to represent argument info for the argument of a setter method. # Implements the necessary parts of IArgInfo's interface. # TODO: Rename and add direction argument or subclass class FieldArgumentInfo attr_reader :name, :argument_type def initialize(name, type) @name = name @argument_type = type end def direction :in end def ownership_transfer :everything end def skip? false end end end gir_ffi-0.16.1/lib/gir_ffi/ownable.rb0000644000004100000410000000070314524576001017367 0ustar www-datawww-data# frozen_string_literal: true module GirFFI # Module implementing the concept of ownership. Owned objects need to have # their memory freed or ref count lowered when they're garbage collected. # Note that this attribute is generally placed on the nested struct of an # object, and the relevant action is performed when the object's finalizer is # run. module Ownable attr_accessor :owned def owned? owned end end end gir_ffi-0.16.1/lib/gir_ffi/type_base.rb0000644000004100000410000000034214524576001017712 0ustar www-datawww-data# frozen_string_literal: true module GirFFI # Base module for all generated GLib types. module TypeBase def gir_ffi_builder self::GIR_FFI_BUILDER end def gir_info self::GIR_INFO end end end gir_ffi-0.16.1/lib/gir_ffi/builder_helper.rb0000644000004100000410000000141014524576001020721 0ustar www-datawww-data# frozen_string_literal: true module GirFFI # Set of helper methods used in the builders. module BuilderHelper def optionally_define_constant(parent, name) if parent.const_defined? name, false parent.const_get name else parent.const_set name, yield end end def get_or_define_class(namespace, name, parent = nil) klass = optionally_define_constant(namespace, name) do parent ||= yield Class.new parent end if parent && klass.superclass != parent raise "Expected #{klass} to have superclass #{parent}, found #{klass.superclass}" end klass end def get_or_define_module(parent, name) optionally_define_constant(parent, name) { Module.new } end end end gir_ffi-0.16.1/lib/gir_ffi/instance_method_setup.rb0000644000004100000410000000063114524576001022324 0ustar www-datawww-data# frozen_string_literal: true module GirFFI # Methods for setting up instance methods. # # Depends on .gir_ffi_builder being defined in the extending class. module InstanceMethodSetup def setup_instance_method(name) gir_ffi_builder.setup_instance_method name end def setup_instance_method!(name) setup_instance_method name or raise "Unknown method #{name}" end end end gir_ffi-0.16.1/lib/ffi-glib.rb0000644000004100000410000000452214524576001016015 0ustar www-datawww-data# frozen_string_literal: true # Ensure GLib is defined by GirFFI itself raise "The module GLib was already defined elsewhere" if Kernel.const_defined? :GLib require "gir_ffi/core" # Set up the GLib module, bypassing the check for existing modules. This also # creates GLib::Lib. GirFFI::Builders::ModuleBuilder.new("GLib").generate require "ffi-glib/array" require "ffi-glib/byte_array" require "ffi-glib/bytes" require "ffi-glib/destroy_notify" require "ffi-glib/error" require "ffi-glib/hash_table" require "ffi-glib/list" require "ffi-glib/main_loop" require "ffi-glib/ptr_array" require "ffi-glib/s_list" require "ffi-glib/strv" require "ffi-glib/variant" # Module representing GLib's GLib namespace. module GLib load_class :HFunc load_class :HashFunc load_class :EqualFunc load_class :Func # Module for attaching functions from the glib library. This module is # defined by the call to ModuleBuilder#generate above. module Lib attach_function :g_slist_append, [:pointer, :pointer], :pointer attach_function :g_slist_prepend, [:pointer, :pointer], :pointer attach_function :g_slist_reverse, [:pointer], :pointer attach_function :g_list_append, [:pointer, :pointer], :pointer attach_function :g_list_prepend, [:pointer, :pointer], :pointer attach_function :g_list_reverse, [:pointer], :pointer attach_function :g_hash_table_foreach, [:pointer, HFunc, :pointer], :void attach_function :g_hash_table_new, [HashFunc, EqualFunc], :pointer attach_function :g_hash_table_insert, [:pointer, :pointer, :pointer], :void attach_function :g_byte_array_new, [], :pointer attach_function :g_byte_array_append, [:pointer, :pointer, :uint], :pointer attach_function :g_bytes_get_data, [:pointer, :pointer], :pointer attach_function :g_bytes_new, [:pointer, :size_t], :pointer attach_function :g_array_new, [:int, :int, :uint], :pointer attach_function :g_array_append_vals, [:pointer, :pointer, :uint], :pointer attach_function :g_array_get_element_size, [:pointer], :uint attach_function :g_ptr_array_new, [], :pointer attach_function :g_ptr_array_add, [:pointer, :pointer], :void attach_function :g_ptr_array_foreach, [:pointer, Func, :pointer], :pointer attach_function :g_iconv_open, [:pointer, :pointer], :pointer attach_function :g_variant_ref_sink, [:pointer], :pointer end end gir_ffi-0.16.1/lib/gir_ffi-base/0000755000004100000410000000000014524576001016323 5ustar www-datawww-datagir_ffi-0.16.1/lib/gir_ffi-base/gobject.rb0000644000004100000410000000314614524576001020271 0ustar www-datawww-data# frozen_string_literal: true # Ensure GObject is defined by GirFFI itself raise "The module GObject was already defined elsewhere" if Kernel.const_defined? :GObject require "gir_ffi-base/gobject/lib" # The part of the GObject namespace that is needed by GirFFI. # # :reek:TooManyConstants because it needs to hold the type constants. module GObject def self.type_from_name(name) Lib.g_type_from_name name end def self.type_fundamental(gtype) Lib.g_type_fundamental gtype end TYPE_INVALID = type_from_name("invalid") TYPE_NONE = type_from_name("void") TYPE_INTERFACE = type_from_name("GInterface") TYPE_CHAR = type_from_name("gchar") TYPE_UCHAR = type_from_name("guchar") TYPE_BOOLEAN = type_from_name("gboolean") TYPE_INT = type_from_name("gint") TYPE_UINT = type_from_name("guint") TYPE_LONG = type_from_name("glong") TYPE_ULONG = type_from_name("gulong") TYPE_INT64 = type_from_name("gint64") TYPE_UINT64 = type_from_name("guint64") TYPE_ENUM = type_from_name("GEnum") TYPE_FLAGS = type_from_name("GFlags") TYPE_FLOAT = type_from_name("gfloat") TYPE_DOUBLE = type_from_name("gdouble") TYPE_STRING = type_from_name("gchararray") TYPE_POINTER = type_from_name("gpointer") TYPE_BOXED = type_from_name("GBoxed") TYPE_PARAM = type_from_name("GParam") TYPE_OBJECT = type_from_name("GObject") TYPE_GTYPE = type_from_name("GType") TYPE_VARIANT = type_from_name("GVariant") TYPE_ARRAY = Lib.g_array_get_type TYPE_BYTE_ARRAY = Lib.g_byte_array_get_type TYPE_ERROR = Lib.g_error_get_type TYPE_HASH_TABLE = Lib.g_hash_table_get_type TYPE_STRV = Lib.g_strv_get_type end gir_ffi-0.16.1/lib/gir_ffi-base/gobject/0000755000004100000410000000000014524576001017740 5ustar www-datawww-datagir_ffi-0.16.1/lib/gir_ffi-base/gobject/lib.rb0000644000004100000410000000124114524576001021031 0ustar www-datawww-data# frozen_string_literal: true require "ffi/bit_masks" module GObject # Module for attaching functions from the gobject library module Lib extend FFI::Library extend FFI::BitMasks ffi_lib "gobject-2.0" attach_function :g_type_from_name, [:string], :size_t attach_function :g_type_fundamental, [:size_t], :size_t attach_function :g_type_class_ref, [:size_t], :pointer attach_function :g_array_get_type, [], :size_t attach_function :g_byte_array_get_type, [], :size_t attach_function :g_error_get_type, [], :size_t attach_function :g_hash_table_get_type, [], :size_t attach_function :g_strv_get_type, [], :size_t end end gir_ffi-0.16.1/COPYING.LIB0000644000004100000410000006347614524576001014720 0ustar www-datawww-data GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! gir_ffi-0.16.1/gir_ffi.gemspec0000644000004100000410000002740014524576001016215 0ustar www-datawww-data######################################################### # This file has been automatically generated by gem2tgz # ######################################################### # -*- encoding: utf-8 -*- # stub: gir_ffi 0.16.1 ruby lib Gem::Specification.new do |s| s.name = "gir_ffi".freeze s.version = "0.16.1" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.metadata = { "changelog_uri" => "https://github.com/mvz/gir_ffi/blob/master/Changelog.md", "homepage_uri" => "http://www.github.com/mvz/ruby-gir-ffi", "rubygems_mfa_required" => "true", "source_code_uri" => "https://github.com/mvz/gir_ffi" } if s.respond_to? :metadata= s.require_paths = ["lib".freeze] s.authors = ["Matijs van Zuijlen".freeze] s.date = "2023-10-07" s.description = "GirFFI creates bindings for GObject-based libraries at runtime based on introspection\ndata provided by the GObject Introspection Repository (GIR) system. Bindings are created\nat runtime and use FFI to interface with the C libraries. In cases where the GIR does not\nprovide enough or correct information to create sane bindings, overrides may be created.\n".freeze s.email = ["matijs@matijs.net".freeze] s.extra_rdoc_files = ["Changelog.md".freeze, "DESIGN.md".freeze, "README.md".freeze, "TODO.md".freeze] s.files = ["COPYING.LIB".freeze, "Changelog.md".freeze, "DESIGN.md".freeze, "README.md".freeze, "TODO.md".freeze, "docs/Documentation.md".freeze, "docs/Subclassing.md".freeze, "examples/clutter.rb".freeze, "examples/main_loop.rb".freeze, "lib/ffi-glib.rb".freeze, "lib/ffi-glib/array.rb".freeze, "lib/ffi-glib/byte_array.rb".freeze, "lib/ffi-glib/bytes.rb".freeze, "lib/ffi-glib/container_class_methods.rb".freeze, "lib/ffi-glib/destroy_notify.rb".freeze, "lib/ffi-glib/error.rb".freeze, "lib/ffi-glib/hash_table.rb".freeze, "lib/ffi-glib/list.rb".freeze, "lib/ffi-glib/list_methods.rb".freeze, "lib/ffi-glib/main_loop.rb".freeze, "lib/ffi-glib/ptr_array.rb".freeze, "lib/ffi-glib/s_list.rb".freeze, "lib/ffi-glib/strv.rb".freeze, "lib/ffi-glib/variant.rb".freeze, "lib/ffi-gobject.rb".freeze, "lib/ffi-gobject/closure.rb".freeze, "lib/ffi-gobject/initially_unowned.rb".freeze, "lib/ffi-gobject/object.rb".freeze, "lib/ffi-gobject/object_class.rb".freeze, "lib/ffi-gobject/param_spec.rb".freeze, "lib/ffi-gobject/ruby_closure.rb".freeze, "lib/ffi-gobject/value.rb".freeze, "lib/ffi-gobject_introspection.rb".freeze, "lib/ffi-gobject_introspection/g_error.rb".freeze, "lib/ffi-gobject_introspection/gobject_type_init.rb".freeze, "lib/ffi-gobject_introspection/i_arg_info.rb".freeze, "lib/ffi-gobject_introspection/i_base_info.rb".freeze, "lib/ffi-gobject_introspection/i_callable_info.rb".freeze, "lib/ffi-gobject_introspection/i_callback_info.rb".freeze, "lib/ffi-gobject_introspection/i_constant_info.rb".freeze, "lib/ffi-gobject_introspection/i_enum_info.rb".freeze, "lib/ffi-gobject_introspection/i_field_info.rb".freeze, "lib/ffi-gobject_introspection/i_flags_info.rb".freeze, "lib/ffi-gobject_introspection/i_function_info.rb".freeze, "lib/ffi-gobject_introspection/i_interface_info.rb".freeze, "lib/ffi-gobject_introspection/i_object_info.rb".freeze, "lib/ffi-gobject_introspection/i_property_info.rb".freeze, "lib/ffi-gobject_introspection/i_registered_type_info.rb".freeze, "lib/ffi-gobject_introspection/i_repository.rb".freeze, "lib/ffi-gobject_introspection/i_signal_info.rb".freeze, "lib/ffi-gobject_introspection/i_struct_info.rb".freeze, "lib/ffi-gobject_introspection/i_type_info.rb".freeze, "lib/ffi-gobject_introspection/i_union_info.rb".freeze, "lib/ffi-gobject_introspection/i_unresolved_info.rb".freeze, "lib/ffi-gobject_introspection/i_value_info.rb".freeze, "lib/ffi-gobject_introspection/i_vfunc_info.rb".freeze, "lib/ffi-gobject_introspection/lib.rb".freeze, "lib/ffi-gobject_introspection/strv.rb".freeze, "lib/gir_ffi-base.rb".freeze, "lib/gir_ffi-base/gobject.rb".freeze, "lib/gir_ffi-base/gobject/lib.rb".freeze, "lib/gir_ffi.rb".freeze, "lib/gir_ffi/allocation_helper.rb".freeze, "lib/gir_ffi/arg_helper.rb".freeze, "lib/gir_ffi/array_element_convertor.rb".freeze, "lib/gir_ffi/boolean.rb".freeze, "lib/gir_ffi/boxed_base.rb".freeze, "lib/gir_ffi/builder.rb".freeze, "lib/gir_ffi/builder_helper.rb".freeze, "lib/gir_ffi/builders/argument_builder.rb".freeze, "lib/gir_ffi/builders/argument_builder_collection.rb".freeze, "lib/gir_ffi/builders/base_argument_builder.rb".freeze, "lib/gir_ffi/builders/base_method_builder.rb".freeze, "lib/gir_ffi/builders/base_return_value_builder.rb".freeze, "lib/gir_ffi/builders/base_type_builder.rb".freeze, "lib/gir_ffi/builders/c_to_ruby_convertor.rb".freeze, "lib/gir_ffi/builders/callback_argument_builder.rb".freeze, "lib/gir_ffi/builders/callback_builder.rb".freeze, "lib/gir_ffi/builders/callback_return_value_builder.rb".freeze, "lib/gir_ffi/builders/closure_argument_builder.rb".freeze, "lib/gir_ffi/builders/closure_convertor.rb".freeze, "lib/gir_ffi/builders/closure_return_value_builder.rb".freeze, "lib/gir_ffi/builders/closure_to_pointer_convertor.rb".freeze, "lib/gir_ffi/builders/constant_builder.rb".freeze, "lib/gir_ffi/builders/constructor_builder.rb".freeze, "lib/gir_ffi/builders/enum_builder.rb".freeze, "lib/gir_ffi/builders/field_builder.rb".freeze, "lib/gir_ffi/builders/flags_builder.rb".freeze, "lib/gir_ffi/builders/full_c_to_ruby_convertor.rb".freeze, "lib/gir_ffi/builders/function_builder.rb".freeze, "lib/gir_ffi/builders/initializer_builder.rb".freeze, "lib/gir_ffi/builders/initializer_return_value_builder.rb".freeze, "lib/gir_ffi/builders/interface_builder.rb".freeze, "lib/gir_ffi/builders/mapping_method_builder.rb".freeze, "lib/gir_ffi/builders/marshalling_method_builder.rb".freeze, "lib/gir_ffi/builders/method_template.rb".freeze, "lib/gir_ffi/builders/module_builder.rb".freeze, "lib/gir_ffi/builders/null_argument_builder.rb".freeze, "lib/gir_ffi/builders/null_class_builder.rb".freeze, "lib/gir_ffi/builders/null_convertor.rb".freeze, "lib/gir_ffi/builders/null_return_value_builder.rb".freeze, "lib/gir_ffi/builders/object_builder.rb".freeze, "lib/gir_ffi/builders/pointer_value_convertor.rb".freeze, "lib/gir_ffi/builders/property_argument_builder.rb".freeze, "lib/gir_ffi/builders/property_builder.rb".freeze, "lib/gir_ffi/builders/property_return_value_builder.rb".freeze, "lib/gir_ffi/builders/registered_type_builder.rb".freeze, "lib/gir_ffi/builders/return_value_builder.rb".freeze, "lib/gir_ffi/builders/ruby_to_c_convertor.rb".freeze, "lib/gir_ffi/builders/signal_closure_builder.rb".freeze, "lib/gir_ffi/builders/struct_builder.rb".freeze, "lib/gir_ffi/builders/struct_like.rb".freeze, "lib/gir_ffi/builders/type_builder.rb".freeze, "lib/gir_ffi/builders/unintrospectable_boxed_builder.rb".freeze, "lib/gir_ffi/builders/unintrospectable_builder.rb".freeze, "lib/gir_ffi/builders/union_builder.rb".freeze, "lib/gir_ffi/builders/user_defined_builder.rb".freeze, "lib/gir_ffi/builders/vfunc_argument_builder.rb".freeze, "lib/gir_ffi/builders/vfunc_builder.rb".freeze, "lib/gir_ffi/builders/with_layout.rb".freeze, "lib/gir_ffi/callback_base.rb".freeze, "lib/gir_ffi/class_base.rb".freeze, "lib/gir_ffi/core.rb".freeze, "lib/gir_ffi/enum_base.rb".freeze, "lib/gir_ffi/enum_like_base.rb".freeze, "lib/gir_ffi/error_argument_info.rb".freeze, "lib/gir_ffi/error_type_info.rb".freeze, "lib/gir_ffi/ffi_ext.rb".freeze, "lib/gir_ffi/ffi_ext/pointer.rb".freeze, "lib/gir_ffi/field_argument_info.rb".freeze, "lib/gir_ffi/flags_base.rb".freeze, "lib/gir_ffi/g_type.rb".freeze, "lib/gir_ffi/glib_error.rb".freeze, "lib/gir_ffi/in_pointer.rb".freeze, "lib/gir_ffi/info_ext.rb".freeze, "lib/gir_ffi/info_ext/full_type_name.rb".freeze, "lib/gir_ffi/info_ext/i_arg_info.rb".freeze, "lib/gir_ffi/info_ext/i_callable_info.rb".freeze, "lib/gir_ffi/info_ext/i_callback_info.rb".freeze, "lib/gir_ffi/info_ext/i_field_info.rb".freeze, "lib/gir_ffi/info_ext/i_function_info.rb".freeze, "lib/gir_ffi/info_ext/i_property_info.rb".freeze, "lib/gir_ffi/info_ext/i_registered_type_info.rb".freeze, "lib/gir_ffi/info_ext/i_signal_info.rb".freeze, "lib/gir_ffi/info_ext/i_type_info.rb".freeze, "lib/gir_ffi/info_ext/i_unresolved_info.rb".freeze, "lib/gir_ffi/info_ext/i_value_info.rb".freeze, "lib/gir_ffi/info_ext/i_vfunc_info.rb".freeze, "lib/gir_ffi/info_ext/safe_constant_name.rb".freeze, "lib/gir_ffi/info_ext/safe_function_name.rb".freeze, "lib/gir_ffi/instance_method_setup.rb".freeze, "lib/gir_ffi/interface_base.rb".freeze, "lib/gir_ffi/lib_c.rb".freeze, "lib/gir_ffi/method_setup.rb".freeze, "lib/gir_ffi/method_stubber.rb".freeze, "lib/gir_ffi/module_base.rb".freeze, "lib/gir_ffi/object_base.rb".freeze, "lib/gir_ffi/object_store.rb".freeze, "lib/gir_ffi/ownable.rb".freeze, "lib/gir_ffi/property_not_found_error.rb".freeze, "lib/gir_ffi/receiver_argument_info.rb".freeze, "lib/gir_ffi/receiver_type_info.rb".freeze, "lib/gir_ffi/registered_type_base.rb".freeze, "lib/gir_ffi/return_value_info.rb".freeze, "lib/gir_ffi/signal_not_found_error.rb".freeze, "lib/gir_ffi/sized_array.rb".freeze, "lib/gir_ffi/struct.rb".freeze, "lib/gir_ffi/struct_base.rb".freeze, "lib/gir_ffi/struct_like_base.rb".freeze, "lib/gir_ffi/type_base.rb".freeze, "lib/gir_ffi/type_map.rb".freeze, "lib/gir_ffi/unintrospectable_boxed_info.rb".freeze, "lib/gir_ffi/unintrospectable_signal_info.rb".freeze, "lib/gir_ffi/unintrospectable_type_info.rb".freeze, "lib/gir_ffi/union.rb".freeze, "lib/gir_ffi/union_base.rb".freeze, "lib/gir_ffi/user_defined_object_info.rb".freeze, "lib/gir_ffi/user_defined_property_info.rb".freeze, "lib/gir_ffi/variable_name_generator.rb".freeze, "lib/gir_ffi/version.rb".freeze, "lib/gir_ffi/vfunc_implementation.rb".freeze, "lib/gir_ffi/zero_terminated.rb".freeze] s.homepage = "http://www.github.com/mvz/ruby-gir-ffi".freeze s.licenses = ["LGPL-2.1+".freeze] s.rdoc_options = ["--main".freeze, "README.md".freeze] s.required_ruby_version = Gem::Requirement.new(">= 2.7.0".freeze) s.rubygems_version = "3.3.15".freeze s.summary = "FFI-based GObject binding using the GObject Introspection Repository".freeze if s.respond_to? :specification_version then s.specification_version = 4 end if s.respond_to? :add_runtime_dependency then s.add_development_dependency(%q.freeze, ["~> 2.0"]) s.add_runtime_dependency(%q.freeze, ["~> 1.16", ">= 1.16.3"]) s.add_runtime_dependency(%q.freeze, ["~> 0.1.1"]) s.add_development_dependency(%q.freeze, ["~> 5.12"]) s.add_development_dependency(%q.freeze, ["~> 1.3", ">= 1.3.1"]) s.add_development_dependency(%q.freeze, ["~> 13.0"]) s.add_development_dependency(%q.freeze, ["~> 0.2.0"]) s.add_development_dependency(%q.freeze, ["~> 3.0"]) s.add_development_dependency(%q.freeze, ["~> 3.5"]) s.add_development_dependency(%q.freeze, ["~> 1.56"]) s.add_development_dependency(%q.freeze, ["~> 0.32.2"]) s.add_development_dependency(%q.freeze, ["~> 0.5.2"]) s.add_development_dependency(%q.freeze, ["~> 1.19"]) s.add_development_dependency(%q.freeze, ["~> 0.22.0"]) else s.add_dependency(%q.freeze, ["~> 2.0"]) s.add_dependency(%q.freeze, ["~> 1.16", ">= 1.16.3"]) s.add_dependency(%q.freeze, ["~> 0.1.1"]) s.add_dependency(%q.freeze, ["~> 5.12"]) s.add_dependency(%q.freeze, ["~> 1.3", ">= 1.3.1"]) s.add_dependency(%q.freeze, ["~> 13.0"]) s.add_dependency(%q.freeze, ["~> 0.2.0"]) s.add_dependency(%q.freeze, ["~> 3.0"]) s.add_dependency(%q.freeze, ["~> 3.5"]) s.add_dependency(%q.freeze, ["~> 1.56"]) s.add_dependency(%q.freeze, ["~> 0.32.2"]) s.add_dependency(%q.freeze, ["~> 0.5.2"]) s.add_dependency(%q.freeze, ["~> 1.19"]) s.add_dependency(%q.freeze, ["~> 0.22.0"]) end end gir_ffi-0.16.1/Changelog.md0000644000004100000410000005660414524576001015464 0ustar www-datawww-data# Changelog ## 0.16.1 / 2023-10-07 * Support Ruby 3.2 ([#331] by [mvz]) * Require at least ffi 1.16.3 to avoid 'Can't modify frozen Hash' error ([#350] by [mvz]) [mvz]: https://github.com/mvz [#331]: https://github.com/mvz/gir_ffi/pull/331 [#350]: https://github.com/mvz/gir_ffi/pull/350 ## 0.16.0 / 2022-05-21 * Support Ruby 3.1 * Rename `#object_class` to `#class_struct` * Remove `GObject.object_class_from_instance` * Limit public interface of `BaseMethodBuilder` * Remove deprecated methods from `GObject::Object` * Stop accepting blocks when defining a type * Check parameter direction in signal argument conversion * Drop support for JRuby * Drop support for Ruby 2.6 ## 0.15.9 / 2021-12-05 * Skip setting destroy notifier state if types don't make sense * Handle functions with multiple user-supplied callback arguments ## 0.15.8 / 2021-11-20 * Drop support for Ruby 2.5 * Bump minimum supported version of gobject-introspection to 1.56.0 * Bump minimum supported version of glib to 2.56.0 * Handle functions that have swapped closure annotation * Handle GPtrArray arguments in signal handlers ## 0.15.7 / 2021-01-15 * Handle sized arrays with interface element types ## 0.15.6 / 2021-01-10 * Officially support Ruby 3.0 * Rely on `GObject.boxed_free` to free GValue objects * Require 'set' in `callback_base.rb`, which needs it (thanks, Jordan Webb!) * Make SizedArray handle `:filename` elements ## 0.15.5 / 2020-11-13 * Make building and finding metaclasses via `Builder.build_class` work again ## 0.15.4 / 2020-11-01 * Support disguised object class structs * Handle the case where vfunc object arguments are null * Bail out earlier when trying to register non-GObject class * Small improvements * Use `Module#prepend` for overrides * Clean up initialization of structs, unions, and boxed types * Make `GObject::Object#store_pointer` private like in the superclass * Handle creating SizedArray of uint8 from a string * Improve derived class setup * Improve List and SList methods * Make `ByteArray#append` return self * Improve packaging infrastructure (thanks, utkarsh2102!) ## 0.15.3 / 2020-06-14 * Officially support Ruby 2.7 * Officially drop support for Ruby 2.4 * Store classes representing inline callback types in the class that defines them instead of in the main namespace, thus avoiding some potential name clashes * Update development dependencies * Various code quality improvements * Record approved licenses for dependencies ## 0.15.2 / 2019-11-29 * Load girepository-1.0 library in a way that does not require installing a development package. ## 0.15.1 / 2019-10-20 * Allow access to properties for unintrospectable classes. ## 0.15.0 / 2019-10-19 * Drop support for gobject-introspection below 1.46, the version available in Ubuntu Xenial. * Merge extended property getter and setter into regular ones. This means you can always just use `#get_property` and `#set_property`. The methods `#get_property_extended` and `#set_property_extended` are deprecated and will be removed in GirFFI version 0.16 or later. * Support setting ByteArray properties directly with string values. * Target Ruby 2.4+ * Implement getting and setting of flag properties and GValues. * Add support for basic hashtable values larger than pointer. * Support unintrospectable classes not derived from GObject but from some other fundamental object type. * Make GPtrArray work with boxed types. * Do not try to ref method reciever for struct instance methods marking the instance receiver as transfer `:everything`. * Support signals with GError arguments. * Cache various methods on IBaseInfo and its subclasses. * Generate aliases for accessor methods instead of relying on `method_missing`. ## 0.14.1 / 2018-09-27 * Add enum values as constants in the generated module. ## 0.14.0 / 2018-09-25 * Do not generate field accessors for Object types. Object data should normally not be accessed directly. ## 0.13.1 / 2018-09-24 * Silence some warnings. * Allow overrides to be applied using `Module#prepend`, as an alternative to alias chaining. * Make `ZeroTerminated` array work with enum elements. * Various refactorings. * Improve consistency of conversion between symbols and integers for enum types. ## 0.13.0 / 2018-09-08 * Drop support for Ruby 2.1 * Support GLib 2.58 * Add `setup_method!` and `setup_instance_method!`, that raise an error when the given method is not found. ## 0.12.1 / 2018-05-20 * Restore support for Ruby 2.1 and 2.2 ## 0.12.0 / 2018-03-24 * Drop support for GLib::IConv, which is no longer introspectable in glib 2.56. * Drop support for Ruby 2.1 and 2.2 * Add support for Ruby 2.5 ## 0.11.4 / 2017-09-19 * Support glib 2.54 and gobject-introspection 1.54 ## 0.11.3 / 2017-05-05 * Allow conversion to native Boolean from any Ruby value ## 0.11.2 / 2017-04-20 * Allow vfunc implementation using a regular method ## 0.11.1 / 2017-01-07 * Fix build on JRuby * Allow clearing properties that take a GObject value * Handle GLists requiring an Interface type ## 0.11.0 / 2016-10-16 * Internal test and code improvements. Some internal APIs have been removed or changed. * Make `Strv#each` thread-safe. * Drop support for CRuby 2.0. * Move `::type_init` and base `Strv` implementation into `GObjectIntrospection`, making it stand-alone. * Move `GLib::Boolean` to `GirFFI::Boolean`. * Guard against instantiating abstract classes using the default constructor. * Handle user-defined properties containing dashes * Handle user-defined properties of a large number of types ## 0.10.2 / 2016-04-29 * Update `ffi-bit_masks` dependency and remove monkey-patch * Support gobject-introspection version 1.48 ## 0.10.1 / 2016-03-28 * Restore JRuby compatibility. - Introduce #owned to flag unions and structs for release at garbage collection time. In JRuby's implementation, FFI::Pointer does not implement #autorelease= and #autorelease?, so this different technique is used to free pointers allocated by GLib. It is in fact doubtful that setting autorelease had any actual effect even on CRuby. - Immediately free string pointers whose ownership is transfered. Again, the #autorelease technique doesn't work on JRuby. - Fix handling of callee-allocated out parameters in vfuncs. The `put_pointer` method was wrongly called, and JRuby is more picky about what types that method expects, exposing the bug. ## 0.10.0 / 2016-03-23 * Ensure ownership of created RubyClosure objects ## 0.10.0.pre1 / 2016-03-22 * Rework generated method code to use less indirection. * Remove unused classes and methods * Clearly distinguish boxed types from other structs * Take ownership transfer into account in generated methods * Properly free unions, structs and boxed types owned by GirFFI * Block access to fields that have disguised types ## 0.9.5 / 2016-03-05 * Abort if modules were defined earlier, e.g., through the gems from the ruby-gnome family. * Extend integration testing with GObjectIntrospection's test libraries. * Find signals on user-defined types. * Allow getting and setting of properties with a callback value. * Handle pointer-like signal arguments such as GList. * Handle static methods on interface modules. * Free most self-allocated boxed types using `GObject.boxed_free`. * Correctly assign length arguments for zero-terminated arguments ## 0.9.4 / 2016-02-22 * Pass nil user data as null pointer, and store a missing callback as nil. This avoids passing a null callback and a non-null user data value, which causes problems with `vte_terminal_spawn_sync()` and perhaps other functions. ## 0.9.3 / 2016-02-20 * Make allow-none arguments optional in Ruby * Add Clutter example * Clean up mainloop example * Use bit masks for relevant functions in GObjectIntrospection ## 0.9.2 / 2016-02-05 * Do not create a property accessor when a corresponding getter method exists ## 0.9.1 / 2016-02-04 * Add field accessors for Object types for fields that don't have corresponding properties or getter methods * Improve error handling for signals and properties that are not found * Handle signals without GIR data * Add interrupt handler to break out of main loops ## 0.9.0 / 2016-01-21 * Propagate exceptions from callbacks during event loops * Make default object constructor take a hash of properties * Fix implementation of `ObjectBase.object_class` * Make object class struct types inherit from their parent structs. This makes parent methods and fields available. * Use `ObjectBase.object_class` instead of old `Object#type_class` to find properties * Remove `Object#type_class` * Automatically unpack GValue return values * Use a BitMask to handle flag values * Handle callback arguments as Ruby block arguments * Use user data and destroy notify arguments to automate callback cleanup. This means you can no longer supply your own user data and notifiers. * Support CRuby 2.3 and Rubinius 3.x * Drop support for JRuby 1.7 and Rubinius 2.x. ## 0.8.6 / 2015-12-09 * Change handling of initializers in subclasses * Subclasses with their own GType revert to the default GObject constructor * Subclasses cannot use their parent classes' non-default contructors * Find signals in ancestor classes of unintrospectable types ## 0.8.5 / 2015-12-04 * Improve GObject::Value * Make `#wrap_ruby_value` work for object classes * Use non-deprecated methods for getting and setting char values * Make `set_value` and `get_value` work for interface types ## 0.8.4 / 2015-12-03 * Handle classes with lower-case names * Make `ObjectBase` a `DataConverter` so FFI handles it natively * Use more of gobject-introspection's test libraries for testing * Simplify constructor overrides: Custom initializers will no longer be overwritten when setting up the corresponding constructor. * Override `GObject::Object.new` to not require a GType argument ## 0.8.3 / 2015-11-13 * Fix handling of signal handler return values * Do not create setters for properties that cannot be set ## 0.8.2 / 2015-10-10 * Use inherited constructor for boxed types * Make `InOutPointer` work correctly for boxed types * Make `.for` work with boxed types * Make `#set_value` work with boxed types * Make GObject::Value support nil type: * Make `.wrap_ruby_value(nil)` work * Make `#set_value` and `#get_value` work when the type is `TYPE_INVALID` * Make `.for_gtype` work with `TYPE_INVALID` and `TYPE_NONE` * Make `.from(nil)` return a `GObject::Value` instead of nil * Make `#set_ruby_value` private * Make `GObject::Object.signal_emit` work with gobject-introspection 1.46 * Replace or remove all custom `.new` methods * Make `setup_method` and `setup_instance_method` handle symbol arguments ## 0.8.1 / 2015-10-04 * Handle struct array fields with related length fields * Update test library build process ## 0.8.0 / 2015-09-18 * Drop official support for CRuby 1.9.3 * Officially support JRuby 9.0.0.0 * Change handling of initializers in custom subclasses ## 0.7.10 / 2015-09-16 * Allow `ffi-gobject` and `ffi-glib` to be required directly * Improve documentation * Remove arbitrary refcount check from finalizer (by John Cupitt) ## 0.7.9 / 2015-05-05 * Unset GValues in finalizer * Dereference GObjects in finalizer * Increase refcount for ingoing :object arguments of functions with full ownership transfer * Increase refcount for receiver arguments with full ownership transfer * Increase refcount for ingoing :object arguments of vfuncs with no ownership transfer * Increase refcount for :object return values of vfuncs with full transfer * Increase refcount for outgoing :object arguments of vfuncs with full ownership transfer * Support Ruby 2.2 * Rename several methods. The old names are deprecated and will be removed in 0.8.0. ## 0.7.8 / 2014-12-09 * Support constants with a falsy value * Support type aliases that resolve to a type that is not introspectable * Support callback arguments with direction :inout * Provide `GObject.signal_connect_after` and `GObject::Object.signal_connect_after` * Handle setting GValues (and hence, properties) that have enum values * Various refactorings & coding style cleanups ## 0.7.7 / 2014-10-21 * Handle introspecting boolean constants * Provide `config.h` for versions of the test libs that need it * Include gemspec in the gem * Avoid needless casting from string to symbol by making `#setup_and_call` take a string * Avoid argument list unpacking by making `#setup_and_call` take an array of arguments rather than a variable number of arguments * Remove old example files * Let rubygems know about required Ruby version * Various clean-ups ## 0.7.6 / 2014-08-22 * Work around `respond_to?` behavior in JRuby 1.6.13 * Deprecate `setup_class` in favor of `load_class` * Support GValue containing GArray * Provide constant `TYPE_BYTE_ARRAY` * Don't recurse looking for signals and properties * Clean up generated code: * Avoid use of an ignored dummy argument * Clean up trailing whitespace * Drop support for Ruby 1.9.2 * Allow data argument for `GObject::Object#signal_connect` * Let Ruby threads run during GLib's main loop * Make all dependencies versioned * Various refactoring & code cleanup ## 0.7.5 / 2014-06-22 * Use closures as signal handlers, rather than callbacks * Obtain reference to GVariant on creation * Make struct arguments work in JRuby * Various refactoring & code cleanup ## 0.7.4 / 2014-05-03 * Correctly handle closure data arguments originating from C * Handle callee-allocated simple types for callbacks and functions * Handle callback out parameters that are zero-terminated arrays * Handle virtual functions with GError arguments * Support the GBytes type * Handle virtual functions returning GObjects * Avoid overwriting methods with getters for properties with dashes in the name ## 0.7.3 / 2014-03-23 * Restore proper handling of enums in callback arguments * Simplify Rake configuration * Various small fixes * Remove remaining Ruby 1.8 version checks ## 0.7.2 / 2014-01-18 * Officially drop Ruby 1.8 compatibility. * Store GType of generated types in a constant, removing the need to generate a separate `get_gtype` method for each type. ## 0.7.1 / 2014-01-17 * Handle method setup for methods with unsafe names (i.e., `g_iconv()`) * Add override for GLib::IConv.open ## 0.7.0 / 2014-01-11 * Type handling: * Handle c arrays with separate length argument for signals * Handle GHashTable values of type `:gint8` and `:guint32` * Handle signals with int64, Strv, uint64 arguments * Handle arrays of integers cast as pointers * Handle fields of callback type * Handle nested GHashTable * Argument handling: * Refactor argument builder system * Improve handling of user data arguments * Handle signal and callback arguments with direction :out * Handle aliases of container types by making the element type optional * Handle signal and callback return values that need conversion * User defined types: * Pass explicit receiver to initialization block for UserDefinedTypeInfo * Allow user defined types that are anonymous Ruby classes * Register defined properties in a subclass * Support setting virtual function implementations in a subclass * Support adding an interface to a subclass * Support implementing an interface's virtual functions in a subclass * Use FFI's DataConvertor system to handle enums and callbacks * Stop using deprecated GValueArray to construct argument array for `signal_emit` * Make `ITypeInfo#g_type` return correct value for c arrays * Make `get_property` and `set_property` less smart, moving conversion into the property accessor definitions * Make `GObject::Value#get_value` handle enums and flags * Clean up deprecated methods ## 0.6.7 / 2013-09-28 * Uniform handling of callback, signal and method arguments * Automatically convert array elements to GValue * Support inline array fields * Support struct fields * Improved field setters and getters * Support many more types of properties * Support skipped arguments and return values * Fix refcount for the result of IBaseInfo#container * Check bounds in GLib::PtrArray#index and GLib::Array#index * Deprecate several methods * Lots of refactoring ## 0.6.6 / 2013-08-05 * Handle GArrays of booleans and structs * Improve handling of gbooleans ## 0.6.5 / 2013-08-03 * Handle inline arrays of structs * Implement equality operator for container types * Fix element size calculation for GArray ## 0.6.4 / 2013-06-30 * Represent enum types by modules wrapping `FFI::Enum` * Support functions on enums * Handle zero-terminated arrays of types other than int32 * Add override for `GLib::Variant#get_string` * Handle non-throwing arguments and return values of type GError * Handle arguments and return values of type GPtrArray * Handle caller-allocated arguments of type GArray * Deprecate `GObject::Value#ruby_value`, replacing it with `#get_value` ## 0.6.3 / 2013-06-15 * Make use of enums as element type for GHashTable and other containers work ## 0.6.2 / 2013-06-14 * Handle introspectable types with introspectable parent types ## 0.6.1 / 2013-06-09 * Handle SizedArray containing enums ## 0.6.0 / 2013-06-07 * Support Rubinius * Lots of refactoring ## 0.5.2 / 2013-04-23 * Handle signal details in `GObject.signal_connect` and `.signal_emit` * Make `GValue#set_value` check object GType compatibility * Eliminate GObject::Helper module * Handle more argument types * Support Ruby 2.0.0 ## 0.5.1 / 2013-02-01 * Properly handle zero-terminated arrays of `:filename` * Loosen dependencies on ffi and minitest ## 0.5.0 / 2013-01-19 * Update ffi dependency * Add finalizer to release memory for IBaseInfo and descendents * Remove deprecated methods * Remove pretty-printing functionality * Refactor argument handling ## 0.4.3 / 2012-11-02 * Remove gobject-introspection version check * Make tests pass with gobject-introspection 1.34 * Ongoing refactoring ## 0.4.2 / 2012-09-22 * Make objects and interfaces wrap poiners in the class that matches their GType. ## 0.4.1 / 2012-09-18 * Remove workarounds for older versions of gobject-introspection * Mark certain methods as deprecated. These will be removed in 0.5.0 * Handle :filename type arguments in InPointer * Refactoring ## 0.4.0 / 2012-08-24 * Move Gtk+ bindings to their own gem (`gir_ffi-gtk`). ## 0.3.2 / 2012-08-24 * Correctly set FFI return type when callbacks that return GObjects have incomplete type specification. ## 0.3.1 / 2012-05-13 * Correctly map Interface types in callbacks. ## 0.3.0 / 2012-04-09 * Improve process of defining initializers in derived classes. * Make interfaces know their GType. * Make classes created by the Unintrospectable builder know their GType. * Create property accessors instead of field accessors for GObjects. * Add Ruby-style getter and setter methods (by Antonio Terceiro). * Add `#signal_connect` instance method (by Antonio Terceiro). * Make GirFFI's tests pass with gobject-introspection 0.10. * Improve unintrospectable type handling. * Bug fixes and refactorings. * Start implementing `#define_type`, for creating descendent types that the GObject system knows about. ## 0.2.3 / 2011-12-31 * Fix issue #7: methods that take GValues will autoconvert other values. * Fix method lookup when include'ing a module that is an Interface. * Various refactorings. ## 0.2.2 / 2011-12-07 * Fix issue #19: Check if a GLib::PtrArray.add method was generated before attempting to remove it. * Fix two issues with pretty printing that made output for GLib have syntax errors. ## 0.2.1 / 2011-11-20 * Fix handling of output parameters that are arrays of pointers to structures (i.e., of type `Foo***`). ## 0.2.0 / 2011-11-19 * Add support for properties, with `#get_property` and `#set_property`. * Add support for fields. - Create field accessor methods. - Get rid of `#[]` and `#[]=`. * Explicitely load `libgirepository` with ABI version 1. * Improve implementation of GLib container classes (GList etc.): - Real constructors. - `#append` and friends are instance methods now. - Conversion methods to cast Ruby containers to GLib containers. * Start implementing pretty printing. * Various refactorings. ## 0.1.0 / 2011-10-28 * Put bindings for GObjectIntrospection in their own namespace. * `GirFFI.setup` no longer loads overrides. * Add `ffi-gtk2` and `ffi-gtk3` files for loading Gtk+ overrides. ## 0.0.14 / 2011-10-28 * Support GObject Introspection version 1.30: - Add support for layouts with fixed-length arrays. - Handle type names starting with underscores. - Call `g_signal_emitv` directly to avoid conflict in introspection info with earlier versions of GObject Introspection. ## 0.0.13 / 2011-09-09 * Remove IErrorDomain related code. This functinality was removed from GObject Introspection in version 1.29.17 ## 0.0.12 / 2011-09-04 * No longer use `_id2ref` to locate objects past as user data pointers. * Fix failing tests on JRuby. ## 0.0.11 / 2011-08-22 * Change interface to the underlying builder in generated modules and classes. * Handle string, enum, union, flags signal arguments. * Handle string arguments in `GObject.signal_emit`. * Handle enum signal arguments. * Fix finding signals in non-introspectable types. * Fix method setup in non-introspectable types. * Refactoring. ## 0.0.10 / 2011-05-18 * Handle GObject interfaces properly. * Create types only defined by the GType system. * Support GType array return values. ## 0.0.9 / 2011-05-02 * More complete support for the basic types. * Improved support for GList, GSList, GStrv, and GValue. * Add support for GHashTable, GVariant, GByteArray, and GArray. * Generate constants. * When setting up a module, set up its dependencies as well. * Test against the GIMarshallingTests test namespace. * Use minitest/spec for testing. * Various bug fixes and internal improvements. ## 0.0.8 / 2011-04-08 * Generate modules with names starting with a lowercase letter (like `cairo`). * Allow specifying the typelib version on setup. * Rename methods `#methods` and `#type` of the introspection classes to avoid clashing with standard Ruby methods. * Refactoring. ## 0.0.7 / 2011-04-01 * Support gobject-introspection 0.10, drop support for earlier versions. - Use Regress, not Everything, for testing. - Deal with functions that are no longer introspectable. * Correctly handle constructors that declare their return type different from their class. * Implement `RubyClosure`, a `GObject::Closure` for handling ruby callbacks. * Handle GLib's singly and doubly linked lists. * Handle callback types defined in-place (like `Closure`'s `marshal`). * Refactoring. ## 0.0.6 / 2011-03-01 * Cast returned GObjects to their actual type. * Properly cast callback arguments. * Handle the case where functions formally return interfaces. * Make sure Gtk::Window has the correct number of references after creation. * Refactoring and some small fixes. ## 0.0.5 / 2010-12-30 * Don't create instance methods out of functions and vice versa. * Find signals on interfaces, too. * Implement tests for most of Everything. * Correctly handle array + size arguments. * Handle most other argument types. * Various internal changes and other fixes. ## 0.0.4 / 2010-12-14 * Lots of changes to the internals. * Handle out-only arguments. * Make use of callbacks from other namespaces work. * Handle virtual methods where the invoker method has a different name. * Implement usable `signal_connect` and `signal_emit`. * Sink floating references when creating a GObject. * Implement Union type. * Many small bug fixes. ## 0.0.3 / 2010-11-19 * Update to restore Ruby 1.9 support. * Handle functions with the 'throws' property set. * Handle classes without specified fields. ## 0.0.2 / 2010-11-14 * Several fixes to method creation. ## 0.0.1 / 2010-10-25 * Initial release.