Spec-Zone.ru › Ruby 3.3

модуль Fiddle::Importer

Включенные модули:
Fiddle, Fiddle::CParser

DSL, который предоставляет средства для динамической загрузки библиотек и построения модулей вокруг них, включая вызов внешних функций в загруженной библиотеке C.

Пример

require 'fiddle'
require 'fiddle/import'

module LibSum
  extend Fiddle::Importer
  dlload './libsum.so'
  extern 'double sum(double*, int)'
  extern 'double split(double)'
end

Атрибуты

type_alias[R]

Общедоступные методы экземпляра

[](name) Показать исходный код
# File ext/fiddle/lib/fiddle/import.rb, line 237
def [](name)
  @func_map[name]
end

Возвращает функцию, сопоставленную с name, которая была создана с помощью Fiddle::Importer.extern или Fiddle::Importer.bind.

bind(signature, *opts, &blk) Показать исходный код
# File ext/fiddle/lib/fiddle/import.rb, line 193
    def bind(signature, *opts, &blk)
      name, ctype, argtype = parse_signature(signature, type_alias)
      h = parse_bind_options(opts)
      case h[:callback_type]
      when :bind, nil
        f = bind_function(name, ctype, argtype, h[:call_type], &blk)
      else
        raise(RuntimeError, "unknown callback type: #{h[:callback_type]}")
      end
      @func_map[name] = f
      #define_method(name){|*args,&block| f.call(*args,&block)}
      begin
        /^(.+?):(\d+)/ =~ caller.first
        file, line = $1, $2.to_i
      rescue
        file, line = __FILE__, __LINE__+3
      end
      module_eval(<<-EOS, file, line)
        def #{name}(*args,&block)
          @func_map['#{name}'].call(*args,&block)
        end
      EOS
      module_function(name)
      f
    end

Создает глобальный метод из данной C signature с использованием указанных opts в качестве параметров привязки с заданным блоком.

bind_function(name, ctype, argtype, call_type = nil, &block) Показать исходный код
# File ext/fiddle/lib/fiddle/import.rb, line 313
def bind_function(name, ctype, argtype, call_type = nil, &block)
  abi = CALL_TYPE_TO_ABI[call_type]
  closure = Class.new(Fiddle::Closure) {
    define_method(:call, block)
  }.new(ctype, argtype, abi)

  Function.new(closure, argtype, ctype, abi, name: name)
end

Возвращает новый оберточный замыкание для функции name.

  • ctype — это тип возвращаемого значения функции.

  • argtype — это Array аргументов, передаваемых в функцию обратного вызова.

  • call_type — это abi замыкания.

  • block передаётся в функцию обратного вызова.

См. Fiddle::Closure.

create_value(ty, val=nil) Показать исходный код
# File ext/fiddle/lib/fiddle/import.rb, line 244
def create_value(ty, val=nil)
  s = struct([ty + " value"])
  ptr = s.malloc()
  if( val )
    ptr.value = val
  end
  return ptr
end

Создает класс для обертки структуры C со значением ty.

См. также Fiddle::Importer.struct.

Также алиасируется как: value
dlload(*libs) Показать исходный код
# File ext/fiddle/lib/fiddle/import.rb, line 76
def dlload(*libs)
  handles = libs.collect{|lib|
    case lib
    when nil
      nil
    when Handle
      lib
    when Importer
      lib.handlers
    else
      Fiddle.dlopen(lib)
    end
  }.flatten()
  @handler = CompositeHandler.new(handles)
  @func_map = {}
  @type_alias = {}
end

Создаёт массив обработчиков для заданных libs, может быть экземпляром Fiddle::Handle, Fiddle::Importer, или создаст новый экземпляр Fiddle::Handle с использованием Fiddle.dlopen.

Вызывает исключение DLError, если библиотека не может быть загружена.

См. Fiddle.dlopen.

extern(signature, *opts) Показать исходный код
# File ext/fiddle/lib/fiddle/import.rb, line 169
    def extern(signature, *opts)
      symname, ctype, argtype = parse_signature(signature, type_alias)
      opt = parse_bind_options(opts)
      f = import_function(symname, ctype, argtype, opt[:call_type])
      name = symname.gsub(/@.+/,'')
      @func_map[name] = f
      # define_method(name){|*args,&block| f.call(*args,&block)}
      begin
        /^(.+?):(\d+)/ =~ caller.first
        file, line = $1, $2.to_i
      rescue
        file, line = __FILE__, __LINE__+3
      end
      module_eval(<<-EOS, file, line)
        def #{name}(*args, &block)
          @func_map['#{name}'].call(*args,&block)
        end
      EOS
      module_function(name)
      f
    end

Создаёт глобальный метод из данной C signature.

