module GirFFI # The InPointer class handles conversion from ruby types to pointers for # arguments with direction :in. This is used for arguments that are # arrays, strings, or interfaces. class InPointer < FFI::Pointer def self.from_array type, ary return if !ary case type when :utf8, :filename from_utf8_array ary when :gboolean from_boolean_array ary when Symbol from_basic_type_array type, ary when Class if type == GObject::Value from_gvalue_array type, ary else from_struct_array type, ary end when Module from_enum_array type, ary when Array from_interface_pointer_array ary else raise NotImplementedError, type end end def self.from type, val return if !val case type when :utf8, :filename from_utf8 val when :gint32, :guint32, :gint8 self.new val when Module self.new type[val] when :void from_object val else raise NotImplementedError, type end end class << self # FIXME: Hideous def from_object obj return nil if obj.nil? return obj.to_ptr if obj.respond_to? :to_ptr FFI::Pointer.new(obj.object_id).tap {|ptr| ArgHelper::OBJECT_STORE[ptr.address] = obj } end private 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_interface_pointer_array ary from_basic_type_array :pointer, ary.map {|ifc| ifc.to_ptr} 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 type_size = type::Struct.size length = ary.length ptr = AllocationHelper.safe_malloc length * type_size ary.each_with_index do |item, idx| type.copy_value_to_pointer item, ptr, idx * type_size end new ptr end def from_enum_array type, ary from_basic_type_array :int32, ary.map {|sym| type.to_native sym, nil } end def from_utf8 str len = str.bytesize ptr = AllocationHelper.safe_malloc(len + 1).write_string(str).put_char(len, 0) new ptr end def from_basic_type_array type, ary ffi_type = TypeMap.map_basic_type type length = ary.length size = FFI.type_size ffi_type block = AllocationHelper.safe_malloc size * (length + 1) block.send "put_array_of_#{ffi_type}", 0, ary block.send("put_#{ffi_type}", length * size, (ffi_type == :pointer ? nil : 0)) new block end end end end