handler() Показать исходный код
# File ext/fiddle/lib/fiddle/import.rb, line 266
def handler
  (@handler ||= nil) or raise "call dlload before importing symbols and functions"
end

Экземпляр Fiddle::CompositeHandler.

Вызовет ошибку, если нет открытых обработчиков.

import_function(name, ctype, argtype, call_type = nil) Показать исходный код
# File ext/fiddle/lib/fiddle/import.rb, line 296
def import_function(name, ctype, argtype, call_type = nil)
  addr = handler.sym(name)
  if( !addr )
    raise(DLError, "cannot find the function: #{name}()")
  end
  Function.new(addr, argtype, ctype, CALL_TYPE_TO_ABI[call_type],
               name: name)
end

Возвращает новый экземпляр Fiddle::Function по адресу указанной функции name.

Вызывает исключение DLError, если функция name не существует.

  • argtype — это Array аргументов, передаваемых в функцию name.

  • ctype — это тип возвращаемого значения функции.

  • call_type — это ABI функции.

См. также Fiddle:Function.new

См. Fiddle::CompositeHandler.sym и Fiddle::Handler.sym

import_symbol(name) Показать исходный код
# File ext/fiddle/lib/fiddle/import.rb, line 276
def import_symbol(name)
  addr = handler.sym(name)
  if( !addr )
    raise(DLError, "cannot find the symbol: #{name}")
  end
  Pointer.new(addr)
end

Возвращает новый экземпляр Fiddle::Pointer по адресу заданного name символа.

Вызывает исключение DLError, если символ name не существует.

См. Fiddle::CompositeHandler.sym и Fiddle::Handle.sym.

import_value(ty, addr) Показать исходный код
# File ext/fiddle/lib/fiddle/import.rb, line 256
def import_value(ty, addr)
  s = struct([ty + " value"])
  ptr = s.new(addr)
  return ptr
end

Возвращает новый экземпляр структуры C со значением ty по адресу addr.

sizeof(ty) Показать исходный код
# File ext/fiddle/lib/fiddle/import.rb, line 101
def sizeof(ty)
  case ty
  when String
    ty = parse_ctype(ty, type_alias).abs()
    case ty
    when TYPE_CHAR
      return SIZEOF_CHAR
    when TYPE_SHORT
      return SIZEOF_SHORT
    when TYPE_INT
      return SIZEOF_INT
    when TYPE_LONG
      return SIZEOF_LONG
    when TYPE_FLOAT
      return SIZEOF_FLOAT
    when TYPE_DOUBLE
      return SIZEOF_DOUBLE
    when TYPE_VOIDP
      return SIZEOF_VOIDP
    when TYPE_CONST_STRING
      return SIZEOF_CONST_STRING
    when TYPE_BOOL
      return SIZEOF_BOOL
    else
      if defined?(TYPE_LONG_LONG) and
        ty == TYPE_LONG_LONG
        return SIZEOF_LONG_LONG
      else
        raise(DLError, "unknown type: #{ty}")
      end
    end
  when Class
    if( ty.instance_methods().include?(:to_ptr) )
      return ty.size()
    end
  end
  return Pointer[ty].size()
end

Возвращает размер ty, используя Fiddle::Importer.parse_ctype для определения типа C и соответствующей константы Fiddle.

struct(signature) Показать исходный код
# File ext/fiddle/lib/fiddle/import.rb, line 222
def struct(signature)
  tys, mems = parse_struct_signature(signature, type_alias)
  Fiddle::CStructBuilder.create(CStruct, tys, mems)
end

Создаёт класс для обертки структуры C, описанной в signature.

MyStruct = struct ['int i', 'char c']
typealias(alias_type, orig_type) Показать исходный код
# File ext/fiddle/lib/fiddle/import.rb, line 95
def typealias(alias_type, orig_type)
  @type_alias[alias_type] = orig_type
end

Устанавливает псевдоним типа для alias_type как orig_type.

union(signature) Показать исходный код
# File ext/fiddle/lib/fiddle/import.rb, line 230
def union(signature)
  tys, mems = parse_struct_signature(signature, type_alias)
  Fiddle::CStructBuilder.create(CUnion, tys, mems)
end

Создаёт класс для обертки объединения C, описанного в signature.

MyUnion = union ['int i', 'char c']
value(ty, val=nil)
Псевдоним для: create_value

Закрытые методы экземпляра

parse_bind_options(opts) Показать исходный код
# File ext/fiddle/lib/fiddle/import.rb, line 140
def parse_bind_options(opts)
  h = {}
  while( opt = opts.shift() )
    case opt
    when :stdcall, :cdecl
      h[:call_type] = opt
    when :carried, :temp, :temporal, :bind
      h[:callback_type] = opt
      h[:carrier] = opts.shift()
    else
      h[opt] = true
    end
  end
  h
end

Ruby Core © 1993–2022 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API